def value(game_state: Othello, depth, heuristic, alpha=-1, beta=1): """ Get value for game_state according to alpha beta pruning :param game_state: The state to evaluate :param depth: do alpha beta pruning until this depth is reached :param heuristic: Function reference for the heuristic used to score game state after maximum search depth is reached :param alpha: value of alpha :param beta: value of beta :return: value of move Compare https://github.com/karlstroetmann/Artificial-Intelligence/blob/master/SetlX/game-alpha-beta.stlx """ if game_state.game_is_over(): return game_state.utility(game_state.get_current_player()) if depth == 0: # return heuristic of game state return heuristic(game_state.get_current_player(), game_state) val = alpha for move in game_state.get_available_moves(): next_state = game_state.deepcopy() next_state.play_position(move) val = max({ val, -1 * AlphaBetaPruning.value(next_state, depth - 1, heuristic, -beta, -alpha) }) if val >= beta: return val alpha = max({val, alpha}) return val
def value_monte_carlo(game_state: Othello, depth, heuristic, alpha=-1, beta=1, mc_count=100): """ get score for alpha beta pruning :param game_state: actual game state :param depth: do alpha beta pruning this depth :param heuristic: score game state after alpha beta pruning with this heuristic :param mc_count: number of games which are played in each terminal node after alpha beta pruning :param alpha: value of alpha :param beta: value of beta :return: score of move Compare https://github.com/karlstroetmann/Artificial-Intelligence/blob/master/SetlX/game-alpha-beta.stlx """ if game_state.game_is_over(): return game_state.utility(game_state.get_current_player()) if depth == 0: # use monte carlo player if enabled # mc_count = number of played games mc = MonteCarlo(big_number=mc_count, use_start_libs=False, preprocessor_n=-1, heuristic=heuristic, use_multiprocessing=True) # get best move move = mc.get_move(game_state) # return winnings stats of best move prob = mc.get_move_probability(move) return prob val = alpha for move in game_state.get_available_moves(): next_state = game_state.deepcopy() next_state.play_position(move) val = max({ val, -1 * AlphaBetaPruning.value_monte_carlo(next_state, depth - 1, heuristic, -beta, -alpha, mc_count=mc_count) }) if val >= beta: return val alpha = max({val, alpha}) return val
for game_counter in range(games_nr): print(f"game: {game_counter}") # Store the players in a dict with the internal player codes as key to allow easy access and maintaining the correct order players = {PLAYER_ONE: player_one, PLAYER_TWO: player_two} times = {PLAYER_ONE: 0, PLAYER_TWO: 0} # Create a new game state game = Othello() # Initialize it to start a new game game.init_game() # store the start time start = time.time() # While the game is still running continue to make turns while not game.game_is_over(): # Get the symbol for the current player current_player = game.get_current_player() # Get the Player object assigned to that player player_object = players[current_player] # Ask the Player to calculate it's move based on the current state calculation_start = time.time() move = player_object.get_move(game) calculation_time = time.time() - calculation_start times[current_player] += calculation_time # Play the move calculated by the player game.play_position(move) # Print the new state of the board # game.print_board() print(f"Played position: ({COLUMN_NAMES[move[1]]}{move[0] + 1})")