c+中基于大决策树的人工智能设计模式+; 我目前正在编写一个用C++编写的游戏的人工智能。人工智能在概念上相当简单,它只是运行在决策树中并选择适当的操作。以前我使用Prolog作为决策引擎,但是由于其他开发人员使用C++和集成Prolog代码的一些问题,我现在尝试将其移植到C++。
目前,我在prolog(100+)中有一系列事实和规则。很多东西都是以形式表达的,如果游戏状态是,那么就做动作xyz。大多数规则都相当简单,有些规则相当复杂。我研究了一种有限状态机方法,但它似乎不能很好地适应更大的情况。 我第一次尝试在C++中编码这是一个巨大的噩梦。我到处都能看到这样的代码:c+中基于大决策树的人工智能设计模式+; 我目前正在编写一个用C++编写的游戏的人工智能。人工智能在概念上相当简单,它只是运行在决策树中并选择适当的操作。以前我使用Prolog作为决策引擎,但是由于其他开发人员使用C++和集成Prolog代码的一些问题,我现在尝试将其移植到C++。,c++,design-patterns,rule-engine,C++,Design Patterns,Rule Engine,目前,我在prolog(100+)中有一系列事实和规则。很多东西都是以形式表达的,如果游戏状态是,那么就做动作xyz。大多数规则都相当简单,有些规则相当复杂。我研究了一种有限状态机方法,但它似乎不能很好地适应更大的情况。 我第一次尝试在C++中编码这是一个巨大的噩梦。我到处都能看到这样的代码: if( this->current_game_state->some_condition == true ){ if( this->current_game_st
if( this->current_game_state->some_condition == true ){
if( this->current_game_state->some_other_condition == false ){
//some code
}else{
return do_default_action();
}
}else if( this->current_game->another_condition ){
//more code
}
这种复杂性很快变得难以管理
是否有一个很好的方法来解决C++中的这类问题?有什么好的设计模式来处理这种情况吗?不需要逻辑包含在源中,它只需要从C++访问即可。唯一真正的要求是速度要相当快
我还研究了规则引擎,如果足够快,它们可能是合适的。你知道有没有一个开源的C++规则引擎是合适的?< p>我不明白为什么有限状态机对你的游戏来说不足够。这是做你想做的事情的常见方式。您可以使其成为数据驱动的,以使您的代码不受具体操作的影响。有限状态m。《游戏开发的人工智能》O'Reilly(David M.Bourg&Glenn Seemann)中也有描述
您可能希望将规则拆分为几个较小的规则集,以保持机器小且易于理解 代码就是数据,数据就是代码。你有工作代码——你只需要将它以一种可以编译的方式暴露给C++,然后你可以实现一个最小的解释器来评估它。 一种可能是采用Prolog规则,并以最直接的方式将它们转换为数据结构。也许你可以设计一个简单的表格,如:
struct {
State coming_from;
Event event;
void (*func)(some, args);
State going_to;
} rules[] = {
{ WANDERING_AROUND, HEAR_SOUND, look_around, ENEMY_SEEN },
{ ENEMY_SEEN, GUN_LOADED, fire_gun, SNEEK_AWAY },
{ next, rule, goes, here },
etc...
}
类似地,函数调用可以以类似于原始序言的方式填充数据结构:
void init_rules () {
rule("Parent", "Bill", "John");
rule("Parent", "Paul", "Bill");
// 99 more rules go here...
}
然后实现一个简单的解释器来遍历该数据结构并找到所需的答案。使用少于1000条规则,在搜索过程中使用蛮力的方法可能会足够快,但稍后你总是可以变得聪明,并且尝试在时间到来时以真正的Prolog环境做事情。 < P>如果你想把Prolog代码转换成C++代码, 看看Castor库(C++),它支持C++中的逻辑编程: 我自己还没有试过,所以我对它的性能一无所知
如果你想使用状态机,请看一下Boost.Meta-state-machine如何使用mercury?它基本上是为了与C代码接口而构建的。您可以使用多态性。调用一个虚拟函数实际上是一个由编译器为您完成和优化的大开关/案例
class GameState {
virtual void do_something() { std::cout << "GameState!"; }
// some functions
virtual ~GameState() {}
};
class SomeOtherState : public GameState {
// some other functions
virtual void do_something() { std::cout << "SomeOtherState!"; }
};
class MyFinalState : public GameState {
virtual void do_something() { std::cout << "MyOtherState!"; }
};
class StateMachine {
std::auto_ptr<GameState> curr_state;
public:
StateMachine()
: curr_state(NULL) {}
void DoSomething() { curr_state->DoSomething(); }
void SetState(GameState* ptr) { curr_state = ptr; }
template<typename T> void SetState() { curr_state = new T; }
};
int main() {
StateMachine sm;
sm.SetState(new SomeOtherState());
sm.SetState<SomeOtherState>();
sm.DoSomething(); // prints "SomeOtherState!"
sm.SetState<MyFinalState>();
sm.DoSomething(); // prints "MyFinalState!"
}
类游戏状态{
虚拟的void do_something(){std::cout试图将Prolog的表达能力与状态机相匹配就像试图用自行车跑过汽车
<> Paster可能是很好的方法。它非常轻量级,允许逻辑编程和C++的其他部分之间的平滑互操作。看一下上的教程视频,有没有特别的C++接口?水星也有很多麻烦,从源代码编译到接口。到C++是EZ游戏。但是,它是没有用的。你可以让编译器工作:p这是一个有限状态机,这正是他说的,他先尝试了,然后当面崩溃了。与其说有限状态机不是我想要的,不如说是有限状态机的简单实现太复杂,难以管理。这个建议似乎有助于管理c复杂度更好。如果我要采用这种方法,使用解释器似乎正是我所需要的。但是我仍然没有完全接受使用有限状态机方法。第一个块当然是状态机,但我的观点是,你可以将其实现为表驱动算法,而不是一堆嵌套的if-then-else或第二个块是用C++语法来显示DSL。这不仅仅是一个简单的状态机。你已经有了工作PROlog,所以我不想把它翻译成C++,我认为教C++如何解释你现有的代码/数据可能更简单更干净。也许你可以发布你的一个子集。规则/事实,以便我们能够更好地处理它,并给出一个合理的示例。boost::function是否是这里建议的使用函数指针的好替代方案?如果您的项目已经在使用boost,我认为无论采用哪种方式都是合理的。这似乎是减少大量函数指针使用的一个很好的方法我一定会记住未来的项目。