在繼續我們的AI之旅前,分享一個在煎蛋上看到的有趣新聞,能通過讀說明書來學習的AI,這個世界真是變得越來越不可琢磨啦!機器人很快就要超越我們了……
因為這一次是接著上面的內容的,所以請不要跳過直接看這裡。
哭!!!寫完了上傳出錯,丟失啊,重傷重寫~~~~~~~~~~~
螞蟻例項類
在我們正式建造大腦之前,我們得先做一個螞蟻類出來,就是下面的這個,從GameEntity繼承而來:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class Ant(GameEntity): def __init__(self, world, image): # 執行基類構造方法 GameEntity.__init__(self, world, "ant", image) # 建立各種狀態 exploring_state = AntStateExploring(self) seeking_state = AntStateSeeking(self) delivering_state = AntStateDelivering(self) hunting_state = AntStateHunting(self) self.brain.add_state(exploring_state) self.brain.add_state(seeking_state) self.brain.add_state(delivering_state) self.brain.add_state(hunting_state) self.carry_image = None def carry(self, image): self.carry_image = image def drop(self, surface): # 放下carry影象 if self.carry_image: x, y = self.location w, h = self.carry_image.get_size() surface.blit(self.carry_image, (x-w, y-h/2)) self.carry_image = None def render(self, surface): # 先呼叫基類的render方法 GameEntity.render(self, surface) # 額外繪製carry_image if self.carry_image: x, y = self.location w, h = self.carry_image.get_size() surface.blit(self.carry_image, (x-w, y-h/2)) |
這個Ant類先呼叫了父類的 __init__ ,都是Python基礎不多說了。下面的程式碼就是一些狀態機程式碼了,對了還有一個carry_image變數,保持了現在螞蟻正在搬運物體的影象,或許是一片樹葉,或許是一隻死蜘蛛。這裡我們寫了一個加強的render函式,因為我們可能還需要畫一下搬的東西。
建造大腦
我們給每一隻螞蟻賦予四個狀態,這樣才能足夠建造我們的螞蟻的狀態機。在建造狀態機之前,我們得先把這些狀態的詳細資訊列出來。
狀態 | 動作 |
---|---|
探索(Exploring) | 隨機的走向一個點 |
蒐集(Seeking) | 向一篇樹葉前進 |
搬運(Dellivering) | 搬運一個什麼回去 |
狩獵(Hunting) | 攻擊一隻蜘蛛 |
我們也需要定義一下各個狀態之間的連結,或者可以叫轉移條件。這裡舉兩個例子(實際上不止):
條件 | 轉移狀態 |
---|---|
發現樹葉 | 蒐集 |
有蜘蛛攻擊 | 狩獵 |
我們還是最終畫一張圖來表示整個狀態機:
高水平的你也許可以看著上面的圖寫狀態機了,不過為了方便先建立一個State類,來儲存一個狀態。很簡單,只是一個框子,實際上什麼都不做:
1 2 3 4 5 6 7 8 9 10 11 |
class State(): def __init__(self, name): self.name = name def do_actions(self): pass def check_conditions(self): pass def entry_actions(self): pass def exit_actions(self): pass |
然後可以建立一個狀態機類來管理這些狀態,這個狀態機可是整個程式碼的核心類。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class StateMachine(): def __init__(self): self.states = {} # 儲存狀態 self.active_state = None # 當前有效狀態 def add_state(self, state): # 增加狀態 self.states[state.name] = state def think(self): if self.active_state is None: return # 執行有效狀態的動作,並做轉移檢查 self.active_state.do_actions() new_state_name = self.active_state.check_conditions() if new_state_name is not None: self.set_state(new_state_name) def set_state(self, new_state_name): # 更改狀態,執行進入/退出動作 if self.active_state is not None: self.active_state.exit_actions() self.active_state = self.states[new_state_name] self.active_state.entry_actions() |
然後就可以通過繼承State建立一系列的實際狀態了,這些狀態傳遞給StateMachine保留並執行。StateMachine類的think方法是檢查當前有效狀態並執行其動作的,最後還可能會呼叫set_state來進入下一個狀態。
我們應該根據上面的四個狀態表格建立狀態了,有鑑於本次的程式碼已經很多了,需要好好消化…… 下一次將會一次性給出完整程式碼,到時候就能看到一個豐富多彩的昆蟲世界了!盡請期待~