예제 #1
0
    def get_move(self, game_state, possible_moves):
        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
        if len(possible_moves) == 1:
            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move in case Minimax does not return an answer:
        best_move = possible_moves[0]

        # Initialize Minimax algorithm, still not running anything
        minimax = MiniMaxWithAlphaBetaPruning(
            self.utility, self.color, self.no_more_time,
            self.selective_deepening_criterion)

        # Iterative deepening until the time runs out.
        while True:

            print(
                'going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'
                .format(
                    current_depth, self.time_for_current_move -
                    (time.process_time() - self.clock), prev_alpha, best_move))

            try:
                (alpha, move), run_time = run_with_limited_time(
                    minimax.search,
                    (game_state, current_depth, -INFINITY, INFINITY, True), {},
                    self.time_for_current_move -
                    (time.process_time() - self.clock))
            except (ExceededTimeError, MemoryError):
                print('no more time, achieved depth {}'.format(current_depth))
                break

            if self.no_more_time():
                print('no more time')
                break

            prev_alpha = alpha
            best_move = move

            if alpha == INFINITY:
                print('the move: {} will guarantee victory.'.format(best_move))
                break

            if alpha == -INFINITY:
                print('all is lost')
                break

            current_depth += 1

        if self.turns_remaining_in_round == 1:
            self.turns_remaining_in_round = self.k
            self.time_remaining_in_round = self.time_per_k_turns
        else:
            self.turns_remaining_in_round -= 1
            self.time_remaining_in_round -= (time.process_time() - self.clock)
        return best_move
예제 #2
0
    def run(self):
        """The main loop.
        :return: The winner.
        """

        white_player_exceeded = self.setup_player(sys.modules[self.white_player].Player, WHITE_PLAYER)
        black_player_exceeded = self.setup_player(sys.modules[self.black_player].Player, BLACK_PLAYER)
        winner = self.handle_time_expired(white_player_exceeded, black_player_exceeded)
        if winner:
            return winner

        game_state = gameutils.GameState()
        curr_player_idx = 0

        remaining_run_times = self.remaining_times[:]
        k_count = 0
        turns_elapsed = 0

        # Running the actual game loop. The game ends if someone is left out of moves,
        # exceeds his time or maximum turns limit was reached.
        while True:
            gameutils.draw(game_state, self.verbose)

            player = self.players[curr_player_idx]
            remaining_run_time = remaining_run_times[curr_player_idx]
            try:
                possible_moves = game_state.get_possible_moves()
                self.print_if_verbose('Possible moves: {}'.format(possible_moves))
                if not possible_moves:
                    winner = self.make_winner_result(0 if curr_player_idx == 1 else 1)
                    break
                move_idx, run_time = utils.run_with_limited_time(
                    player.get_move, (copy.deepcopy(game_state), possible_moves), {}, remaining_run_time)
                remaining_run_times[curr_player_idx] -= run_time
                if remaining_run_times[curr_player_idx] < 0:
                    raise utils.ExceededTimeError
            except (utils.ExceededTimeError, MemoryError):
                self.print_if_verbose('Player {} exceeded resources.'.format(player))
                winner = self.make_winner_result(0 if curr_player_idx == 1 else 1)
                break

            game_state.perform_move(possible_moves[move_idx])
            self.print_if_verbose('Player ' + repr(player) + ' performed the move: ' + repr(possible_moves[move_idx]))
            curr_player_idx = (curr_player_idx + 1) % 2

            if curr_player_idx == 0:
                # White and black played.
                k_count = (k_count + 1) % self.k
                if k_count == 0:
                    # K rounds completed. Resetting timers.
                    remaining_run_times = self.remaining_times[:]

                turns_elapsed += 1
                if turns_elapsed == self.maximum_turns_allowed:
                    winner = self.make_winner_result(-1)
                    break

        self.end_game(winner, turns_elapsed)
        return winner
