游戏人工智能

状态机

  状态机系统中的状态具有进入状态,离开状态,接受输入,进行转移等动作。
  根据“状态A->接收条件X->状态B”可以画出状态机图或是列成状态表。
  原理简单,但是随着设计的状态增加状态间的跳转关系增加,状态图越来越不直观,状态机编码和调试的难度也越来越大。

决策树

  决策树,顾名思义,主要目的是为了做决策。通过某种方式来让电脑找出自己该做什么事。所以名字中的“树”就是说明这个思考查找要做的事的方式。
  就好像我们有时想问题可能像是这个样子的(当时写文章的时候还在学校宿舍,精神状态也不佳,所以例子是这个样子的不要在意):

想问题的方式

想问题的方式

  注意到了么,我们可以把这种思考要做什么事的方式,组织成一个以“开始想问题”为根节点的树形结构。
  接下来我们就只要分析这棵树的节点有什么特点了。
  如果我们把思考问题的过程看成是遍历这棵树的过程,然后我们从根节点开始,遍历子节点1,2,3的时候,只要有满足条件的子节点就算遍历成功,否则继续遍历其它子节点。在决策树中我们就把这种节点叫做选择节点(Selector Node)。
  然后看a节点和b节点,看样子遍历到“有东西吃”的节点后,它的子节点“吃东西”如果遍历成功了,那就继续遍历“做事情”节点(意思是说吃东西成功才做事)。这个“有东西吃”节点我们说它具有序列节点(Sequence Node)的作用。
  用代码来描述选择节点和序列节点分别是这个意思:

class Node
{
public:
	void addChild(Node* node);
	/* 返回值为true表示这个节点遍历成功,false为失败 */
	virtual bool traverse() = 0;
protected:
	vector<Node*> _children;
};

class SelectorNode: public Node
{
public:
	virtual bool traverse()
	{
		for (Node* child : _children)
		{
			bool success = child->traverse();
			/* 一旦有成功就停止遍历,
			 否则继续遍历直到有节点成功 */
			if (success)
			{
				return true;
			}
		}
		return false;
	}
};

class SequenceNode
{
public:
	virtual bool traverse()
	{
		for (Node* child : _children)
		{
			bool success = child->traverse();
			/* 一旦有失败就停止遍历,
			 否则按顺序遍历所有子节点 */
			if (success = false)
			{
				return false;
			}
		}
		return true;
	}
};

  然后我们还可以从具体做什么事的角度找出两种类型的节点,它们是条件节点和动作节点。

class ConditionNodeA
{
public:
	virtual bool traverse()
	{
		if (某条件A成立)
		{
			return true;
		}
		return false;
	}
};

class ActionNodeA
{
public:
	virtual bool traverse()
	{
		if (某动作A执行成功)
		{
			return true;
		}
		return false;
	}
};

  有了这些基本节点我们就可以构建各种逻辑的决策树了,包括条件And和Or的逻辑。
  条件与这样组合(如果条件A和条件B成立就执行动作A):

条件与

条件与

  条件或这样组合(如果条件A或条件B成立就执行动作A):

条件或

条件或

  此外还可以扩展其它各种功能的节点,比如并发节点,它的子节点无论遍历结果成功与否都会被全部遍历;以随机的顺序访问子节点的选择节点;对子节点遍历结果取反的节点等等。

Dorothy构建AI的方法

  动物的行为有两种方式,条件反射与本能。其实我们会发现决策树执行的过程就是一个条件反射的过程,通过分析各种环境最终选择该做的动作。就如游戏中的角色在周围有敌人接近的时候会选择不同的技能主动打击敌人。而本能往往是与自身相关的某些状态变化而直接触发行动。比如游戏中的角色被敌人打到而产生硬直的动作就应该被视为一种本能。
  模拟这两种行为,使用决策树系统模拟条件反射当然是没问题了。而本能的模拟,我的方法是设定游戏角色自身的某项属性变化为触发本能的直接原因。比如,挨打时身体硬直和死亡都是由游戏角色自己生命值属性的变化而触发的。
  最后的问题是关于条件反射触发的时机,也就是什么时候执行一次决策树决策的过程。我定下的规则是:
  1.当角色刚创建时触发。
  2.当角色每停止一个动作时触发。
  3.当角色在执行有时间周期或是需要持续执行的动作时,根据做当前动作时设定的反应速度,以不同的周期间隔在做动作的过程中触发。

标题目录