private byte[] PredictBestMove(int depth, OthelloGame game, BoardStates player) { byte[] bestMove = new byte[] { byte.MaxValue, byte.MaxValue }; List <byte[]> moves = game.GetPossiblePlayList(); double bestScore = int.MinValue + 1; if (game.GetPieceCount(BoardStates.empty) > 58)//first two moves, don't compute { return(OpeningMove(player, game)); } else if (moves.Count == 1) //don't compute if there is only 1 move { return(moves[0]); } foreach (byte[] move in moves) { OthelloGame testGame = game.DeepCopy(); testGame.MakeMove(move); double thisScore = MinimaxAlphaBeta(testGame, depth - 1, double.MinValue, double.MaxValue, player); if (thisScore > bestScore) { bestScore = thisScore; bestMove = move; } } return(bestMove); }
public static OthelloGame GetReflectedAcrossA1H8(OthelloGame game) { OthelloGame newGame = game.DeepCopy(); for (int i = 0; i <= game.GetMovesMade(); i++) { for (int j = 0; j < BOARD_SIZE; j++) { for (int k = 0; k < BOARD_SIZE; k++) { if (game.BoardHistory[i] != null) { newGame.BoardHistory[i][j, k] = game.BoardHistory[i][k, j]; } } } } for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { newGame.Board[i, j] = game.Board[j, i]; } } return(newGame); }
public static OthelloGame GetInverseGame(OthelloGame game) { OthelloGame newGame = game.DeepCopy(); for (int i = 0; i <= game.GetMovesMade(); i++) { for (int j = 0; j < BOARD_SIZE; j++) { for (int k = 0; k < BOARD_SIZE; k++) { if (game.BoardHistory[i] != null) { newGame.BoardHistory[i][j, k] = OpposingPlayer(game.BoardHistory[i][j, k]); } } } } for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { newGame.Board[i, j] = OpposingPlayer(game.Board[i, j]); } } return(newGame); }
public static OthelloGame GetHalfPiRotation(OthelloGame game) { OthelloGame newGame = game.DeepCopy(); for (int i = 0; i <= game.GetMovesMade(); i++) { for (int j = 0; j < BOARD_SIZE; j++) { for (int k = 0; k < BOARD_SIZE; k++) { if (game.BoardHistory[i] != null) { newGame.BoardHistory[i][j, k] = game.BoardHistory[i][BOARD_SIZE - k - 1, j]; } } } } for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { newGame.Board[i, j] = game.Board[BOARD_SIZE - j - 1, i]; } } return(newGame); }
private double MinimaxAlphaBeta(OthelloGame board, int depth, double a, double b, BoardStates player)// bool isMaxPlayer) { // The heart of our AI. Minimax algorithm with alpha-beta pruning to speed up computation. // Higher search depths = greater difficulty. //from oliverzh200/reversi https://github.com/oliverzh2000/reversi if (depth == 0 || board.GameComplete) { return(HeuristicEval(player, board)); } double bestScore = double.MinValue; List <byte[]> validMoves = board.GetPossiblePlayList(); if (validMoves.Count > 0) { foreach (byte[] move in validMoves) { OthelloGame childBoard = board.DeepCopy(); childBoard.MakeMove(move); double nodeScore = MinimaxAlphaBeta(childBoard, depth - 1, a, b, player); bestScore = Math.Max(bestScore, nodeScore); a = Math.Max(bestScore, a); if (b <= a) //Prune { break; } } } else { return(MinimaxAlphaBeta(board, depth, a, b, player)); } return(bestScore); }
private byte[] PredictBestMove(int depth, OthelloGame game, BoardStates player) { byte[] bestMove = new byte[] { byte.MaxValue, byte.MaxValue }; List <byte[]> moves = game.GetPossiblePlayList(); double bestScore = int.MinValue + 1; foreach (byte[] move in moves) { OthelloGame testGame = game.DeepCopy(); testGame.MakeMove(move); double thisScore = MinimaxAlphaBeta(testGame, depth - 1, double.MinValue, double.MaxValue, player); if (thisScore > bestScore) { bestScore = thisScore; bestMove = move; } } if ((bestMove[0] == byte.MaxValue || bestMove[1] == byte.MaxValue) && moves.Count > 0) {//All moves are valued at -inf, return one of em return(moves[0]); } return(bestMove); }