예제 #1
0
    def get_move(self, game_state: Othello):
        """
        Will select the best move according to the value of the resulting game_state according to monte carlo
        :param game_state: current game state
        :return: best move in available moves
        """
        # Use start library if it is selected and still included
        if self._use_start_lib and game_state.get_turn_nr(
        ) < 21:  # check whether start move match
            moves = self._start_tables.get_available_moves_of_start_tables(
                game_state)
            if len(moves) > 0:
                return util.translate_move_to_pair(moves[random.randrange(
                    len(moves))])
        # According to experience the number of moves to consider decreases relevantly after reaching a certain
        # turn number. Therefore it is possible to increase the search depth without loosing to much time.
        # We dynamically increase the search depth after reaching turn_number 40
        search_depth = self._search_depth
        turn_number = game_state.get_turn_nr()
        if turn_number > 40:
            search_depth += turn_number // 10
        # Dict used to store a list of the moves resulting in a state with the respective value
        best_moves = dict()
        # Evaluate each available move
        for move in game_state.get_available_moves():
            # Play the move to get the resulting state
            next_state = game_state.deepcopy()
            next_state.play_position(move)

            # Evaluate the state using the selected function
            if self._use_monte_carlo:
                result = -AlphaBetaPruning.value_monte_carlo(
                    next_state,
                    search_depth - 1,
                    self._heuristic,
                    mc_count=self._mc_count)
            else:
                result = -AlphaBetaPruning.value(
                    next_state, self._search_depth - 1, self._heuristic)

            # Append the move to the list of states with that value
            if result not in best_moves.keys():
                best_moves[result] = []
            best_moves[result].append(move)

        # Determine the best result
        best_result = max(best_moves.keys())
        if self._use_monte_carlo:
            print(AlphaBetaPruning.value_monte_carlo.cache_info())
            AlphaBetaPruning.value_monte_carlo.cache_clear()
        else:
            print(AlphaBetaPruning.value.cache_info())
            AlphaBetaPruning.value.cache_clear()
        # Play one random move with the best possible result
        return best_moves[best_result][random.randrange(
            len(best_moves[best_result]))]
예제 #2
0
    def get_available_moves_of_start_tables(self, game: Othello):
        """
        search self._start_table for move sequences starting with the one of game and get next elements of those
        :return: list of available moves
        """
        if len(self._start_tables) == 0:
            self._init_start_tables()

        turn_nr = game.get_turn_nr()
        available_moves = []
        taken_mv = game.get_taken_mvs_text()
        for move_sequence in self._start_tables:
            turn = 0
            for move in move_sequence:
                # move was played
                if turn < turn_nr:
                    if taken_mv[turn] != move:
                        # move is different to start_table
                        break
                # if start sequence is finished
                elif move != "nan":
                    available_moves.append(move)
                    break
                turn += 1
        available_moves = list(dict.fromkeys(available_moves))
        if "nan" in available_moves:
            available_moves.remove("nan")
        return available_moves
예제 #3
0
    def heuristic(current_player, game_state: Othello):
        """
        Calculates the value of game_state for current_player according to the Stored MonteCarlo Heuristic
        current_player is coded as the constants EMPTY_CELL, PLAYER_ONE and PLAYER_TWO
          form constants.py. Therefore the parameter is an integer values.
        """

        moves = game_state.get_available_moves()
        turn_nr = game_state.get_turn_nr()
        # get maximum of likelihood values
        return max([database.db.get_change_of_winning(move, turn_nr, current_player) for move in moves])