예제 #3
0
    def run(self):
        """The main loop.
        :return: The winner.
        """
        # Setup each player
        x_player_exceeded = self.setup_player(
            sys.modules[self.x_player].Player, X_PLAYER)
        o_player_exceeded = self.setup_player(
            sys.modules[self.o_player].Player, O_PLAYER)
        winner = self.handle_time_expired(x_player_exceeded, o_player_exceeded)
        if winner:  # One of the players exceeded the setup time
            return winner

        board_state = GameState()
        remaining_run_times = copy.deepcopy(self.player_move_times)
        k_count = 0

        # Running the actual game loop. The game ends if someone is left out of moves,
        # or exceeds his time.
        while True:
            if self.verbose == 'y':
                board_state.draw_board()

            player = self.players[board_state.curr_player]
            remaining_run_time = remaining_run_times[board_state.curr_player]
            try:
                possible_moves = board_state.get_possible_moves()
                if not possible_moves:
                    winner = self.make_winner_result(board_state.get_winner())
                    break
                # Get move from player
                move, run_time = utils.run_with_limited_time(
                    player.get_move,
                    (copy.deepcopy(board_state), possible_moves), {},
                    remaining_run_time * 1.5)

                remaining_run_times[board_state.curr_player] -= run_time
                if remaining_run_times[board_state.curr_player] < 0:
                    raise utils.ExceededTimeError
            except (utils.ExceededTimeError, MemoryError):
                print('Player {} exceeded resources.'.format(player))
                winner = self.make_winner_result(
                    OPPONENT_COLOR[board_state.curr_player])
                break

            board_state.perform_move(move[0], move[1])
            if self.verbose == 'y':
                print('Player ' + repr(player) + ' performed the move: [' +
                      str(move[0]) + ', ' + str(move[1]) + ']')

            if board_state.curr_player == X_PLAYER:
                k_count = (k_count + 1) % self.k
                if k_count == 0:
                    # K rounds completed. Resetting timers.
                    remaining_run_times = copy.deepcopy(self.player_move_times)

        self.end_game(winner)
        return winner
예제 #4
0
파일: run_amazons.py 프로젝트: itaicaspi/AI
    def run(self):
        """The main loop.
        :return: The winner.
        """

        white_player_exceeded = self.setup_player(sys.modules[self.white_player].Player, WHITE_PLAYER)
        black_player_exceeded = self.setup_player(sys.modules[self.black_player].Player, BLACK_PLAYER)
        winner = self.handle_time_expired(white_player_exceeded, black_player_exceeded)
        if winner:
            return winner

        board_state = amazons_board.amazonsBoard()
        curr_player_idx = 0

        remaining_run_times = self.remaining_times[:]
        k_count = 0

        # Running the actual game loop. The game ends if someone is left out of moves,
        # or exceeds his time.
        while True:
            if self.printPref == 'y':
                board_state.printBoard()

            player = self.players[curr_player_idx]
            remaining_run_time = remaining_run_times[curr_player_idx]
            try:
                possible_moves = board_state.legalMoves()
                if not possible_moves:
                    winner = self.make_winner_result(0 if curr_player_idx == 1 else 1)
                    break
                move, run_time = utils.run_with_limited_time(
                    player.get_move, (copy.deepcopy(board_state), possible_moves), {}, remaining_run_time*1.5)
                remaining_run_times[curr_player_idx] -= run_time
                if remaining_run_times[curr_player_idx] < 0:
                    raise utils.ExceededTimeError
            except (utils.ExceededTimeError, MemoryError):
                print('Player {} exceeded resources.'.format(player))
                winner = self.make_winner_result(0 if curr_player_idx == 1 else 1)
                break

            board_state.doMove(move)
            if self.printPref == 'y':
                print('Player ' + repr(player) + ' performed the move: ' + repr(move))
            curr_player_idx = (curr_player_idx + 1) % 2

            if curr_player_idx == 0:
                # White and black played.
                k_count = (k_count + 1) % self.k
                if k_count == 0:
                    # K rounds completed. Resetting timers.
                    remaining_run_times = self.remaining_times[:]

        self.end_game(winner)
        return winner
