我正在尝试在游戏中实施GOAP。该游戏是一种模拟类型的游戏,不仅会从GOAP中受益,而且从本质上来说,它是基于代理可以执行的操作范围的要求。
我有以下代码。这里没有计划者,只有动作,状态等的定义
#include <vector>
#include <string>
#include <unordered_map>
class Condition
{
public:
bool operator()(const int value) const
{
return m_min <= value && value <= m_max;
}
enum class OP : std::uint8_t
{
EE, LT, GT, LE, GE
};
Condition(const int min, const int max, const OP op)
:
m_op(op),
m_min(min),
m_max(max)
{}
static Condition CreateEE(const int goal)
{
return Condition(goal, goal, OP::EE);
}
static Condition CreateGT(const int goal)
{
return Condition(goal+1, std::numeric_limits<int>::max(), OP::GT);
}
static Condition CreateLT(const int goal)
{
return Condition(std::numeric_limits<int>::min(), goal-1, OP::LT);
}
static Condition CreateGE(const int goal)
{
return Condition(goal, std::numeric_limits<int>::max(), OP::GT);
}
static Condition CreateLE(const int goal)
{
return Condition(std::numeric_limits<int>::min(), goal, OP::LT);
}
private:
OP m_op;
int m_min;
int m_max;
};
class Effect
{
public:
enum class OP : std::uint8_t
{
ADD, SUB, MUL, DIV, EQ
};
Effect(OP op, int value)
:
m_op(op),
m_value(value)
{
}
protected:
OP m_op;
int m_value;
};
class Action
{
public:
void AddPrereq(const std::string& name, Condition value)
{
m_prereqs.emplace_back(name,value);
}
void AddEffect(const std::string& name, Effect effect)
{
m_effects.emplace_back(name,effect);
}
void SetCost(const float cost)
{
m_cost = cost;
}
private:
float m_cost;
std::vector<std::pair<std::string,Condition>> m_prereqs;
std::vector<std::pair<std::string,Effect>> m_effects;
};
class WorldState
{
public:
void AddFact(const std::string& name, const int value)
{
m_facts[name] = value;
}
private:
std::unordered_map<std::string,int> m_facts;
};
class GoalState
{
public:
void AddCondition(const std::string& name, const Condition condition)
{
m_conditions.emplace_back(name, condition);
}
private:
std::vector<std::pair<std::string,Condition>> m_conditions;
};
int main()
{
Action goTo;
goTo.AddEffect("isAtPosition", Effect(Effect::OP::EQ, 1));
Action pickUp;
pickUp.AddPrereq("isAtPosition", Condition::CreateEE(1));
pickUp.AddEffect("itemInPossession", Effect(Effect::OP::EQ, 1));
Action drop;
drop.AddPrereq("itemInPossession", Condition::CreateEE(1));
drop.AddEffect("itemAtPosition", Effect(Effect::OP::EQ, 1));
WorldState ws;
ws.AddFact("itemAtPosition", 0);
GoalState gs;
gs.AddCondition("itemAtPosition", Condition::CreateGE(1));
return 0;
}
目前,我仅使用布尔值,因为对于我的测试用例,它是关于代理移动到某个位置,拾取一个项目并将其移动到另一个位置。稍后,目标可能是移动n个项目或其他内容。
动作将是:
但是我如何在这里两次使用Goto
操作?设置“ isAtPosition”变量的效果是相同的。我需要为“ isAtItemPosition”和“ isAtDestinationPosition”创建一个新的状态变量吗?
因为似乎我将为每个可能的目标有效地制定特定的行动,而我的效果是确定所有可能的行动顺序。
如何编码状态信息,以便可以将池中的相同操作应用于不同的阶段,从而产生不同的效果? (转到项目位置与转到目标位置)。