def test_evaluate_board(self): starting_fen = chess.Board( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1") white_down_one_pawn = chess.Board( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPP1/RNBQKBNR w KQkq - 0 1") self.assertTrue( evaluate_board(starting_fen) > evaluate_board(white_down_one_pawn))
def solve_alphabeta(board: SimpleGoBoard, color: int, board_is_evaluated=False): result, winner = board.check_game_end_gomoku() if result: if winner == color: return 10*score.FIVE, None else: return -10*score.FIVE, None # print('ok') alpha, beta = -10*score.FIVE, 10*score.FIVE if not board_is_evaluated: evaluate_board(board) moves = gen_possible_moves(board, color) print(list(map(lambda t: (t[0], gtp_connection.format_point( gtp_connection.point_to_coord(t[0], board.size)), t[1], t[2]), moves))) if len(moves) == 0: return 0, None if (gtp_connection.total_steps == 0 or gtp_connection.total_steps == 1) and board.board[36] == EMPTY: return 1, 36 # best_move = None global best_move best_move = PASS for m in moves: move = m[0] # move_coord = gtp_connection.point_to_coord(move, board.size) # move_as_string = gtp_connection.format_point(move_coord) board.board[move] = color update_board(board, move) result = -alphabeta_search(board, move, GoBoardUtil.opponent(color), 40, -beta, -alpha) # print("trying move:", move_as_string, "score:", result) board.board[move] = EMPTY update_board(board, move) if result > alpha: alpha = result best_move = move if result >= beta: return beta, move return alpha, best_move
def boolean_negamax(board: SimpleGoBoard, last_move: int, current_color: int) -> ('result', 'move'): if debug: print_board(board) if last_move is None: evaluate_board(board) if last_move is not None and check_winning_condition(board, last_move, board.board[last_move]): # print('game ends') return -1, None opponent_color = GoBoardUtil.opponent(current_color) moves = gen_possible_moves(board, current_color) if len(moves) == 0: return 0, None best_result = -1 best_move = moves[0][0] if debug: print_moves(moves, board.size) for m in moves: move = m[0] board.board[move] = current_color update_board(board, move) # print('play', gtp_connection.point_to_str(move, board.size)) result, _ = boolean_negamax(board, move, opponent_color) result = -result board.board[move] = EMPTY update_board(board, move) if result > 0: # print("win") return 1, move if result > best_result: best_result = result best_move = move return best_result, best_move
def minimax( depth: int, board: chess.Board, alpha: float, beta: float, is_maximising_player: bool, ) -> float: debug_info["nodes"] += 1 if board.is_checkmate(): # The previous move resulted in checkmate return -float("inf") if is_maximising_player else float("inf") # When the game is over and it's not a checkmate it's a draw # In this case, don't evaluate. Just return a neutral result: zero elif board.is_game_over(): return 0 if depth == 0: return evaluate_board(board) if is_maximising_player: best_move = -float("inf") moves = get_ordered_moves(board) for move in moves: board.push(move) best_move = max( best_move, minimax(depth - 1, board, alpha, beta, not is_maximising_player), ) board.pop() alpha = max(alpha, best_move) if beta <= alpha: return best_move return best_move else: best_move = float("inf") moves = get_ordered_moves(board) for move in moves: board.push(move) best_move = min( best_move, minimax(depth - 1, board, alpha, beta, not is_maximising_player), ) board.pop() beta = min(beta, best_move) if beta <= alpha: return best_move return best_move
def test_evaluate_board(self): white_down_one_pawn = chess.Board( "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPP1/RNBQKBNR w KQkq - 0 1") self.assertTrue( evaluate_board(chess.Board()) > evaluate_board(white_down_one_pawn) ) white_played_e2e4 = chess.Board( "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1") self.assertTrue( evaluate_board(chess.Board()) < evaluate_board(white_played_e2e4)) black_played_b8c6 = chess.Board( "r1bqkbnr/pppppppp/2n5/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 1 2") self.assertTrue( evaluate_board(black_played_b8c6) < evaluate_board( white_played_e2e4))
def q_function(time, state, action): current_score = evaluate.evaluate_board()
def minimax( depth: int, board: chess.Board, alpha: float, beta: float, is_maximising_player: bool, ) -> float: """ Core minimax logic. https://en.wikipedia.org/wiki/Minimax """ debug_info["nodes"] += 1 if board.is_checkmate(): # The previous move resulted in checkmate return -MATE_SCORE if is_maximising_player else MATE_SCORE # When the game is over and it's not a checkmate it's a draw # In this case, don't evaluate. Just return a neutral result: zero elif board.is_game_over(): return 0 if depth == 0: return evaluate_board(board) if is_maximising_player: best_move = -float("inf") moves = get_ordered_moves(board) for move in moves: board.push(move) curr_move = minimax(depth - 1, board, alpha, beta, not is_maximising_player) # Each ply after a checkmate is slower, so they get ranked slightly less # We want the fastest mate! if curr_move > MATE_THRESHOLD: curr_move -= 1 elif curr_move < -MATE_THRESHOLD: curr_move += 1 best_move = max( best_move, curr_move, ) board.pop() alpha = max(alpha, best_move) if beta <= alpha: return best_move return best_move else: best_move = float("inf") moves = get_ordered_moves(board) for move in moves: board.push(move) curr_move = minimax(depth - 1, board, alpha, beta, not is_maximising_player) if curr_move > MATE_THRESHOLD: curr_move -= 1 elif curr_move < -MATE_THRESHOLD: curr_move += 1 best_move = min( best_move, curr_move, ) board.pop() beta = min(beta, best_move) if beta <= alpha: return best_move return best_move