예제 #5
0
파일: __init__.py 프로젝트: itaicaspi/AI
    def get_move(self, board_state, possible_moves):
        self.move_index += 2
        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
        if len(possible_moves) == 1:
            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move:
        best_move = possible_moves[0]

        minimax = SelectiveMiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time, self.w)

        # Iterative deepening until the time runs out.
        while True:
            if self.no_more_time():
                print('no more time')
                break

            print('going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'.format(
                current_depth, self.time_for_current_move - (time.process_time() - self.clock), prev_alpha, best_move))

            try:
                (alpha, move), run_time = run_with_limited_time(
                    minimax.search, (board_state, current_depth, -INFINITY, INFINITY, True), {},
                    self.time_for_current_move - (time.process_time() - self.clock))
            except (ExceededTimeError, MemoryError):
                print('no more time')
                break

            prev_alpha = alpha
            best_move = move

            if alpha == INFINITY:
                print('the move: {} will guarantee victory.'.format(best_move))
                break

            if alpha == -INFINITY:
                print('all is lost')
                break

            current_depth += 1

        if self.turns_remaining_in_round == 1:
            self.turns_remaining_in_round = self.k
            self.time_remaining_in_round = self.time_per_k_turns
        else:
            self.turns_remaining_in_round -= 1
            self.time_remaining_in_round -= (time.process_time() - self.clock)
        return best_move
예제 #6
0
    def setup_player(self, player_class, player_type):
        """ An auxiliary function to populate the players list, and measure setup times on the go.

        :param player_class: The player class that should be initialized, measured and put into the list.
        :param player_type: Player type, passed as an argument to the player.
        :return: A boolean. True if the player exceeded the given time. False otherwise.
        """
        try:
            player, measured_time = utils.run_with_limited_time(
                player_class, (self.setup_time, player_type, self.time_per_k_turns, self.k), {}, self.setup_time*1.5)
        except MemoryError:
            return True

        self.players[player_type] = player
        return measured_time > self.setup_time
예제 #7
0
파일: run_amazons.py 프로젝트: itaicaspi/AI
    def setup_player(self, player_class, player_color):
        """ An auxiliary function to populate the players list, and measure setup times on the go.

        :param player_class: The player class that should be initialized, measured and put into the list.
        :param player_color: Player color, passed as an argument to the player.
        :return: A boolean. True if the player exceeded the given time. False otherwise.
        """
        try:
            player, measured_time = utils.run_with_limited_time(
                player_class, (self.setup_time, player_color, self.time_per_k_turns, self.k), {}, self.setup_time*1.5)
        except MemoryError:
            return True

        self.players.append(player)
        return measured_time > self.setup_time
