前言:
對弈類游戲的智能算法, 網上資料頗多, 大同小異. 我寫這篇文章, 並非想做互聯網的搬運工. 而是想對當年的經典<<PC游戲編程(人機博弈)>>表達敬意, 另一方面, 也想對自己當年的游戲編程人生做下回顧.
這邊我們以黑白棋游戲為例, 從博弈和學習兩方面來闡述游戲AI的編寫要點. 本文側重於講述博弈(評估函數+博弈算法).
博弈:
以前看圍棋比賽, 常有人評價棋手水平高: 大局觀強(評估局面好), 算路精准(計算步數深, 實戰效果好). 他山之石可以攻玉, 對弈類游戲的AI本質上也是在評估局面, 博弈深度這兩點上做足了文章.
(一)評估函數:
讓我們先來談談局面評估, 那如何從程序的角度去合理評估游戲的局勢呢?
首先局面的好壞, 需要綜合考慮多個因素(權重不同, 不同階段重要性的變化), 其次因素影響力需轉化為數值來衡量.
為了簡化模型, 我們引入評估函數G(s), s為當前的局面, G(s)為當前局面的評估值.
G(s) = a1 * f1(s) + a2 * f2(s) + ... + an * fn(s)
注: fi(s)為某個評估因素的得分, ai為某個評估因素的權重比
評估函數G(s)的引入, 為游戲AI的智能引入了數學模型, 也是一切的基礎.
回到黑白棋游戲本身, 依據經驗選定如下特征評估因素:
1).地勢估值表
黑白棋和圍棋一樣, 也遵守着"金角銀邊爛肚皮"的定律, 四個角的地勢值非常大, 其次是四條邊. 因此我們再給8*8地圖點分配地勢值時, 大體滿足角邊重, 中腹輕的模式.
potential_enegy(s) = ∑ pe[x, y] {map[x,y] is occupied, 8>x>=0, 8>y>=0}
注: potential_enegy(s) 為地勢評估函數, pe[x,y] 為地勢估值矩陣, map[x,y]是游戲地圖本身.
2).行動力
基於這樣的假設: 在某局面中, 選擇多, 則靈活主動, 而選擇少, 則往往陷入被動. 因此選擇多少, 就成為了評估局面好壞的參考因素了. 於是我們把面對某一局面, 可以落子的個數, 稱之為行動力.
3).穩定子
所謂穩定子, 是指無論如何, 都不可能被翻覆的子, 最簡單的穩定子就是4個角點, 穩定值越多, 獲勝的幾率就越大.
有了這些評估因素后, 再賦予一定的權重系數, 評估函數就比較完善了. 此時游戲的AI也基本構建完畢, 其棋力能擊敗初學者, 應該不成問題.
但此時的AI很脆弱, 看似每步都選擇最佳落子, 卻很容易落入陷阱. 這就是貪心算法, 導致的局部最優陷阱. 如何破這個局呢? 期待王者到來: 博弈樹.
(二)博弈樹:
博弈樹本質就是極大極小的搜索過程,相關資料可參考博文: "極大極小博弈樹".
極大極小的算法, 分支繁多而冗余, 於是引入alpha+beta剪枝做優化, 它可以快速裁剪不必要的搜索分支, 提高搜索效率.
關於這塊, 就不再具體展開, 參見如下博文: A*算法/博弈樹, 機器博弈中的基本搜索算法;
alpha+beta剪枝的極大極小過程示意圖:
負極大值算法偽碼:
// 負極大值算法 int negamax(GameState S, int depth, int alpha, int beta) { // 游戲是否結束 || 探索的遞歸深度是否到邊界 if ( gameover(S) || depth == 0 ) { return evaluation(S); } // 遍歷每一個候選步 foreach ( move in candidate list ) { S' = makemove(S); value = -negamax(S', depth - 1, -beta, -alpha); unmakemove(S') if ( value > alpha ) { // alpha + beta剪枝點 if ( value >= beta ) { return beta; } alpha = value; } } return alpha; }
展望:
有了評估函數和博弈樹后, 其游戲AI有了飛躍的進步, 但一山更有一山高, 我們是否能夠更進一步呢?
對於評估函數, 我們當前的策略是基於經驗, 選擇評估因素和權重分配. 能否用機器學習的方法,自動實現因素(特征)選擇, 權重系數合理分配呢?
而對於博弈算法本身, 是否還有優化的地方? 搜索深度和搜索分支的廣度如何權衡?
最重要的如何設置進階的AI難度, 增強用戶的體驗?
因篇幅受限, 決定放到下一篇博文中.
總結:
為何選擇黑白棋作為對弈類游戲AI解說的對象, 一方面游戲規則簡單, 另一方面其評估模型容易構建, 且其搜索分支少+搜索深度深, 這些對快速實現並理解博弈游戲的AI核心算法有非常大的幫助. 該博文主要講述了評估函數和博弈樹的原理和優化. 下文講着重講述下 博弈游戲的AI如何學習, 以及性能優化的進階篇.
寫在最后:
如果你覺得這篇文章對你有幫助, 請小小打賞下. 其實我想試試, 看看寫博客能否給自己帶來一點小小的收益. 無論多少, 都是對樓主一種由衷的肯定.