/** * Alpha-Beta Negamax algorithm. Go check on wikipedia! * * @param evaluatedBoard The board currently evaluated. * @param resultBoard (Optional) The board that will store the result of the best move. * @param alpha Alpha parameter, to cut some leaves on the multiverse tree. * @param beta Alpha parameter, to cut even more leaves on the multiverse tree. * @param depth The current depth of the reflexion. * @return The best you can do with the worst the other player can do with the best you can do * with... */ public int negaMax(Board evaluatedBoard, Board resultBoard, int alpha, int beta, int depth) { // If it's a leaf, evaluate. if (depth == MAX_DEPTH || evaluatedBoard.numberOf(DWARF) == 0 || evaluatedBoard.numberOf(TROLL) == 0) { return evaluate(evaluatedBoard); } List<Board> childrenBoards = evaluatedBoard.childrenBoards(); /* Map<Board, Integer> boardValues = new HashMap<>(); for (Board childrenBoard : childrenBoards) { boardValues.put(childrenBoard, evaluate(childrenBoard)); } // Sort those boards with the evaluation method, to evaluate the most interesting moves. Collections.sort(childrenBoards, (board1, board2) -> Integer.compare(boardValues.get(board2), boardValues.get(board1))); */ // Look for the best value on children boards. int boardIndex; int bestValue = -INFINITY; for (boardIndex = 0; boardIndex < childrenBoards.size(); boardIndex++) { // Update the progress callback, if any. if (depth == 0 && progressCallback != null) { progressCallback.accept(100 * boardIndex / childrenBoards.size()); } Board childBoard = childrenBoards.get(boardIndex); // Get the score of the child. The negamax, a specific implementation of the Minimax, requires // switching and inverting values here. int score = -negaMax(childBoard, null, -beta, -alpha, depth + 1); if (score > bestValue) { bestValue = score; // If we're at depth zero, keep track of the best board. if (depth == 0) { if (resultBoard != null) { resultBoard.set(childBoard); } } } // Alpha-beta pruning alpha = Math.max(alpha, score); if (alpha >= beta) { break; } } return bestValue; }