예제 #8
0
    def get_move(self, game_state, possible_moves):

        """
        This method is the same as the get_move method of the simple_player, but with a fix of the time management bug
        found in simple_player that is not counting a move in case this move is the only possible move, thus makes a
        mis-synchronization between the internal time calculation of the class and the external time calculation which
        ultimately results in a timeout.
        """

        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05

        if len(possible_moves) == 1:

            # If this was the last turn in current round.
            if self.turns_remaining_in_round == 1:
                self.turns_remaining_in_round = self.k  # Reset turns count.
                self.time_remaining_in_round = self.time_per_k_turns  # Reset time count.

            else:
                self.turns_remaining_in_round -= 1  # Decrease turns amount by 1.
                self.time_remaining_in_round -= (time.process_time() - self.clock)  # Update remaining time.

            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move in case Minimax does not return an answer.
        best_move = possible_moves[0]

        # Initialize Minimax algorithm, still not running anything.
        minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time,
                                              self.selective_deepening_criterion)

        # Iterative deepening until the time runs out.
        while True:

            print('going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'.format(
                current_depth,
                self.time_for_current_move - (time.process_time() - self.clock),
                prev_alpha,
                best_move))

            try:
                (alpha, move), run_time = run_with_limited_time(
                    minimax.search, (game_state, current_depth, -INFINITY, INFINITY, True), {},
                    self.time_for_current_move - (time.process_time() - self.clock))

            except (ExceededTimeError, MemoryError):
                print('no more time, achieved depth {}'.format(current_depth))
                break

            if self.no_more_time():
                print('no more time')
                break

            prev_alpha = alpha
            best_move = move

            if alpha == INFINITY:
                print('the move: {} will guarantee victory.'.format(best_move))
                break

            if alpha == -INFINITY:
                print('all is lost')
                break

            current_depth += 1

        # If this was the last turn in current round.
        if self.turns_remaining_in_round == 1:
            self.turns_remaining_in_round = self.k
            self.time_remaining_in_round = self.time_per_k_turns
        else:
            self.turns_remaining_in_round -= 1
            self.time_remaining_in_round -= (time.process_time() - self.clock)
        return best_move
예제 #9
0
    def get_move(self, game_state, possible_moves):
        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
        if len(possible_moves) == 1:  # update time and turns
            if self.turns_remaining_in_round == 1:
                self.turns_remaining_in_round = self.k
                self.time_remaining_in_round = self.time_per_k_turns
            else:
                self.turns_remaining_in_round -= 1
                self.time_remaining_in_round -= (time.process_time() -
                                                 self.clock)
            self.curr_board = game_state.board  # save game board
            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move in case Minimax does not return an answer:
        best_move = possible_moves[0]

        # Initialize Minimax algorithm, still not running anything
        minimax = MiniMaxWithAlphaBetaPruning(
            self.utility, self.color, self.no_more_time,
            self.selective_deepening_criterion)

        # Iterative deepening until the time runs out.
        while True:
            time_for_current_depth: float
            print(
                'going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'
                .format(
                    current_depth, current_depth, self.time_for_current_move -
                    (time.process_time() - self.clock), prev_alpha, best_move))
            # The array is init for 6 depth (the average depth) if he succeeded more than that give the remain time
            if current_depth - 1 > 5:
                time_for_current_depth = self.time_for_current_move - (
                    time.process_time() - self.clock)
            else:
                # Deeper in the tree get more time (see array values)
                time_for_current_depth = self.time_for_current_move * self.split_time_array[
                    current_depth - 1]
            try:
                (alpha, move), run_time = run_with_limited_time(
                    minimax.search,
                    (game_state, current_depth, -INFINITY, INFINITY, True), {},
                    time_for_current_depth)
            except (ExceededTimeError, MemoryError):
                print('no more time, achieved depth {}'.format(current_depth))
                break

            if self.no_more_time():
                print('no more time')
                break

            prev_alpha = alpha
            best_move = move

            if alpha == INFINITY:
                print('the move: {} will guarantee victory.'.format(best_move))
                break

            if alpha == -INFINITY:
                print('all is lost')
                break

            current_depth += 1

        if self.turns_remaining_in_round == 1:
            self.turns_remaining_in_round = self.k
            self.time_remaining_in_round = self.time_per_k_turns
        else:
            self.turns_remaining_in_round -= 1
            self.time_remaining_in_round -= (time.process_time() - self.clock)
        self.curr_board = game_state.board  # save game board
        return best_move
예제 #10
0
    def run(self):
        """The main loop.
        :return: The winner.
        """
        # Setup each player
        red_player_exceeded = self.setup_player(
            sys.modules[self.red_player].Player, RED_PLAYER)
        black_player_exceeded = self.setup_player(
            sys.modules[self.black_player].Player, BLACK_PLAYER)
        winner = self.handle_time_expired(red_player_exceeded,
                                          black_player_exceeded)
        if winner:  # One of the players exceeded the setup time
            return winner

        board_state = GameState()
        remaining_run_times = copy.deepcopy(self.player_move_times)
        k_count = 0

        # Running the actual game loop. The game ends if someone is left out of moves,
        # or exceeds his time.
        while True:
            if self.verbose == 'y':
                board_state.draw_board()

            player = self.players[board_state.curr_player]
            remaining_run_time = remaining_run_times[board_state.curr_player]
            try:
                possible_moves = board_state.get_possible_moves()
                if not possible_moves:
                    winner = self.make_winner_result(
                        OPPONENT_COLOR[board_state.curr_player])
                    break
                # Get move from player
                move, run_time = utils.run_with_limited_time(
                    player.get_move,
                    (copy.deepcopy(board_state), possible_moves), {},
                    remaining_run_time * 1.5)  ###

                remaining_run_times[board_state.curr_player] -= run_time
                if remaining_run_times[board_state.curr_player] < 0:
                    raise utils.ExceededTimeError

            except (utils.ExceededTimeError, MemoryError):
                print('Player {} exceeded resources.'.format(player))
                winner = self.make_winner_result(
                    OPPONENT_COLOR[board_state.curr_player])
                break

            board_state.perform_move(move)
            if self.verbose == 'y':
                print('Player ' + repr(player) + ' performed the move: ' +
                      str(move))

            if board_state.turns_since_last_jump >= MAX_TURNS_NO_JUMP:
                print('Number of turns without jumps exceeded {}'.format(
                    MAX_TURNS_NO_JUMP))
                winner = self.make_winner_result(TIE)
                break

            if board_state.curr_player == RED_PLAYER:
                # red and black played.
                k_count = (k_count + 1) % self.k
                if k_count == 0:
                    # K rounds completed. Resetting timers.
                    remaining_run_times = copy.deepcopy(self.player_move_times)

        self.end_game(winner)
        return winner
예제 #11
0
    def get_move(self, game_state, possible_moves):
        """
        This method returns the next move of the player by using a minimax search with Alpha-Beta pruning. In this
        method we apply a smart time management mechanism. The method performs a minimax search layer by layer, but in
        case the alpha value and best next move have not been changed in 3 layer cycles (Starting from 5 layer) we stop
        the search and the best move so far is returned, thus saving time for future moves.
        In the last turn of the cycle, we exhaust all the remaining time.
        """

        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05

        # If there is only one possible move.
        if len(possible_moves) == 1:

            # If this was the last turn in current round.
            if self.turns_remaining_in_round == 1:
                self.turns_remaining_in_round = self.k  # Reset turns count.
                self.time_remaining_in_round = self.time_per_k_turns  # Reset time count.

            else:
                self.turns_remaining_in_round -= 1  # Decrease turns amount by 1.
                self.time_remaining_in_round -= (
                    time.process_time() - self.clock)  # Update remaining time.

            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move in case Minimax does not return an answer.
        best_move = possible_moves[0]

        # Initialize Minimax algorithm, still not running anything.
        minimax = MiniMaxWithAlphaBetaPruning(
            self.utility, self.color, self.no_more_time,
            self.selective_deepening_criterion)

        roundsNotChanged = 0

        # Iterative deepening until the time runs out.
        while True:

            print(
                'going to depth: {}, remaining time: {}, prev_alpha: {}, best_move: {}'
                .format(
                    current_depth, self.time_for_current_move -
                    (time.process_time() - self.clock), prev_alpha, best_move))

            try:
                (alpha, move), run_time = run_with_limited_time(
                    minimax.search,
                    (game_state, current_depth, -INFINITY, INFINITY, True), {},
                    self.time_for_current_move -
                    (time.process_time() - self.clock))

            except (ExceededTimeError, MemoryError):
                print('no more time, achieved depth {}'.format(current_depth))
                break

            if self.no_more_time():
                print('no more time')
                break

            # Check if both alpha and next best move according to the last search has not been changed.
            if prev_alpha == alpha and move.origin_loc == best_move.origin_loc \
                    and move.target_loc == best_move.target_loc and current_depth > MIN_DEEPENING_DEPTH:

                # If so, then increment the counter.
                roundsNotChanged += 1

            else:  # alpha or next best move were changed - Reset counter.
                roundsNotChanged = 0

            # If alpha and best move have not been changed in 3 cycles, stop searching and save time for future moves.
            if roundsNotChanged == 3 and self.turns_remaining_in_round > 1:
                print(
                    'Best move and alpha has not changed for {} rounds, depth is {}.'
                    .format(roundsNotChanged, current_depth))
                break

            prev_alpha = alpha
            best_move = move

            if alpha == INFINITY:
                print('the move: {} will guarantee victory.'.format(best_move))
                break

            if alpha == -INFINITY:
                print('all is lost')
                break

            current_depth += 1

        # If this was the last turn in current round.
        if self.turns_remaining_in_round == 1:
            self.turns_remaining_in_round = self.k  # Reset turns count.
            self.time_remaining_in_round = self.time_per_k_turns  # Reset time count.
        else:
            self.turns_remaining_in_round -= 1  # Decrease turns amount by 1.
            self.time_remaining_in_round -= (time.process_time() - self.clock
                                             )  # Update remaining time.

        return best_move
