/// <summary> /// Minimax with alpha-beta pruning (faster). /// </summary> /// <param name="board">Board of this game</param> /// <param name="depth">Depth of move tree</param> /// <param name="playerFirst">Maximizing player</param> /// <param name="playerSecond">Minimizing</param> /// <param name="alpha">Alpha parameter</param> /// <param name="beta">Beta parameter</param> /// <returns></returns> public int AlphaBeta(Board board, int depth, Player playerFirst, Player playerSecond, int alpha, int beta) { if (board.EndState() == true || depth == simulationDepth) { return(boardEvaluator.Evaluate(board, playerFirst) - boardEvaluator.Evaluate(board, playerSecond)); } if (depth % 2 == 0) { int bestScore = int.MinValue; List <ICommand> moves = board.PossibleMoves(playerFirst); foreach (ICommand move in moves) { Board afterMove = board.Copy(); gameExecutor.ExecuteCommand(afterMove, move); int score = AlphaBeta(afterMove, depth + 1, playerFirst, playerSecond, alpha, beta); bestScore = Mathf.Max(bestScore, score); alpha = Mathf.Max(alpha, bestScore); if (alpha >= beta) { break; } } return(bestScore); } else { int bestScore = int.MaxValue; List <ICommand> moves = board.PossibleMoves(playerSecond); foreach (ICommand move in moves) { Board afterMove = board.Copy(); gameExecutor.ExecuteCommand(afterMove, move); int score = AlphaBeta(afterMove, depth + 1, playerFirst, playerSecond, alpha, beta); bestScore = Mathf.Min(bestScore, score); beta = Mathf.Min(beta, bestScore); if (beta <= alpha) { break; } } return(bestScore); } }
private void Simulate() { Player player1; //Player doing this move Player player2; //Player next in turn if (turn % 2 == 0) { //P1 move player1 = p1; player2 = p2; } else { //P2 move player1 = p2; player2 = p1; } List <ICommand> moves = board.PossibleMoves(player1); int bestScore = int.MinValue; ICommand bestMove = null; foreach (ICommand move in moves) { Board afterMove = board.Copy(); gameExecutor.ExecuteCommand(afterMove, move); int score = 0; if (UseAlphaBeta) { score = AlphaBeta(afterMove, 1, player1, player2, int.MinValue, int.MaxValue); } else { score = Minimax(afterMove, 1, player1, player2); } if (score > bestScore) { bestScore = score; bestMove = move; } } if (bestMove != null) { gameExecutor.ExecuteCommand(bestMove); } else { Debug.Log("No possible moves. Game has ended."); } turn++; }
/// <summary> /// Minimax without alpha-beta pruning (slower). /// </summary> /// <param name="board">Board of this game</param> /// <param name="depth">Depth of move tree</param> /// <param name="playerFirst">Maximizing player</param> /// <param name="playerSecond">Minimizing</param> /// <returns></returns> public int Minimax(Board board, int depth, Player playerFirst, Player playerSecond) { if (board.EndState() == true || depth == _simulationDepth) { return(_boardEvaluator.Evaluate(board, playerFirst) - _boardEvaluator.Evaluate(board, playerSecond)); } if (depth % 2 == 0) { int bestScore = int.MinValue; List <ICommand> moves = board.PossibleMoves(playerFirst); foreach (ICommand move in moves) { Board afterMove = board.Copy(); _gameExecutor.ExecuteCommand(afterMove, move); int score = Minimax(afterMove, depth + 1, playerFirst, playerSecond); bestScore = Mathf.Max(bestScore, score); } return(bestScore); } else { int bestScore = int.MaxValue; List <ICommand> moves = board.PossibleMoves(playerSecond); foreach (ICommand move in moves) { Board afterMove = board.Copy(); _gameExecutor.ExecuteCommand(afterMove, move); int score = Minimax(afterMove, depth + 1, playerFirst, playerSecond); bestScore = Mathf.Min(bestScore, score); } return(bestScore); } }