簡體   English   中英

如何提高Chess.js的Minimax性能?

[英]How to improve performance of Minimax for Chess.js?


我正在嘗試使用Minimax算法和alpha-beta修剪功能,使用Chess.js和Chessboard.js編寫象棋引擎。 問題在於,即使使用depth=3 ,該算法也需要很長時間才能執行所有評估並確定要進行的移動。 如何提高性能?

以下是我的minimax實現:

var minimax = function (depth, game, alpha, beta, isAIplaying) {

  // end branch: simply evaluate and return the current score of the board
  if (depth === 0) {
    return evaluateBoard(game);
  }

  // list of all the possible moves in current status
  var newGameMoves = game.moves();
  if (isAIplaying) {
      var bestMove = -9999;
      for (var i = 0; i < newGameMoves.length; i++) {
          game.move(newGameMoves[i]);
          bestMove = Math.max(bestMove, minimax(depth - 1, game, !isAIplaying));
          game.undo();
          alpha = Math.max(alpha, bestMove);
          if (beta <= alpha) {
            return bestMove;
          }
      }
      return bestMove;
  } else {
      var bestMove = 9999;
      for (var i = 0; i < newGameMoves.length; i++) {
          game.move(newGameMoves[i]);
          bestMove = Math.min(bestMove, minimax(depth - 1, game, !isAIplaying));
          game.undo();
          beta = Math.min(beta, bestMove);
          if (beta <= alpha) {
           return bestMove;
          }
      }
      return bestMove;
  }
};

在以下代碼和平中調用該函數,其中Black必須決定必須采取的動作:

var possibleMoves = game.moves(); 

// game over
if (possibleMoves.length === 0) 
  return;

var best_score = -9999;
var bestMoveFound;

for(var i=0; i<possibleMoves.length; ++i){
  game.move(possibleMoves[i]); // make one possible move

   // minimax: take the current status of the game
  // it is not Black's turn
  var score = minimax(3, game, -10000, 10000, false);

  // if I get a better score then I store it
  if(score >= best_score){
    best_score = score;
    bestMoveFound = i;
  }

  // undo move
  game.undo();
}

// make the best move (update both the game and the board on the screen)
game.move(possibleMoves[bestMoveFound]);
board.position(game.fen());

其中以下是評估功能:

var evaluateBoard = function(current_game) {
    var status = current_game.fen();

    var score = 0;

    // calculate score for the current situation
    var fen_idx = 0;
    var piece = status[fen_idx];
    while(piece != ' '){
      switch(piece){
        case 'p': score += pawn; break;
        case 'n': score += knight; break;
        case 'b': score += bishop; break;
        case 'r': score += tower; break;
        case 'q': score += queen; break;
        case 'k': score += king; break;
        case 'P': score -= pawn; break;
        case 'N': score -= knight; break;
        case 'B': score -= bishop; break;
        case 'R': score -= tower; break;
        case 'Q': score -= queen; break;
        case 'K': score -= king; break;
        default: break;
      }

      ++fen_idx;
      piece = status[fen_idx];
    }

    return score;
};

pawnbishop和其他是簡單常數, p表示黑色的棋子, P表示白色的棋子。 您有加快性能的想法嗎?

評估FEN-String的想法看起來很快,但是您的程序必須為游戲樹的每次離開計算FEN-String。 這確實很慢,因為它必須在64個正方形上循環掃描每個圖形以及每個空白的正方形。 您不應該這樣做,而是將電路板上的圖形保留在列表中,以便計算與源代碼的模擬量。

如果在板上取下一塊或更換一塊,則最好具有所有余量的總和,而僅增加或減去一個值。 因此,您的評估功能不需計算,引擎將更快。 根據我的經驗,如果您的評估功能只是將兩側的零件值進行比較,則您應在2秒內達到7級深度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM