def minimax(evaluate, board: chess.Board, depth: int): ''' performs minimax search from the current board position, exploring down to a given depth; returns the optimal move from the current position (None if there are no moves, or depth is 0) and the value of the board when applying that move ''' if depth <= 0: return (None, evaluate(board)) moves = board.get_moves() if len(moves) == 0: # active player has no moves; loss or stalemate return (None, -INFTY - depth) max_utility_move = None max_utility = -float('inf') for move in moves: future_board = chess.Board.from_board(board) future_board.apply_move(move) opp_best_move, opp_utility = minimax(evaluate, future_board, depth - 1) utility = -opp_utility # negate since this is the opponent's maximal utility, which is our minimal utility if (utility > max_utility): max_utility = utility max_utility_move = move return (max_utility_move, max_utility)
def model_to_player_wrapper(evaluate, board: chess.Board): ''' Wrapper for returning a move to apply from an evaluation function and a board. ''' moves = board.get_moves() utilities = np.zeros(len(moves)) # future_boards = [board.apply_move(move) for move in moves] # copy-based for i in range(len(moves)): future_board = chess.Board.from_board(board) future_board.apply_move(moves[i]) future_tensor = convonet.board_tensor(future_board, one_hot=True, unsqueeze=True, half=False) utilities[i] = evaluate(future_tensor).item() utilities = np.exp(utilities) / np.exp(utilities).sum() # softmax choice = np.random.choice(moves, size=1, p=utilities).item() return choice
def test_minimax(self): # Own Test board1 = chess.Board() pawn = board1.get_piece(chess.locate("e2")) knight = board1.get_piece(chess.locate("g8")) board1.move_piece(pawn, chess.locate("e4")) board1.move_piece(knight, chess.locate("f6")) _, move = ai.minimax(board1, 3, 1) self.assertEqual( move, chess.Move(board1.get_piece(chess.locate("f6")), chess.locate("e4"))) _, move = ai.minimax_with_pruning(board1, 3, 1, alpha=-1000, beta=1000) self.assertEqual( move, chess.Move(board1.get_piece(chess.locate("f6")), chess.locate("e4"))) _, move = ai.minimax(board1, 3, 0) _, move = ai.minimax_with_pruning(board1, 0, 3, alpha=-1000, beta=1000) board1.move_piece(board1.get_piece(chess.locate("f1")), chess.locate("a6")) _, move = ai.minimax(board1, 3, 1) self.assertEqual( move, chess.Move(board1.get_piece(chess.locate("b8")), chess.locate("a6"))) board1.move_piece(board1.get_piece(chess.locate("b8")), chess.locate("a6")) print(board1.compute_score(1)) print(move) # Puzzle 68960 from lichess.org board3 = Board(empty=True) board3.add_piece(locate_piece(ROOK, WHITE, locate("d1"))) board3.add_piece(locate_piece(ROOK, WHITE, locate("f1"))) board3.add_piece(locate_piece(KING, WHITE, locate("g1"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("b2"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("c2"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("a3"))) board3.add_piece(locate_piece(KNIGHT, BLACK, locate("e3"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("h3"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("c4"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("g4"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("b5"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("e5"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("f5"))) board3.add_piece(locate_piece(BISHOP, BLACK, locate("a6"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("b6"))) board3.add_piece(locate_piece(KNIGHT, WHITE, locate("d6"))) board3.add_piece(locate_piece(KNIGHT, WHITE, locate("e7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("f7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("g7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("h7"))) board3.add_piece(locate_piece(ROOK, BLACK, locate("a8"))) board3.add_piece(locate_piece(KNIGHT, BLACK, locate("b8"))) board3.add_piece(locate_piece(ROOK, BLACK, locate("f8"))) board3.add_piece(locate_piece(KING, BLACK, locate("h8"))) print(board3) ai.minimax(board3, 4, WHITE) # Puzzle 68960 from lichess.org board3 = Board(empty=True) board3.add_piece(locate_piece(ROOK, WHITE, locate("d1"))) board3.add_piece(locate_piece(ROOK, WHITE, locate("f1"))) board3.add_piece(locate_piece(KING, WHITE, locate("g1"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("b2"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("c2"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("a3"))) board3.add_piece(locate_piece(KNIGHT, BLACK, locate("e3"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("h3"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("c4"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("g4"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("b5"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("e5"))) board3.add_piece(locate_piece(PAWN, WHITE, locate("f5"))) board3.add_piece(locate_piece(BISHOP, BLACK, locate("a6"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("b6"))) board3.add_piece(locate_piece(KNIGHT, WHITE, locate("d6"))) board3.add_piece(locate_piece(KNIGHT, WHITE, locate("e7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("f7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("g7"))) board3.add_piece(locate_piece(PAWN, BLACK, locate("h7"))) board3.add_piece(locate_piece(ROOK, BLACK, locate("a8"))) board3.add_piece(locate_piece(KNIGHT, BLACK, locate("b8"))) board3.add_piece(locate_piece(ROOK, BLACK, locate("f8"))) board3.add_piece(locate_piece(KING, BLACK, locate("h8"))) print(board3) board3.move_piece(locate_piece(ROOK, WHITE, locate("d1")), locate("d2")) print(board3) for move, board in board3.get_moves(BLACK): print(move) print(ai.minimax(board3, 3, BLACK)) print(BLACK)