天天看點

星際争霸傳統AI機器人源碼分析(2)——建造順序搜尋

星際争霸中,玩家需要按照合理的順序去建造單元,以盡快形成所需的戰鬥力。不過,找到最優的建造順序并不簡單,需要做權衡。例如,玩家可以先建造一些勞工,讓勞工去采集資源,勞工越多收集資源的速度就越快,進而盡快達成建造的條件,然而建造勞工也需要消耗時間,太多勞工也是浪費,是以需要找出一個合理的建造方法。

本文内容主要結合UAlbertaBot的代碼和相關的論文《Build-order Optimization in StarCraft》進行分析,論文位址如下:

https://www.aaai.org/ocs/index.php/AIIDE/AIIDE11/paper/viewFile/4078/4407

星際争霸傳統AI機器人源碼分析(2)——建造順序搜尋

星際争霸遊戲中,勞工在采集礦石

建造目标的産生

UAlbertaBot的政策管理器(StrategyManager)會根據目前局勢去選擇一種政策(具體方法後續再探讨,這裡先關注建設相關),每種政策包含該政策下需要有哪些單元。

例如,如果AI選擇神族(protoss),政策管理器有可能産生一個叫ZealotRush的政策,這個政策對應以下的建造目标,包含一些Probe(勞工)、Pylon(水晶塔)、Gateway(兵營)和Zealot(狂熱者,一種攻擊機關)。

["Probe", "Probe", "Probe", "Probe", "Pylon", "Probe", "Gateway", "Gateway", "Probe", "Probe", "Zealot", "Pylon", "Zealot", "Zealot", "Probe", "Zealot", "Zealot", "Probe", "Pylon", "Zealot", "Gateway", "Probe", "Pylon", "Probe", "Zealot", "Probe", "Zealot", "Zealot", "Zealot", "Zealot", "Pylon", "Probe", "Zealot", "Zealot", "Zealot" ]},
星際争霸傳統AI機器人源碼分析(2)——建造順序搜尋

Probe相當于勞工

當AI選擇的政策有變更、或者玩家某些單元被殲滅時,就需要更建立造順序。而ProductionManager便會根據StrategyManager的建造目前去建設。源碼中,上層通過如下接口給ProductionManager設定建設目标。

void ProductionManager::setBuildOrder(const BuildOrder & buildOrder);           

再通過performBuildOrderSearch方法做深度搜尋,最終獲得最優建造順序。

ProductionManager::performBuildOrderSearch()           

對遊戲的抽象

程式将遊戲的建造部分抽象成“遊戲狀态”和“動作”,并使用搜尋算法來計算最優解。

狀态

對于遊戲狀态,抽象成 S=(t,R,P,I) ,各含義如下:

  • t是一個數值,代表遊戲的時間(幀數)
  • R是一個向量,代表各種資源占用情況,例如目前遊戲有3個兵工廠,其中兩個是可用的,另一個進行生産,一分鐘後才變為可用
  • P是一個向量,存放已經安排但尚未執行的動作,例如正在建造補給站,還需30秒才能建完
  • I是一個向量,訓示勞工的狀态。例如有8個勞工正在挖晶體礦(mineral),另有3個正在收集油礦(gas)

通過抽象,程式便能夠使用較為簡單的數值來表達遊戲狀态,雖然這樣的表達簡化了很多内容,卻也降低了計算量,遊戲AI程式的運作速度不能太慢,才能夠做到實時操控

動作

  • 對于建造有關的操作,使用 a=(δ,r,b,c,p) 來抽象,各個符号的含義如下
  • δ 是一個數值,代表動作的持續時間(幀數),例如建一個士兵需要10秒
  • r、b、c代表執行該動作的各種先決條件,其中 r 指required(需要建好哪些東西),b指borrowed(需要借用哪些資源),c指consumed(需要消耗的資源)。
  • p指執行該動作後會産生的東西

舉例來說,對于“生産一個神族的龍騎兵”(Produce Protoss Dragoon)這麼一個動作,而言

  • 生産總共需要600幀,是以δ = 600
  • 必須先有建有控制核(Cybernetics-Core)才能建造,是以r = {Cybernetics-Core}
  • 建造過程中需使用兵營,“借用”兵營的生産力一小段時間,是以b = {Gateway}
  • 建造它需要消耗125個晶體礦,50個鈾礦,還算2個人口,是以c = {125 minerals, 50 gas, 2 supply}
  • 動作執行完畢會産生一個龍騎士,是以p = {1 Dragoon}

