// Overriden chooseMove() function, which contains the code to check for time to make // sure that it is a staged DFS and the code to run the minimax function as well as // return the move that is best calculated. public override int chooseMove(Board b) { Stopwatch watch = new Stopwatch(); watch.Start(); int i = 1; MoveResult move = new MoveResult(0, 0, false); // try-catch block to make sure that we are not only using the latest // COMPLETED move, but also check that we have not passed the time limit try { while (!move.isEndGame()) { move = minimax(b, i++, watch, Int32.MinValue, Int32.MaxValue); } } // if we see that we are past the time, don't do anything and return the move catch (MoveTimedOutException) { // NOP } return(move.getMove()); }
// 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)); }