我们来创建一个机器人,以便与 CircleAI 和 RandomAI 战斗。第一步是制定一个策略。因为这是我们创建的第一个 Python Battle 机器人,所以我们最好从一个简单的策略开始。
1. 如果面对着一个敌人,那么我应该攻击它。
2. 如果面对着墙,则我应该转弯。
3. 否则,我继续向前走。
尽管这不是最高级的策略,但它可能刚好可以打败 CircleAI。如果它打不过,我们还可以再回来改进它。
第二步是开始编码机器人。创建一个新 Python 文件(我把它叫作 better_than_circleai.py),然后输入以下代码:
class AI: def __init__(self):pass def turn(self):pass
这是所有机器人都必须具备的基础代码。在游戏开始时创建机器人,此时 __init__
函数会被调用。turn
函数会在每一回合被调用,并决定机器人做什么。这个类必须叫作 AI,否则 Python Battle 游戏不知道你的 AI 代码在哪里。
编写机器人的下一步是添加能让机器人执行我们制定的策略的代码。你将使用以下函数来控制机器人的移动:
self.robot.lookInFront
self.robot.turnRight
self.robot.turnLeft
self.robot.goForth
self.robot.attack
这些函数需要采用 self.robot.xx
的形式调用,因为 self 指向 AI 对象本身,而不是 AI 控制的机器人。AI 对象是不会移动或者攻击的,它只负责告知机器人需要做什么,具体的移动和攻击是由机器人对象来执行的。
我们来编写 turn
方法。移除代码中的 pass
,添加下面的代码:
self.robot.goForth
如果你现在测试一下这个机器人,会看到每一回合它都会尝试向前移动。这会导致它很快撞到游戏边界处的“墙”。如果敌人挡住了它的路,则它只会停止移动而已。你可以使用 self.robot.lookInFront
来修复这个问题。如果在正前方有一个可以攻击的敌人,则这个函数返回 "bot"
。修改一下 turn
函数,像这样:
if self.robot.lookInFront == "bot": self.robot.attackelse: self.robot.goForth
现在,如果在你的机器人前方有敌人挡路,则机器人会攻击它。但是如果机器人撞“墙”了,则它会停下来。如果前方是“墙”,则 self.robot.lookInFront
会返回 "wall"
。将下面的代码加到 turn
函数中,放在 self.robot.attack
和 else
之间:
elif self.robot.lookInFront == "wall": self.robot.turnRight
现在,如果你运行代码,则机器人会开始转圈!当它撞到“墙”的时候会向右转,当它撞到下一堵“墙”时会再次向右转,一直这样运行下去。你更希望机器人在撞“墙”的时候能转身折返回去,而这需要两次右转才能完成。当机器人撞“墙”的时候,它需要右转一次,然后在一下回合中,再右转一次。也就是说,你需要机器人记住它现在是在做 U 型转身。你可以给 AI 设置一个新属性(变量)来记住它正在做什么。我们在 __init__
函数中添加一行代码:
self.currentlyDoing = "forward"
这将告诉机器人,当游戏开始时,它需要向前走。当机器人在做 U 型转身时,你可以将这个属性的值改为 "turnRight"
以便告知机器人它需要右转。修改之后的 turn
函数最终看起来像这样:
代码清单 26-1 完成的机器人 AI
class AI: def __init__(self):self.currentlyDoing = "forward" def turn(self):if self.robot.lookInFront == "bot": self.robot.attackelif self.robot.lookInFront == "wall": self.robot.turnRight self.currentlyDoing = "turnRight"elif self.currentlyDoing == "turnRight": self.robot.turnRight self.currentlyDoing = "forward"else: self.robot.goForth
如果你运行这段代码,可能会发现这个 AI 有一定的缺陷。我们来修改一下以便我们的机器人可以打败 CircleAI。