玩法的抽象

在實際的遊戲中,建造過程和收集資源的過程都較難用數學去表達,因為建造和收集過程中,需要派遣勞工,讓勞工走到目的地,然後建造或收集,對于收集,勞工還需要把礦物拿回基地,這個過程會涉及資源的位置、地圖尋路,比較複雜。是以,做了一些适當的簡化,如下所示。

  • 對于晶體礦收集,固定設定為每個勞工每幀收集0.045個
  • 對于油礦收集,固定設定為每個勞工每幀收集0.07個
  • 對于每個建築,預設加上4秒的建造時間,以模拟勞工走路花費的時間

狀态轉換

對于遊戲的狀态轉換,做出如下三種抽象:

  1. S′←Sim(S,δ) ,模拟從狀态S開始,沒有操作的經過δ時間,最後變為S'狀态
  2. δ←When(S,R) ,目前狀态為S,它需要R資源,該抽象計算出達成該資源所需的時間δ,例如有3個勞工在收集礦石,它需要多少時間才滿足建一個兵營
  3. S′←Do(S,a) ,目前狀态為S,且執行動作a的條件已滿足,執行動作a,使狀态變為S'

綜合起來即可得到狀态轉換函數 S′=Do(Sim(S,When(S,a)),a),既想執行動作a,先計算滿足條件所需的時間,然後等待條件滿足,最後執行。

搜尋算法

在做好抽象定義之後,即可從目前遊戲狀态(S)開始,找出達成建造目标(G)的方法,具體是通過深度優先搜尋(depth-first recursive search),遞歸周遊目前狀态下可能的發生的動作,具體算法如下:

星際争霸傳統AI機器人源碼分析(2)——建造順序搜尋
  • 2-4行:其中的TimeElapsed是為算法效率考慮,限制它執行的時間,以适應遊戲的實時性;
  • 9-17行:遞歸搜尋的過程,周遊S下可能執行的動作(while S has more children do),針對該動作形成的新局面S',遞歸調用( DFBB(S') )。其中h←eval(S')是啟發式評估的過程,目的是加快搜尋速度,隻對S'+h<b的狀态去做深度搜尋,忽略其他,這裡就展現了算法名字裡的Branch&Bound(分支界限)。其中的b是作為一個判斷的界限,它綜合兩層計算,其一,星際争霸的科技樹發展是有規律的,如果與預知的經驗相去甚遠,就不再進行搜尋;其二,根據所需的資源消耗來做條件,如果場面的資源不夠,說明難以執行到理想情況,無需繼續搜尋。
  • 5-7行:當周遊到目标局面G,即傳回最優的動作序列bestSolution。

這麼做法還有個問題,實際遊戲是多個動作并行處理,不過要做到并行處理動作的計算量很大,算法中采用串行來模拟并行,公式如下所示,即将a和b動作的并行視為有順序的執行。

Do(S,a+b)=Do(Do(S,a),b)

UAlbertaBot将以上算法封裝成一個成為BOSS的子系統,上層可以直接調用,輸入目前局勢和目标,它會傳回搜尋到的動作序列。

文章會分如下幾篇

  1. 架構和規則,宏觀介紹UAlbertaBot的原理
  2. 建造順序搜尋,介紹使用深度搜尋算法去找到最優建造順序的方法
  3. 戰鬥模拟評估,介紹模拟隊伍作戰評估能否獲勝的方法
  4. starterbot,一個最簡單的機器人,從中了解最基礎星際AI的寫法
  5. 政策制定,政策制定部分的代碼分析
  6. 建造實作,生産、建造相關系統的代碼分析
  7. 戰鬥實作,戰鬥相關代碼分析
  8. 尋路算法,地圖相關代碼的分析

下面又到廣而告之的時間啦,《Unity3D網絡遊戲實戰》是一本很好的書籍,作者花費很多時間編寫的呢,教你從零開始開發一款多人對戰遊戲,很有特色。網上其他資料大多教怎麼做單機遊戲,而這本書會說明制作網絡遊戲的方法,很值得閱讀。

星際争霸傳統AI機器人源碼分析(2)——建造順序搜尋

繼續閱讀