简单的AI实现

j2me人工智能入门  
  int patterns[NUM_PATTERNS][MAX_PATTERNS_ELEMENTS]
    = { 1, 1, 2, 2, 0, 3, 4, 4, -1,
      2, 2, 1, 1, 4, 4, 4, 1, -1,
      0, 0, 0, 4, 4, 4, 1, 1, -1,
      2, 2, 2, 2, 1, 3, 3, 4, -1};
  正如你所看到,共有四个模式。每个模式最多包含5条指令。这些指令被转换成方向,然后被转换成实际的速率向量控制外来的机器人,这种模式使用可如图4-1所示。

 在为“小蜜蜂”提供的模式装置中,笔者使用了在屏幕上移动机器人的模式。该程序读入表,然后基于当前表中的元素,向适当的方向移动机器人。模式装置可以理解6个值或指令。值1 — 4分别为方向,北(N),南(S),东(E),西(W)。0的意思是不动,-1的意思是模式结束。
  模式的使用不仅可以只连接移动。模式可用于选择动作、随机数等等。例如,可以使用一个模式作为随机数生成器的根源,以便于时间向前流动的时候,生成的随机数基于一个不同根值的模式。这会获得改变数的概率分布的效果,近而改变使用随机数的任何系统的行为。对于我们所制作的游戏大脑而言,我们使用模式仅作为移动顺序。然而,你们可使用它们提供任何你们希望的东西。
———————————————————————–  
跟综及逃避

  为了便于分析,我们可以使用一个游戏者和一个游戏对象或是游戏者对象的模型。问题是我们想使游戏者对手跟踪和追逐游戏者的角色。游戏者对手和游戏者的角色都有一个对坐标,指出它们各处于游戏中的什么位置,如图2.1所示。

 跟踪算法2.1
  取得 (Px, Py) – 玩家角色的位置
     (Cx, Cy) – 对手的位置
  begin
   // Do x tracking
   if (Px > Cx) then Cx++;
   else if (Px < Cx) then Cx–;
   // Do y tracking
   if (Py > Cy) then Cy++;
   else if (Py < Cy) Cy–;
  end
  由于我们获得游戏者角色和游戏者对手的位置,就可以使用这一信息为游戏者计算一个方向,就是它怎样移动才能接近游戏者的角色。因此,游戏者对手看起来就好象正在追逐游戏者的角色。算法2.1使游戏者对手跟踪或攻击游戏者的角色。不管游戏者向那个方向移动它。
  就这里多:我们基于每一个坐标,向游戏者角色方向移动游戏者对手,如图2.2所示。

算法2.1有些残忍;它直到游戏者对手处于游戏者角色的正上方时才停下来。当然,这可能正是你们想要的东西。然而,这也许太具有侵略性了。它就像是一个颗跟踪导弹:它直到击中你才会停下来。要做出进一步改进,我们可以增加如下的逻辑前提:当什么东西追赶你们时,它肯定是先看到你们。换句话说,它肯定在一定范围之内。考虑这种情况时,我们可以使用一个能见半径。
  我们可以进行测试,看看游戏者对手是否处于游戏者角色的一定距离之内(其视觉范围还是感觉范围)。如果条件为真,我们则打开这个算法。否则,我们可使游戏者对手做其他的事情,而不是追逐游戏者的角色,因为它根本就是无法看见游戏者的角色。
2.2、逃避
  追逐的反意词为逃避。逃避的做法与追逐相同,只不过一切都被颠倒过来进行。如果游戏者对手在游戏者角色的右边,游戏者对手则继续向右移动,而不是向左移动(接近游戏者角色),如图2.3所示。

逃避算法2.2
  取得 (Px, Py) – 玩家角色的位置
     (Cx, Cy) – 对手的位置
  begin
   // Do x tracking
   if (Px > Cx) then Cx–;
   else if (Px < Cx) then Cx++;
   // Do y tracking
   if (Py > Cy) then Cy–;
   else if (Py < Cy) Cy++;

有限状态机
我们必须把一个类似存储器形式的东西有限状态机(Finite-State Machine)加入到我们的“大脑”中,以便系统可以从一种行为迁移至另一种行为,并且能够了解它正在执行的行为。图5-1显示了一个有限状态机。

有限状态机一般用于执行复杂逻辑的硬件设计中,有限状态机的概念在软件工程中也很有用。一个电脑游戏可有许多种操作模式 — 例如:初始化模式、正常模式及终止模式 — 有限状态机除了可以跟踪游戏的全部状态外,还可以跟踪这些模式。有限状态机还可以控制游戏中玩家的对手和游戏对象。例如,我们可以做一部跟踪玩家角色状态的有限状态机。角色可能有如下状态:  
状态0:活着  
状态1:奄奄一息  
状态2:死亡  
  基于这些状态,游戏中的控制逻辑可执行不同的事情。如果玩家角色处于状态0,逻辑将允许角色移动、开火等等。然而,如果角色处于1,游戏逻辑将显示死亡顺序,角色就不能再移动或开火了。最后,当状态切换到状态2时,游戏逻辑将仔细检查它使用什么样的顺序才能使玩家角色活过来。
  当然,还存在将玩家角色从一种状态向另一种状态迁移的逻辑。如果玩家角色处于状态0,进入状态1的唯一办法就是以某种方式被击中或其它。一旦玩家角色处于状态1,一段时间后,角色会自动进入状态2,因此,我们明白了状态变化就是游戏环境 — 输入和有限状态机自身的结果,意思是说下一状态在某种方式上基于当前的状态。请参考图5-2所示。

上面我们讲的例子是为了游戏对象所提供的一个有限状态机比较典型的例子。总之,一个游戏对象可能有很多的状态,复杂的规则控制状态变化,这些状态变化我们称为状态迁移。另外,一个状态可以有输出。例如:在我们的状态模型的实例中,死亡状态可能有一个输出,用信号通知声音系统播放一次惨叫声。
  通过上面的阐述,我们已经知道什么是有限状态机了,但是我们如何在计算机中制作它呢?下面我们就以一个精灵活动状态为例写出伪代码:
我们可以定义一些变量跟踪状态  
基于每种状态和可能的输入制定规则  
  // 定义状态
  #define STATE_CHASE  1  // 追逐
  #define STATE_RANDOM  2  // 随机
  #define STATE_EVADE  3  // 逃避
  #define STATE_PATTERN 4  // 模式
  // 赋予精灵STATE_CHASE状态
  int sprite_state = STATE_CHASE;
  // 进入游戏主循环
  while(!done)
  {
    …
    switch(sprite_state)
    {
      case STATE_CHASE:
      {
        // 追逐状态的控制逻辑
      }break;
      case STATE_RANDOM:
      {
        // 随机状态的控制逻辑
      }break;
      case STATE_EVADE:
      {
        // 逃避状态的控制逻辑
      }break;
      case STATE_PATTERN:
      {
        // 模式状态的控制逻辑
      }break;
    default:break;
    } // end switch sprite_state
  请记住上面这个简单的AI模型吧,以后也许你会用到。还有一点可以加到有限状态机中:占先状态控制。这就是在基于某些变量或函数在状态完全没有“成熟” 之前便改变状态。在上面的伪代码中,每个状态都要执行完成为止。我们可以把条件增加为:如果在状态的执行中足够的因素得到了满足,有限状态机就会“跳出” 这个状态。
  小结:设计有限状态机时,一定要仔细考虑出全部状态和状态迁移规则,避免在两个间出现周而复始的“无限循环”。