编写机器人来玩僵尸骰子

注意:我正在寻找有关我的 Zombie Dice 模拟器以及这组说明的反馈。 如果有任何您觉得可以改进的部分,请给我发电子邮件至 [email protected].

编程游戏是一种游戏类型,玩家不是直接玩游戏,而是编写机器人程序来自主玩游戏。 我创建了一个 Zombie Dice 模拟器,允许程序员练习他们的技能,同时享受制作游戏 AI 的乐趣。 Zombie Dice 机器人可以很简单,也可以非常复杂,非常适合课堂练习或个人编程挑战。

如何玩僵尸骰子

Zombie Dice 是一款来自 Steve Jackson Games 的快速有趣的骰子游戏。 玩家是僵尸,他们试图尽可能多地吃掉人脑而不被“霰弹枪”。 杯子里有 13 个骰子,上面有大脑、脚步和霰弹枪的图标。 骰子颜色为绿色(大脑更有可能)、红色(猎枪更有可能)和黄色(大脑和猎枪之间平均分配)。

轮到他们了:

    玩家随机从杯子中取出骰子,直到手中有三个,然后掷骰子。 玩家总是恰好掷出三个骰子。 他们搁置了任何大脑(大脑被吃掉的人)和猎枪(反击的人)。 如果玩家在本回合中放置了三支霰弹枪,则他们的回合以零分结束。 如果玩家决定再次掷骰子,则将所有出现脚步声的骰子保留在手中。 否则,玩家可以选择结束他们的回合,他们将在每个大脑中收集一分,并将所有骰子归还给下一个玩家的杯子。 或者玩家可以选择继续他们的回合并再次滚动。 回到第 1 步,注意手中已经出现的任何骰子都将被重复使用。

Zombie Dice 有一个“推动你的运气”游戏机制:你重新掷骰子的次数越多,你得到的脑子就越多,但你最终获得三把霰弹枪并失去一切的可能性就越大。 一旦一名玩家达到 13 分,其余玩家将再轮一次(可能赶上),游戏结束。 得分最多的玩家获胜。

Zombie Dice 更完整的规则可以在这里找到:

    英文版规则的 PDF 动画 Flash 演示如何使用规则播放 Instructables 文章 某人解释规则的 YouTube 视频

机器人编程挑战

要使用 pip 安装模拟器,请运行 pip install zombiedice (在 Windows 上)或 pip3 install zombiedice (在 macOS 和 Linux 上)。 要使用一些预制机器人运行演示,请运行 python -m zombiedice (在 Windows 上)或 python3 -m zombiedice (在 macOS 和 Linux 上)查看模拟器的 web gui 示例:

该模拟器可以快速运行数百场比赛,记录每个机器人获得了多少胜利和平局。

您将通过编写一个类来创建机器人 turn() 方法,轮到您的机器人时由模拟器调用。 这里面 turn() 方法,你会调用 zombiedice.roll() 想掷骰子就调用多少次(当然,轮到你时至少应该调用一次)。 类超出了本文的范围,但您可以简单地更改 turn() myzombie.py 中的代码:

import zombiedice

class MyZombie:
    def __init__(self, name):
        self.name = name

    def turn(self, gameState):
        # gameState is a dict with info about the current state of the game.
        # You can choose to ignore it in your code.

        diceRollResults = zombiedice.roll() # first roll
        # roll() returns a dictionary with keys 'brains', 'shotgun', and
        # 'footsteps' with how many rolls of each type there were.
        # The 'rolls' key is a list of (color, icon) tuples with the
        # exact roll result information.
        # Example of a roll() return value:
        # {'brains': 1, 'footsteps': 1, 'shotgun': 1,
        #  'rolls': [('yellow', 'brains'), ('red', 'footsteps'),
        #            ('green', 'shotgun')]}

        # The code logic for your zombie goes here:
        brains = 0
        while diceRollResults is not None:
            brains += diceRollResults['brains']

            if brains 

The code in the MyZombie class's turn() method keeps calling zombiedice.roll() until it has rolled at least two brains. A second bot is implemented in the AlwaysRollsTwicePerTurn class, which has a turn() method that simply rolls the dice twice on every turn. Running this program calls runWebGui() and brings up the web browser as shown in Figure 6-1, ready to run the simulation. You can examine the source code in the zombiedice package's examples.py file to see how the other bots work.

Try writing some of your own bots to play Zombie Dice, and see how they compare against the other bots. And if you find yourself playing this game in the real world, you'll have the benefit of thousands of simulated games telling you that one of the best strategies is to simply stop once you've rolled two shotguns. But you could always try pressing your luck...

