簡評:本文通過實際范例教大家如何實現(xiàn)一個低配版國際象棋 AI。
文中的基本概念如下,先自行搜索以方便理解:
- move-generation
- board evaluation
- minimax
- alpha beta pruning
在每個步驟中,我們將使用其中某種技術(shù)來改進我們的算法,并且演示他們是如何影響象棋 AI 的執(zhí)行效果。
你可以在 GitHub 上查看算法的最終版。
我無法打敗我自己寫的象棋程序,真不知道這是我太弱還是算法太好。
—— lhartikk
Step 1: 移動生成和邊界可視化
使用 chess.js 庫進行移動生成,并使用 chessboard.js 來顯示棋盤。移動生成庫基本上實現(xiàn)了棋的所有規(guī)則。基于此,我們可以計算出所有合法棋步。
移動生成功能的可視化。起始位置用作輸入,輸出是從該位置出發(fā)的所有可能的移動。
使用這些庫將有助于我們專注于最有趣的任務(wù):最佳棋步算法的構(gòu)建。
首先,我們創(chuàng)建一個從所有可移動中返回隨機移動的函數(shù):
Gif:黑手隨機移動
Step 2 : 位置評估
現(xiàn)在我們來評估哪一方在某一位置更強。可以用這個表來判斷:
通過評估功能,我們可以創(chuàng)建一個選擇提供最高評估的動作的算法:
var calculateBestMove = function (game) {
var newGameMoves = game.ugly_moves();
var bestMove = null;
//use any negative large number
var bestValue = -9999;
for (var i = 0; i < newGameMoves.length; i++) {
var newGameMove = newGameMoves[i];
game.ugly_move(newGameMove);
//take the negative as AI plays as black
var boardValue = -evaluateBoard(game.board())
game.undo();
if (boardValue > bestValue) {
bestValue = boardValue;
bestMove = newGameMove
}
}
return bestMove;
};
我們的算法現(xiàn)在可以在一塊區(qū)域內(nèi)實現(xiàn)評估。
Gif:測起來,動起來
Step 3: 使用 Minimax 搜索樹
接下來,我們要創(chuàng)建一個搜索樹,算法可以從中選擇最佳方法。這里用 Minimax 算法實現(xiàn)。
在該算法中,將所有可能移動的遞歸樹探索到給定的深度,并且在樹葉處評估位置。
之后,我們將最小值或最大值返回給父節(jié)點,這取決于它是移動白色還是黑色。(也就是說,我們盡可能地減少或最大限度地提高每一級的成果。)
白色的最佳舉措是 b2-c3,因為我們可以保證我們能夠達到評估為 -50 的位置
var minimax = function (depth, game, isMaximisingPlayer) {
if (depth === 0) {
return -evaluateBoard(game.board());
}
var newGameMoves = game.ugly_moves();
if (isMaximisingPlayer) {
var bestMove = -9999;
for (var i = 0; i < newGameMoves.length; i++) {
game.ugly_move(newGameMoves[i]);
bestMove = Math.max(bestMove, minimax(depth - 1, game, !isMaximisingPlayer));
game.undo();
}
return bestMove;
} else {
var bestMove = 9999;
for (var i = 0; i < newGameMoves.length; i++) {
game.ugly_move(newGameMoves[i]);
bestMove = Math.min(bestMove, minimax(depth - 1, game, !isMaximisingPlayer));
game.undo();
}
return bestMove;
}
};
利用最小值,我們的算法開始了解象棋的基本策略:
極小值算法的有效性很大程度上取決于我們可以實現(xiàn)的搜索深度,我們將在以下步驟中進行改進。
Step 4: Alpha-beta pruning
Alpha-beta pruning 是最小化算法的優(yōu)化,允許我們忽略搜索樹中的一些分支。這有助于我們在使用相同的資源的同時更深入地評估最小值搜索樹。如果我們發(fā)現(xiàn)導(dǎo)致比之前動作更糟糕的情況時,這個算法能停止評估搜索樹。它不會影響算法結(jié)果,反而能加速其進行。
使用 alpha-beta,可以顯著提升極小值算法,如下例所示:
按照這個鏈接來嘗試這個國際象棋 AI 的 alpha-beta 改進版。
Step 5: 改進評估功能
初始評估功能非常簡陋。為了改善這一點,我們增加一些因素。比如,棋盤中心的騎士比邊緣的騎士更好(因為它有更多的選擇,因此更加活躍)。
在 chess-programming-wiki 中描述的改進表格:
改進后我們能得到稍微聰明一點的象棋 AI,至少從業(yè)余玩家的眼中是這樣的。
結(jié)論
即使是這樣一個簡單的象棋算法,它的優(yōu)勢也在于幾乎不會產(chǎn)生顯而易見的錯誤。但這同時也顯示,它缺乏戰(zhàn)略性思考。
本文闡述的方法已經(jīng)足夠編程基本象棋的棋藝算法,AI 的部分其實只有區(qū)區(qū) 200 行代碼(不包括 move-generation),實現(xiàn)起來并不難。
戳 GitHub 鏈接看最終版本,更多信息可以查看 chess programming wiki。
原文地址:A step-by-step guide to building a simple chess AI
歡迎關(guān)注知乎專欄「極光日報」,每天為 Makers 導(dǎo)讀三篇優(yōu)質(zhì)英文文章。
日報延伸閱讀: