編程遊戲是一種遊戲類型,玩家不是直接玩遊戲,而是編寫機器人程序來自主玩遊戲。我已經創建了一個Zombie Dice模擬器,允許程式設計師練習他們的技能,同時玩得開心玩遊戲AI。Zombie Dice機器人可以簡單或非常複雜,非常適合課堂練習或個人編程挑戰。
如何玩殭屍骰子
Zombie Dice是有趣的骰子遊戲。玩家是殭屍,試圖吃儘可能多的人類大腦,而不是「槍擊」。他們的臉上有一杯13個骰子,上面有大腦,腳步聲和霰彈槍的圖標。骰子是綠色(大腦更有可能),紅色(霰彈槍更可能)和黃色(在大腦和霰彈槍之間均勻分開)。
輪到他們了:
玩家隨機從杯子中掏出骰子,直到他們手中有三個骰子並滾動它們。玩家總是擲三個骰子。他們拋開任何大腦(人類大腦被吃掉)和霰彈槍(反擊的人)。如果玩家在本回合中留出了三支霰彈槍,他們的回合以零點結束。如果他們決定再次擲骰子,那麼玩家會手上拿著任何骰子。否則,玩家可以選擇結束他們的回合,他們將在每個大腦中收集一個點並將所有骰子返回到下一個玩家的杯子。或者玩家可以選擇繼續轉彎並再次滾動。回到第1步,注意到任何已經出現的骰子都會被重複使用。殭屍骰子有一個「推動你的運氣」遊戲機制:你重新擲骰子越多,你可以獲得的大腦越多,但你最有可能累積三支霰彈槍而失去一切。一旦玩家達到13分,其餘玩家再轉一圈(可能會趕上)並且遊戲結束。得分最高的玩家獲勝。
Bot編程挑戰
要使用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()像你想要擲骰子一樣經常調用這個函數(當然,你應該在輪到你時至少調用它一次)。類超出了本文的範圍,但您只需更改myzombie.py中的turn()代碼即可:
import zombiediceclass 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 < 2: diceRollResults = zombiedice.roll() # roll again else: breakclass AlwaysRollsTwicePerTurn: def __init__(self, name): self.name = name def turn(self, gameState): zombiedice.roll() zombiedice.roll()zombies = ( zombiedice.examples.RandomCoinFlipZombie(name='Random'), zombiedice.examples.RollsUntilInTheLeadZombie(name='Until Leading'), zombiedice.examples.MinNumShotgunsThenStopsZombie(name='Stop at 2 Shotguns', minShotguns=2), zombiedice.examples.MinNumShotgunsThenStopsZombie(name='Stop at 1 Shotgun', minShotguns=1), MyZombie(name='My Zombie Bot'), AlwaysRollsTwicePerTurn(name='Rolls Twice'), # Add any other zombie players here.)# Uncomment one of the following lines to run in CLI or Web GUI mode:#zombiedice.runTournament(zombies=zombies, numGames=1000)zombiedice.runWebGui(zombies=zombies, numGames=1000)
MyZombie類的turn()方法中的代碼一直在調用,zombiedice.roll()直到它至少滾動了兩個大腦。第二個機器人在AlwaysRollsTwicePerTurn類中實現,它有一個turn()方法,每次轉動只需擲骰子兩次。運行此程序會調用runWebGui()並打開Web瀏覽器,如圖6-1所示,準備運行模擬。您可以檢查zombiedice包的examples.py文件中的原始碼,以了解其他bot如何工作。
嘗試編寫一些自己的機器人來玩Zombie Dice,看看他們如何與其他機器人進行比較。如果你發現自己在現實世界中玩這個遊戲,你將獲得成千上萬的模擬遊戲的好處,告訴你最好的策略之一就是在你擲出兩支霰彈槍後停下來。但你總是可以試試你的運氣......
一步一步構建MyZombie
我將MyZombie在上一節中描述創建類的過程。從這個導入zombiedice模塊的基本模板開始,使用turn()調用方法創建一個類zombiedice.roll(),然後運行錦標賽:
import zombiediceclass 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() 大腦= 0 而diceRollResults不是None: diceRollResults = zombiedice.roll()
現在代碼將繼續滾動骰子直到它返回None。但就在那時,我們已經達到了三支霰彈槍而失去了轉彎。我們需要添加邏輯,以便在某些時候方法在zombiedice.roll()開始返回之前返回None。讓我們diceRollResults來看看有多少腦子被捲起來:
def turn(self, gameState): diceRollResults = zombiedice.roll() brains = 0 while diceRollResults is not None: diceRollResults = zombiedice.roll()
那更好,現在zombiedice.roll()只要我們在輪到我們還沒有達到兩個大腦滾動時就被調用。但是,這種方法沒有變化的條件。它只是永遠循環!讓我們添加更多代碼:
def turn(self, gameState): diceRollResults = zombiedice.roll() brains = 0 while diceRollResults is not None: brains += diceRollResults['brains'] if brains < 2: diceRollResults = zombiedice.roll()
這個新代碼說如果我們至少推出了兩個大腦,那麼繼續前進並突破循環並最終從方法返回,這告訴模擬器機器人完成了它。
為gameState參數傳遞的值是具有以下鍵的字典:
'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文件,以獲取已經創建的一些機器人的代碼。然後將它們加載到模擬器中,看看它們的表現如何!