예제 #12
0
    def run(self):
        """The main loop.
        :return: The winner.
        """

        white_player_exceeded = self.setup_player(
            sys.modules[self.white_player].Player, WHITE_PLAYER)
        black_player_exceeded = self.setup_player(
            sys.modules[self.black_player].Player, BLACK_PLAYER)
        winner = self.handle_time_expired(white_player_exceeded,
                                          black_player_exceeded)
        if winner:
            return winner

        game_state = gameutils.GameState()
        curr_player_idx = 0

        remaining_run_times = self.remaining_times[:]
        k_count = 0
        turns_elapsed = 0

        # Running the actual game loop. The game ends if someone is left out of moves,
        # exceeds his time or maximum turns limit was reached.
        while True:
            gameutils.draw(game_state, self.verbose)

            player = self.players[curr_player_idx]
            remaining_run_time = remaining_run_times[curr_player_idx]
            try:
                possible_moves = game_state.get_possible_moves()
                self.print_if_verbose(
                    'Possible moves: {}'.format(possible_moves))
                if not possible_moves:
                    winner = self.make_winner_result(0 if curr_player_idx ==
                                                     1 else 1)
                    break
                move_idx, run_time = utils.run_with_limited_time(
                    player.get_move,
                    (copy.deepcopy(game_state), possible_moves), {},
                    remaining_run_time)
                remaining_run_times[curr_player_idx] -= run_time
                if remaining_run_times[curr_player_idx] < 0:
                    raise utils.ExceededTimeError
            except (utils.ExceededTimeError, MemoryError):
                self.print_if_verbose(
                    'Player {} exceeded resources.'.format(player))
                winner = self.make_winner_result(0 if curr_player_idx ==
                                                 1 else 1)
                break

            game_state.perform_move(possible_moves[move_idx])
            self.print_if_verbose('Player ' + repr(player) +
                                  ' performed the move: ' +
                                  repr(possible_moves[move_idx]))
            curr_player_idx = (curr_player_idx + 1) % 2

            if curr_player_idx == 0:
                # White and black played.
                k_count = (k_count + 1) % self.k
                if k_count == 0:
                    # K rounds completed. Resetting timers.
                    remaining_run_times = self.remaining_times[:]

                turns_elapsed += 1
                if turns_elapsed == self.maximum_turns_allowed:
                    winner = self.make_winner_result(-1)
                    break

        self.end_game(winner, turns_elapsed)
        return winner