// The function minimax() calculates the best possible move that Chappie can make by // recursing as far as it can within the time limit and keeping track of what the best move and // score are as it recurses. It is also implemented with AB pruning, meaning that if it // starts to go down a path where the outcome will inevitable be worse that our best values, // it prunes off that path, therefore saving time to go down a better path. private MoveResult minimax(Board b, int d, Stopwatch w, int alpha, int beta) { // check to see if the time limit is up if (w.ElapsedMilliseconds > getTimePerMove()) { throw new MoveTimedOutException(); } // base case if (b.gameOver() || d == 0) { return(new MoveResult(0, evaluate(b), b.gameOver())); } // initialization of trackers int bestMove = 0; int bestVal; bool gameCompleted = false; // check all the the moves that top could make, and act as if it is the MAX in minimax if (b.whoseMove() == Position.Top) // TOP is MAX { // smallest possible value so that it can only get better bestVal = Int32.MinValue; for (int move = 7; move <= 12 && alpha < beta; move++) { if (b.legalMove(move)) { Board b1 = new Board(b); // duplicate board b1.makeMove(move, false); // make the move MoveResult val = minimax(b1, d - 1, w, alpha, beta); // find its value if (val.getScore() > bestVal) // remember if best { bestVal = val.getScore(); bestMove = move; // track the current condition of the game gameCompleted = val.isEndGame(); } // prune if (bestVal > alpha) { alpha = bestVal; } } } } // check all the the moves that bottom could make, and act as if it is the MIN in minimax else // BOTTOM is MIN { // lergest possible value so that it can only get better bestVal = Int32.MaxValue; for (int move = 0; move <= 5 && alpha < beta; move++) { if (b.legalMove(move)) { Board b1 = new Board(b); // duplicate board b1.makeMove(move, false); // make the move MoveResult val = minimax(b1, d - 1, w, alpha, beta); // find its value if (val.getScore() < bestVal) // remember if best { bestVal = val.getScore(); bestMove = move; // track the current condition of the game gameCompleted = val.isEndGame(); } // prune if (bestVal < beta) { beta = bestVal; } } } } return(new MoveResult(bestMove, bestVal, gameCompleted)); }