Constructing MyZombie, Step by Step

I'll describe the though process of creating the MyZombie class in the previous section. Start with this basic template that imports the zombiedice module, creates a class with a turn() method that calls zombiedice.roll(), and then runs a tournament:

import zombiedice

class MyZombie:
    def __init__(self, name):
        self.name = name

    def turn(self, gameState):
        zombiedice.roll()

zombies = (
    zombiedice.examples.RandomCoinFlipZombie(name="Random"),
    MyZombie(name="My Zombie Bot"),
)

# Uncomment one of the following lines to run in CLI or Web GUI mode:
zombiedice.runWebGui(zombies=zombies, numGames=1000)

MyZombie 到目前为止只掷一次骰子,这是一种非常保守的策略,不太可能得到很多分数。 要决定它是否应该再次滚动,我们需要检查的返回值 zombiedice.roll(),这是一本显示三个骰子掷骰结果的字典。 它看起来像这样:

{'brains': 1, 'footsteps': 1, 'shotgun': 1,
 'rolls': [('yellow', 'brains'), ('red', 'footsteps'),
           ('green', 'shotgun')]}

这本字典有一个 'brains', 'footsteps', 和 'shotgun' 键值是那种卷的数量。 确切的卷在 'rolls' 键的值:元组列表。 每个元组代表一个骰子,由颜色和出现的图标组成。

假设我们要编写策略,让我们的僵尸继续滚动,直到它至少滚动了两个大脑。 我们需要跟踪到目前为止在这一回合中已经滚动了多少大脑(在 brains 变量),开始于 0. 如果将来打电话给 zombiedice.roll() 永远回归 None,那么我们就知道在这个回合中我们已经达到或超过了三把霰弹枪,并且会得到零分。 更新 turn() 所以它看起来像这样:

    def turn(self, gameState):
        diceRollResults = zombiedice.roll()
        brains = 0
        while diceRollResults is not None:
            diceRollResults = zombiedice.roll()

现在代码将继续掷骰子直到它返回 None. 但在那个时候,我们已经达到了三把霰弹枪并且失去了转弯。 我们需要添加逻辑,以便在某个时候该方法返回之前 zombiedice.roll() 开始返回 None. 让我们检查一下 diceRollResults 看看有多少大脑被滚动:

    def turn(self, gameState):
        diceRollResults = zombiedice.roll()
        brains = 0
        while diceRollResults is not None:
            brains += diceRollResults['brains']

            if brains 

That's better, now zombiedice.roll() is only called as long as we've yet to reach two brain rolls on our turn. However, there's no condition where this method changes. It'd just loop forever! Let's add a bit more code:

    def turn(self, gameState):
        diceRollResults = zombiedice.roll()
        brains = 0
        while diceRollResults is not None:
            brains += diceRollResults['brains']

            if brains 

This new code says that if we've rolled at least two brains, go ahead and break out of the loop and eventually return from the method, which tells the simulator that the bot is done with its turn.

The value passed for the gameState parameter is a dictionary with the following keys:

    'CURRENT_ZOMBIE' – 当前轮到它的僵尸字符串
    'CURRENT_CUP' – 杯子中的骰子串列表(即“红色”、“黄色”、“绿色”)
    'CURRENT_HAND' – 正在滚动的骰子列表(应始终为三个)
    'SHOTGUNS_ROLLED' – 本回合到目前为止的霰弹枪数量
    'BRAINS_ROLLED' – 本回合到目前为止的大脑数量
    'ROLLED_BRAINS_DETAILS' – 每个大脑掷出的骰子串列表,在我们用完大脑骰子的罕见情况下使用
    'TURN_START_TIME' – 从当前回合开始的 unix 纪元开始的时间

其他机器人的想法

Zombie Dice 中有很多策略可供您尝试。 尝试编写执行以下操作的机器人:

    有 50% 机会选择重新滚动的机器人。 看看这个机器人与一个有 25% 或 75% 机会重新滚动的机器人相比如何。 一个机器人在到达两把霰弹枪时停止重新滚动。 一个机器人在到达两把霰弹枪时停止重新滚动,除非它不在领先位置。 (检查 gameState 字典来查找此信息。)只要杯子中还剩下绿色骰子,它就会滚动的机器人。 (检查 gameState 字典来查找此信息。)

请务必检查模块中的 examples.py 文件,以获取一些已经创建的机器人的代码。 然后将它们加载到模拟器中,看看它们的表现如何!

阅读更多

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注