//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Method calculates the move the AI Player should choose. /// </summary> /// <param name="b">Game Board object</param> /// /// <returns>the move the AI chose to make</returns> public override int ChooseMove(Board b) { // If AI Player is Position TOP if (b.WhoseMove() == Position.Top) { // Try first go-again. for (int i = 12; i >= 7; i--) { if (b.StonesAt(i) == 13 - i) { return(i); } } // Otherwise, choose first available move. for (int i = 12; i >= 7; i--) { if (b.StonesAt(i) > 0) { return(i); } } } // If AI Player is Position BOTTOM else { // Try first go-again. for (int i = 5; i >= 0; i--) { if (b.StonesAt(i) == 6 - i) { return(i); } } // Otherwise, choose first available move. for (int i = 5; i >= 0; i--) { if (b.StonesAt(i) > 0) { return(i); } } } // Return illegal move, if no legal moves are possible. (only if game is over) return(-1); }
public override int chooseMove(Board b) { if (b.WhoseMove() == Position.Top) { for (int i = 12; i >= 7; i--) // try first go-again { if (b.StonesAt(i) == 13 - i) { return(i); } } for (int i = 12; i >= 7; i--) // otherwise, first { if (b.StonesAt(i) > 0) { return(i); // available move } } } else { for (int i = 5; i >= 0; i--) { if (b.StonesAt(i) == 6 - i) { return(i); } } for (int i = 5; i >= 0; i--) { if (b.StonesAt(i) > 0) { return(i); } } } return(-1); // an illegal move if there aren't any legal ones } // this can't happen unless game is over
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR METHOD SEPARATOR //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Play a Mankalah game with the two given players, with the firstPlayer starting. /// Returns TOP's score. /// </summary> /// <param name="playerTop">the player on the top</param> /// <param name="playerBottom">the player on the bottom</param> /// <param name="firstPlayer">the player who is starting the game</param> /// <returns>the score of the TOP player</returns> public static int PlayGame(Player playerTop, Player playerBottom, Position firstPlayer) { // Create a new game board. _board = new Board(firstPlayer); // Determine the player who starts. if (firstPlayer == Position.Top) { Console.WriteLine("Player " + playerTop.GetName() + " starts."); } else { Console.WriteLine("Player " + playerBottom.GetName() + " starts."); } // Display the current state of the game board. _board.Display(); // Continue rotating turns till the game is over. while (!_board.GameOver()) { Console.WriteLine(); // Get the player's move and output what move the player made. if (_board.WhoseMove() == Position.Top) { _move = playerTop.ChooseMove(_board); Console.WriteLine(playerTop.GetName() + " chooses move " + _move); } else { _move = playerBottom.ChooseMove(_board); Console.WriteLine(playerBottom.GetName() + " chooses move " + _move); } // Commit the move to the game state. (true = verbose, false = non-verbose) _board.MakeMove(_move, true); // Display the new state of the game board. _board.Display(); // Game is over, determine final results. if (_board.GameOver()) { if (_board.Winner() == Position.Top) { Console.WriteLine("Player " + playerTop.GetName() + " (TOP) wins " + _board.ScoreTopPlayer() + " to " + _board.ScoreBottomPlayer()); } else if (_board.Winner() == Position.Bottom) { Console.WriteLine("Player " + playerBottom.GetName() + " (BOTTOM) wins " + _board.ScoreBottomPlayer() + " to " + _board.ScoreTopPlayer()); } else { Console.WriteLine("A tie!"); } } // Game is not over, ask player to make their move. else if (_board.WhoseMove() == Position.Top) { Console.WriteLine(playerTop.GetName() + " to move."); } else { Console.WriteLine(playerBottom.GetName() + " to move."); } } // Return the final score for the match. return(_board.ScoreTopPlayer()); }
// this is a method that evaluates the current board using hueristics to find the best possible move public override int evaluate(Board board) { // declaring the evaulate hueristics int captures = 0; int extraMoves = 0; int finalState = 0; int score = 0; int upperStones = 0; int lowerStones = 0; if (board.WhoseMove() == Position.Top) { // score is increased or decreased by the current score (it's added both times because the score can be negative) if (position == Position.Top) { score += board.StonesAt(13) - board.StonesAt(6); } else { score += board.StonesAt(6) - board.StonesAt(13); } // extraMoves is increased or decreased by two because the player is being rewarded for both increasing their own score and getting to go again for (int i = 12; i >= 7; i--) { if (board.StonesAt(i) == 13 - i) { if (position == Position.Top) { extraMoves += 2; } else { extraMoves -= 2; } } } // capture is increased or decreased by the number of stones that are captured if the move is executed for (int i = 12; i >= 7; i--) // check for captures { if (board.StonesAt((board.StonesAt(i) + i) % 14) == 0 && // check for an empty bowl ((board.StonesAt(i) + i) % 14) <= 12 && ((board.StonesAt(i) + i) % 14) >= 7 && // check that it is not landing on the other side board.StonesAt(6 - (((board.StonesAt(i) + i) % 14) - 6)) > 0) // check that we aren't capturing zero { if (position == Position.Top) { captures += board.StonesAt(6 - (((board.StonesAt(i) + i) % 14) - 6)); } else { captures -= board.StonesAt(6 - (((board.StonesAt(i) + i) % 14) - 6)); } } } // finalState looks for moves that cause one side of the board to be empty and increases or decreases the score according to how many stones each player would capture for (int i = 12; i >= 7; i--) { upperStones += board.StonesAt(i); } for (int i = 5; i >= 0; i--) { lowerStones += board.StonesAt(i); } if (lowerStones == 0 && upperStones > 0) { finalState += upperStones; } if (upperStones == 0 && lowerStones > 0) { finalState -= lowerStones; } } else // These are all the same methods with slight variation that takes into account if the Player is on the bottom { // score hueristic if (position == Position.Bottom) { score += board.StonesAt(6) - board.StonesAt(13); } else { score += board.StonesAt(13) - board.StonesAt(6); } // extraMoves hueristic for (int i = 5; i >= 0; i--) { if (board.StonesAt(i) == 6 - i) { if (position == Position.Bottom) { extraMoves += 2; } else { extraMoves -= 2; } } } // captures hueristic for (int i = 5; i >= 0; i--) { if (board.StonesAt((board.StonesAt(i) + i) % 14) == 0 && ((board.StonesAt(i) + i) % 14) >= 0 && ((board.StonesAt(i) + i) % 14) <= 5 && board.StonesAt(6 + (((board.StonesAt(i) + i) % 14) - 6)) > 0) { if (position == Position.Bottom) { captures += board.StonesAt(6 + (((board.StonesAt(i) + i) % 14) - 6)); } else { captures -= board.StonesAt(6 + (((board.StonesAt(i) + i) % 14) - 6)); } } } // finalState hueristic for (int i = 12; i >= 7; i--) { upperStones += board.StonesAt(i); } for (int i = 5; i >= 0; i--) { lowerStones += board.StonesAt(i); } if (lowerStones == 0 && upperStones > 0) { finalState -= upperStones; } if (upperStones == 0 && lowerStones > 0) { finalState += lowerStones; } } upperStones = lowerStones = 0; // reset the upper and lower stone values return(score + captures + extraMoves + finalState); // output the board quality }
public Tuple <int, double> MiniMax(Board board, int depth, double alpha, double beta) { double bestResult = 0; double result = 0; int bestMove = 0; if (board.GameOver() || depth == 0) { return(new Tuple <int, double>(0, evaluate(board))); } int start = 0; if (board.WhoseMove() == Position.Top) { start = 7; } else { start = 0; } if (board.WhoseMove() == position) { bestResult = double.NegativeInfinity; for (int move = start; move <= start + 5; move++) { if (board.LegalMove(move) && timer.ElapsedMilliseconds < getTimePerMove()) { Board tempBoard = new Board(board); //duplicate board tempBoard.MakeMove(move, false); //make the move result = MiniMax(tempBoard, depth - 1, alpha, beta).Item2; if (result > bestResult) //find its value { bestResult = result; //remember if best bestMove = move; } if (bestResult > alpha) { alpha = bestResult; } if (beta <= alpha) { break; } } } } else { bestResult = double.PositiveInfinity; for (int move = start; move <= start + 5; move++) { if (board.LegalMove(move) && timer.ElapsedMilliseconds < getTimePerMove()) { Board tempBoard = new Board(board); //duplicate board tempBoard.MakeMove(move, false); //make the move result = MiniMax(tempBoard, depth - 1, alpha, beta).Item2; if (result < bestResult) //find its value { bestResult = result; //remember if best bestMove = move; } if (beta < bestResult) { beta = bestResult; } if (beta <= alpha) { break; } } } } return(new Tuple <int, double>(bestMove, bestResult)); }
/* * Play one Kalah game with the two given players, with firstPlayer * starting. This function returns TOP's score. */ public static int playGame(Player pTop, Player pBot, Position firstPlayer) { b = new Board(firstPlayer); if (firstPlayer == Position.Top) { Console.WriteLine("Player " + pTop.getName() + " starts."); } else { Console.WriteLine("Player " + pBot.getName() + " starts."); } b.Display(); while (!b.GameOver()) { Console.WriteLine(); if (b.WhoseMove() == Position.Top) { move = pTop.chooseMove(b); Console.WriteLine(pTop.getName() + " chooses move " + move); } else { move = pBot.chooseMove(b); Console.WriteLine(pBot.getName() + " chooses move " + move); } b.MakeMove(move, true); // last parameter says to be chatty b.Display(); if (b.GameOver()) { if (b.Winner() == Position.Top) { Console.WriteLine("Player " + pTop.getName() + " (TOP) wins " + b.ScoreTop() + " to " + b.ScoreBot()); } else if (b.Winner() == Position.Bottom) { Console.WriteLine("Player " + pBot.getName() + " (BOTTOM) wins " + b.ScoreBot() + " to " + b.ScoreTop()); } else { Console.WriteLine("A tie!"); } } else if (b.WhoseMove() == Position.Top) { Console.WriteLine(pTop.getName() + " to move."); } else { Console.WriteLine(pBot.getName() + " to move."); } } return(b.ScoreTop()); }