Beispiel #1
0
    def get_move(self, game_state, possible_moves):

        self.clock = time.clock()
        if len(possible_moves) == 1:
            return 0

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move:
        best_move = possible_moves[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_per_move - (time.clock() - self.clock), prev_alpha, best_move))
            minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time)
            alpha, move = minimax.search(game_state, current_depth, -INFINITY, INFINITY, True)

            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

            current_depth += 1

        return possible_moves.index(best_move)
Beispiel #2
0
    def get_move(self, game_state, possible_moves):

        self.clock = time.clock()
        if len(possible_moves) == 1:
            return 0

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move:
        best_move = possible_moves[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_per_move - (time.clock() - self.clock), prev_alpha, best_move))
            minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time)
            alpha, move = minimax.search(game_state, current_depth, -INFINITY, INFINITY, True)

            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

            current_depth += 1

        return possible_moves.index(best_move)
Beispiel #3
0
    def get_move(self, game_state, possible_moves):
        self.clock = time.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]

        # best_move = possible_moves[0]
        # next_state = copy.deepcopy(game_state)
        # next_state.perform_move(best_move[0], best_move[1])
        # # Choosing an arbitrary move
        # # Get the best move according the utility function
        # for move in possible_moves:
        #     new_state = copy.deepcopy(game_state)
        #     new_state.perform_move(move[0], move[1])
        #     if self.utility(new_state) > self.utility(next_state):
        #         next_state = new_state
        #         best_move = move
        best_move = possible_moves[0]
        min_max = MiniMaxWithAlphaBetaPruning(self.utility, self.color,
                                              self.no_more_time, None)
        depth = 1
        while self.no_more_time() is False:
            min_max_val = min_max.search(game_state, depth, -INFINITY,
                                         INFINITY, True)[1]
            best_move = min_max_val if min_max_val is not None else best_move
            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.time() - self.clock)

        return best_move
Beispiel #4
0
    def iterative_deepening(self, state):
        alpha_beta = MiniMaxWithAlphaBetaPruning(self.utility, self.color,
                                                 self.no_more_time, False)
        depth = 1
        optimal_move = None
        while True:
            _, move = alpha_beta.search(state, depth, -INFINITY, INFINITY,
                                        True)
            if move is None:
                break
            optimal_move = move
            depth += 1

        return optimal_move
Beispiel #5
0
 def get_move(self, game_state, possible_moves):
     if len(possible_moves) == 1:
         return possible_moves[0]
     self.clock = time.time()
     self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - self.time_per_k_turns * 0.05
     minimaxObject = MiniMaxWithAlphaBetaPruning(
         self.utility, self.color, self.no_more_time,
         self.selective_deepening_criterion)
     D = 1
     (value, move) = (0, possible_moves[0])
     while not self.no_more_time():
         (value, move1) = minimaxObject.search(game_state, D, -INFINITY,
                                               INFINITY, True)
         if not self.no_more_time():
             move = move1
         D = D + 1
     return move
Beispiel #6
0
    def get_move(self, game_state, possible_moves):
        self.clock = time.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]

        best_move = possible_moves[0]
        next_state = copy.deepcopy(game_state)
        next_state.perform_move(best_move[0], best_move[1])
        best_util = self.utility(next_state)

        min_max = MiniMaxWithAlphaBetaPruning(
            self.utility, self.color, self.no_more_time,
            self.selective_deepening_criterion)

        i = 1
        alpha = -INFINITY
        max = -INFINITY
        # print("search time is ", self.time_for_current_move)
        # start_time = time.time()
        depth = 0
        while not self.no_more_time():
            # print("clock ", time.time() - start_time)
            curr_best_util, curr_best_move = min_max.search(
                game_state, i, alpha, INFINITY, True)
            depth += 1
            if curr_best_util > best_util:
                best_move = curr_best_move
                best_util = curr_best_util
            if curr_best_util > max:
                alpha = curr_best_util
                max = curr_best_util
            i += 1
        # print("clock ", time.time() - start_time)

        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.time() - self.clock)

        #print("alpha_beta depth : ",depth)
        return best_move
Beispiel #7
0
    def get_move(self, board_state, possible_moves):

        self.clock = time.process_time()
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round -0.5
        if len(possible_moves) == 1:
            return possible_moves[0]

        current_depth = 1
        prev_alpha = -INFINITY

        # Choosing an arbitrary move:
        best_move = possible_moves[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))
            minimax = MiniMaxWithAlphaBetaPruning(self.utility, self.color, self.no_more_time)
            alpha, move = minimax.search(board_state, current_depth, -INFINITY, INFINITY, True)

            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

            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
Beispiel #8
0
class Player(abstract.AbstractPlayer):
    def __init__(self, setup_time, player_color, time_per_k_turns, k):
        abstract.AbstractPlayer.__init__(self, setup_time, player_color,
                                         time_per_k_turns, k)
        self.clock = time.time()
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05
        self.algorithm = MiniMaxWithAlphaBetaPruning(
            utility=self.utility,
            my_color=self.color,
            no_more_time=self.no_more_time,
            selective_deepening=self.selective_deeping)

        self.opening_book = create_better_opening_book(b_create_file=False)

        self.last_board = []
        for i in range(BOARD_COLS):
            self.last_board.append([EM] * BOARD_ROWS)

        for x in range(BOARD_COLS):
            for y in range(BOARD_ROWS):
                self.last_board[x][y] = EM

        # Starting pieces:
        self.last_board[3][3] = X_PLAYER
        self.last_board[3][4] = O_PLAYER
        self.last_board[4][3] = O_PLAYER
        self.last_board[4][4] = X_PLAYER

        self.moves = ""

    def __repr__(self):
        return '{} {}'.format(abstract.AbstractPlayer.__repr__(self),
                              '- competition_player')

    def no_more_time(self):
        time_passed = (time.time() - self.clock)
        self.time_for_current_move -= time_passed
        self.time_remaining_in_round -= time_passed
        self.clock = time.time()
        if self.time_for_current_move <= 0.05 or self.time_remaining_in_round <= 0.05:
            return True
        return False

    def time_for_step(self):
        return (self.split_time_equally(PERCENTAGE_OF_TIME_TO_SPLIT_EQUALLY * self.time_remaining_in_round) + \
               self.split_time_not_equally(
                   PERCENTAGE_OF_TIME_TO_SPLIT_NOT_EQUALLY * self.time_remaining_in_round))*0.97

    def split_time_equally(self, time_remaining):
        return time_remaining / self.turns_remaining_in_round

    def split_time_not_equally(self, time_remaining):
        sum_of_remaining_turns = sum(range(self.turns_remaining_in_round + 1))
        return time_remaining * (self.turns_remaining_in_round /
                                 sum_of_remaining_turns)

    def get_move(self, game_state, possible_moves):
        depth = 0
        self.time_for_current_move = self.time_for_step()
        self.clock = time.time()

        best_move = None
        max_value = 0
        reached_leaves = False
        while not self.no_more_time() and not reached_leaves:
            depth += 1
            [value, move,
             reached_leaves] = self.algorithm.search(game_state, depth,
                                                     -INFINITY, INFINITY, True)
            if best_move is None or value > max_value:
                max_value = value
                best_move = move

        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

        return best_move if best_move is not None else possible_moves[0]

    def find_opposite_move(self, game_state):
        for i in range(BOARD_COLS):
            for j in range(BOARD_ROWS):
                if self.last_board[i][j] == EM and game_state.board[i][j] != EM:
                    return i, j
        return None

    def opening_move(self, game_state):
        if len(self.moves) / 2 > NUM_OF_MOVES_IN_OPENING_BOOK:
            return None
        other_player_move = self.find_opposite_move(game_state)
        if other_player_move is None:
            other_player_move_as_str = ""
        else:
            other_player_move_as_str = xy_to_a1(other_player_move)
        self.moves += other_player_move_as_str

        return a1_to_xy(self.opening_book[
            self.moves]) if self.moves in self.opening_book else None

    def selective_deeping(self, state):
        sensitive_spots = [(0, 1), (1, 0), (1, 1), (0, 6), (1, 6), (1, 7),
                           (6, 0), (6, 1), (7, 1), (7, 6), (6, 7), (6, 6)]
        corners = [(0, 0), (0, 7), (7, 0), (7, 7)]
        for move in state.get_possible_moves():
            if move in sensitive_spots:
                return True
            if move in corners:
                return True
        return False

    def utility(self, state):
        if len(state.get_possible_moves()) == 0:
            winner = state.get_winner()
            if winner == self.color:
                return INFINITY
            elif winner == TIE:
                return 0
            else:
                return -INFINITY

        my_in_corner = 0
        opp_in_corner = 0
        my_front = 0
        opp_front = 0
        my = 0
        opp = 0
        d = 0
        my_close_to_corner = 0
        opp_close_to_corner = 0
        opp_state = copy.deepcopy(state)
        X = [-1, -1, 0, 1, 1, 1, 0, -1]
        Y = [0, 1, 1, 1, 0, -1, -1, -1]
        piece_diff = [[0] * BOARD_ROWS] * BOARD_COLS
        piece_diff[0] = [20, -3, 11, 8, 8, 11, -3, 20]
        piece_diff[1] = [-3, -7, -4, 1, 1, -4, -7, -3]
        piece_diff[2] = [11, -4, 2, 2, 2, 2, -4, 11]
        piece_diff[3] = [8, 1, 2, -3, -3, 2, 1, 8]
        piece_diff[4] = [8, 1, 2, -3, -3, 2, 1, 8]
        piece_diff[5] = [11, -4, 2, 2, 2, 2, -4, 11]
        piece_diff[6] = [-3, -7, -4, 1, 1, -4, -7, -3]
        piece_diff[7] = [20, -3, 11, 8, 8, 11, -3, 20]
        if state.curr_player == X_PLAYER:
            opp_state.curr_player = O_PLAYER
        else:
            opp_state.curr_player = X_PLAYER

        grid = state.board
        for x in range(BOARD_COLS):
            for y in range(BOARD_ROWS):
                if grid[x][y] == self.color:
                    my += 1
                    d += piece_diff[x][y]
                elif grid[x][y] == OPPONENT_COLOR[self.color]:
                    opp += 1
                    d -= piece_diff[x][y]
                if grid[x][y] != ' ':
                    for k in range(BOARD_ROWS):
                        i = x + X[k]
                        j = y + Y[k]
                        if i >= 0 and i < BOARD_ROWS and j >= 0 and j < BOARD_ROWS and grid[
                                i][j] == EM:
                            if grid[x][y] == self.color:
                                my_front += 1
                            elif grid[x][y] == OPPONENT_COLOR[self.color]:
                                opp_front += 1
                            break

        if my_front > opp_front:
            front = -(100.0 * my_front) / (my_front + opp_front)
        elif my_front < opp_front:
            front = (100.0 * opp_front) / (my_front + opp_front)
        else:
            front = 0

        if my > opp:
            tiles = (100.0 * my) / (my + opp)
        elif my < opp:
            tiles = -(100.0 * opp) / (my + opp)
        else:
            tiles = 0

        if grid[0][0] == self.color:
            my_in_corner += 1
        elif grid[0][0] == OPPONENT_COLOR[self.color]:
            opp_in_corner += 1
        if grid[0][BOARD_ROWS - 1] == self.color:
            my_in_corner += 1
        elif grid[0][BOARD_ROWS - 1] == OPPONENT_COLOR[self.color]:
            opp_in_corner += 1
        if grid[BOARD_COLS - 1][0] == self.color:
            my_in_corner += 1
        elif grid[BOARD_COLS - 1][0] == OPPONENT_COLOR[self.color]:
            opp_in_corner += 1
        if grid[BOARD_COLS - 1][BOARD_ROWS - 1] == self.color:
            my_in_corner += 1
        elif grid[BOARD_COLS - 1][BOARD_ROWS -
                                  1] == OPPONENT_COLOR[self.color]:
            opp_in_corner += 1

        corners = 25 * (my_in_corner - opp_in_corner)
        my_options = len(state.get_possible_moves())
        opp_options = len(opp_state.get_possible_moves())

        if my_options > opp_options:
            options = (100.0 * my_options) / (my_options + opp_options)
        elif opp_options > my_options:
            options = -(100.0 * opp_options) / (my_options + opp_options)
        else:
            options = 0

        if grid[0][0] == EM:
            if grid[0][1] == self.color:
                my_close_to_corner += 1
            elif grid[0][1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[1][1] == self.color:
                my_close_to_corner += 1
            elif grid[1][1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[1][0] == self.color:
                my_close_to_corner += 1
            elif grid[1][0] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
        if grid[0][BOARD_COLS - 1] == EM:
            if grid[0][BOARD_COLS - 2] == self.color:
                my_close_to_corner += 1
            elif grid[0][BOARD_COLS - 2] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[1][BOARD_COLS - 2] == self.color:
                my_close_to_corner += 1
            elif grid[1][BOARD_COLS - 2] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[1][BOARD_COLS - 1] == self.color:
                my_close_to_corner += 1
            elif grid[1][BOARD_COLS - 1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
        if grid[BOARD_ROWS - 1][0] == EM:
            if grid[BOARD_ROWS - 1][1] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 1][1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[BOARD_ROWS - 2][1] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 2][1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[BOARD_ROWS - 2][0] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 2][0] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
        if grid[BOARD_ROWS - 1][BOARD_COLS - 1] == EM:
            if grid[BOARD_ROWS - 2][BOARD_COLS - 1] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 2][BOARD_COLS -
                                      1] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[BOARD_ROWS - 2][BOARD_COLS - 2] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 2][BOARD_COLS -
                                      2] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1
            if grid[BOARD_ROWS - 1][BOARD_COLS - 2] == self.color:
                my_close_to_corner += 1
            elif grid[BOARD_ROWS - 1][BOARD_COLS -
                                      2] == OPPONENT_COLOR[self.color]:
                opp_close_to_corner += 1

        close_to_corner = -12.5 * (my_close_to_corner - opp_close_to_corner)

        return (10 * tiles) + (801.724 * corners) + (382.026 * close_to_corner) + (78.922 * options) + (74.396 * front) \
               + (10 * d)
Beispiel #9
0
class Player(abstract.AbstractPlayer):
    def __init__(self, setup_time, player_color, time_per_k_turns, k):
        abstract.AbstractPlayer.__init__(self, setup_time, player_color, \
                time_per_k_turns, k)
        self.clock = time.time()

        # We are simply providing (remaining time / remaining turns) for each \
        #       turn in round.
        # Taking a spare time of 0.05 seconds.
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
        self.time_for_current_move = self.time_remaining_in_round / \
                self.turns_remaining_in_round - 0.05
        # keep the game-moves as a string
        self.moves = ''
        self.last_state = GameState()

        # chose board configuration
        if self.color == O_PLAYER:
            # will be set after opponent first move
            self.book2reality = None
            self.reality2book = None
        else:
            self.book2reality = self.book2reality1
            self.reality2book = self.reality2book1

        self.alpha_beta_algorithm = MiniMaxWithAlphaBetaPruning(self.utility, \
                self.color, self.no_more_time, None)

        # for performence
        self.max_steps_left = 62

        # create opening book
        opening_book = {}
        f = open("best_70_opens.gam", 'r')
        # FIXME: remove error check before submmision
        if not f:
            print("cannot open file")
            sys.exit(1)

        # assume we play first and update otherwise
        first_move_index = 0
        if self.color == O_PLAYER:
            first_move_index = 1

        for line in f:
            tmp = line.split(' ')[1]
            tmp = re.split(r'[+-]', tmp)
            moves = ''.join(tmp)
            for i in range(first_move_index, 10, 2):
                tmp = re.split('r[+-]', moves)
                key = moves[0:2 * i]
                if key not in opening_book:
                    opening_book[key] = moves[2 * i:2 * i + 2]
        f.close()
        self.opening_book = opening_book

    def get_move(self, game_state, possible_moves):
        self.clock = time.time()
        self.time_for_current_move = self.time_remaining_in_round / \
                self.turns_remaining_in_round - 0.05

        self.max_steps_left -= 2

        # discover last move done by opponent
        opponent_move_str_format = ''
        for x in range(BOARD_COLS):
            for y in range(BOARD_ROWS):
                if self.last_state.board[x][
                        y] == EM and game_state.board[x][y] != EM:
                    opponent_move_str_format = TO_LETTER[str(x + 1)] + str(y +
                                                                           1)

        # chose the board_configuration - firs opponent move became 'd3' in
        # oppening book
        if self.book2reality == None:
            if opponent_move_str_format == 'd6':
                self.book2reality = self.book2reality1
                self.reality2book = self.reality2book1
            elif opponent_move_str_format == 'e3':
                self.book2reality = self.book2reality2
                self.reality2book = self.reality2book2
            elif opponent_move_str_format == 'c5':
                self.book2reality = self.book2reality3
                self.reality2book = self.reality2book3
            elif opponent_move_str_format == 'f4':
                self.book2reality = self.book2reality4
                self.reality2book = self.reality2book4
            else:
                raise ImpossibleBoardTransform

        # append opponent move to self.moves - this will represent the key.
        # if we play first we will append '' to '' (nothing will hapen)
        self.moves += self.reality2book(opponent_move_str_format)

        # this case is handled in run_game.py
        assert (len(possible_moves) != 0)

        # find the best move
        if len(possible_moves) == 1:
            best_move = possible_moves[0]
        else:
            # check if next move can be determined from oppening book
            oppening_book_res = self.opening_move()
            if oppening_book_res != None:
                best_move = oppening_book_res
            else:
                curr_depth = 1

                # there is maximum max_steps_left steps in the game
                last_move = None
                while curr_depth < self.max_steps_left:
                    try:
                        _, best_move = self.alpha_beta_algorithm.search( \
                                game_state, curr_depth, -INFINITY*2, INFINITY*2, True)

                        if last_move != best_move:
                            game_state_copy = copy.deepcopy(game_state)
                            game_state_copy.perform_move(
                                best_move[0], best_move[1])
                            self.last_state = game_state_copy

                        last_move = best_move
                        curr_depth += 1
                    except ExceededTimeError:
                        break

        to_be_append = TO_LETTER[str(best_move[0] + 1)] + str(best_move[1] + 1)
        self.moves += self.reality2book(to_be_append)

        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.time() - self.clock)

        return best_move

    def opening_move(self):

        # check if we can find the next move in the oppening book
        if self.moves not in self.opening_book:
            return None

        res = self.book2reality(self.opening_book[self.moves])
        return [int(TO_DIGIT[res[0]]) - 1, int(res[1]) - 1]

    def book2reality1(self, str_move):
        old_digit = str_move[1]
        old_letter = str_move[0]
        new_digit = str(BOARD_ROWS - int(old_digit) + 1)
        new_letter = old_letter
        return new_letter + new_digit

    def reality2book1(self, str_move):
        if str_move == '':
            return ''
        return self.book2reality1(str_move)

    def book2reality2(self, str_move):
        old_digit = str_move[1]
        old_letter = str_move[0]
        new_digit = old_digit
        new_letter = REVERSE_LETTER[old_letter]
        return new_letter + new_digit

    def reality2book2(self, str_move):
        if str_move == '':
            return ''
        return self.book2reality2(str_move)

    def book2reality3(self, str_move):
        old_digit = str_move[1]
        old_letter = str_move[0]
        new_digit = TO_LETTER[old_digit]
        new_letter = TO_DIGIT[REVERSE_LETTER[old_letter]]
        return new_digit + new_letter

    def reality2book3(self, str_move):
        if str_move == '':
            return ''
        return self.book2reality4(str_move)

    def book2reality4(self, str_move):
        old_digit = str_move[1]
        old_letter = str_move[0]
        new_digit = REVERSE_LETTER[TO_LETTER[old_digit]]
        new_letter = TO_DIGIT[old_letter]
        return new_digit + new_letter

    def reality2book4(self, str_move):
        if str_move == '':
            return ''
        return self.book2reality3(str_move)
#------------------------------------------------------------------------------

    def __is_stable(self, state, J, I):

        # a corner is always stable
        if (I == 0 or I == BOARD_ROWS) and (J == 0 or J == BOARD_COLS):
            return True

        elif I == 0 or I == BOARD_ROWS - 1:
            res1 = True
            res2 = True
            for j in range(J):
                if state.board[j][I] == OPPONENT_COLOR[self.color]:
                    res1 = False
                    break
            for j in range(J, BOARD_COLS):
                if state.board[j][I] == OPPONENT_COLOR[self.color]:
                    res2 = False
                    break
            return res1 or res2

        elif J == 0 or J == BOARD_COLS - 1:
            res1 = True
            res2 = True
            for i in range(I):
                if state.board[J][i] == OPPONENT_COLOR[self.color]:
                    res1 = False
                    break
            for i in range(I, BOARD_ROWS):
                if state.board[J][i] == OPPONENT_COLOR[self.color]:
                    res2 = False
                    break
            return res1 or res2

        # don't let this method be applied on a non-edge index
        else:
            raise NonEdgeIndex

    def __score_utility(self, state):
        CORNER_FAC = 100
        STABLE_EDGE_FAC = 20
        EDGE_FAC = 5
        INTER_FAC = 1

        my_u = 0
        op_u = 0
        for x in range(BOARD_COLS):
            for y in range(BOARD_ROWS):

                # is a corner
                if (x == 0 or x == BOARD_COLS - 1) and (y == 0 or y
                                                        == BOARD_ROWS - 1):
                    if state.board[x][y] == self.color:
                        my_u += CORNER_FAC
                    elif state.board[x][y] == OPPONENT_COLOR[self.color]:
                        op_u += CORNER_FAC

                # is an edge
                elif x == 0 or x == BOARD_COLS - 1 or y == 0 or y == BOARD_ROWS - 1:

                    # is stable
                    if self.__is_stable(state, x, y):
                        if state.board[x][y] == self.color:
                            my_u += STABLE_EDGE_FAC
                        elif state.board[x][y] == OPPONENT_COLOR[self.color]:
                            op_u += STABLE_EDGE_FAC

                    # is not stable
                    else:
                        if state.board[x][y] == self.color:
                            my_u += EDGE_FAC
                        elif state.board[x][y] == OPPONENT_COLOR[self.color]:
                            op_u -= EDGE_FAC

                # is internal
                else:
                    if state.board[x][y] == self.color:
                        my_u += INTER_FAC
                    elif state.board[x][y] == OPPONENT_COLOR[self.color]:
                        op_u -= INTER_FAC

        if my_u == 0:
            # I have no tools left
            return -INFINITY
        elif op_u == 0:
            # The opponent has no tools left
            return INFINITY
        else:
            return my_u - op_u

    def __mobility_utility(self, state):
        MOBILITY_FAC = 1

        # when this function is called the current player is already the
        # opponent so we will change it to our player, check the value and
        # return it as it was
        op_moves = len(state.get_possible_moves())
        state.curr_player = OPPONENT_COLOR[state.curr_player]
        my_moves = len(state.get_possible_moves())
        state.curr_player = OPPONENT_COLOR[state.curr_player]

        return (my_moves - op_moves) * MOBILITY_FAC

    def utility(self, state):
        assert (len(state.get_possible_moves()) != 0)

        mobility_fac = 1
        score_fac = 1

        mobility_res = self.__mobility_utility(state)
        score_res = self.__score_utility(state)

        return mobility_res * mobility_fac + score_res * score_fac

#------------------------------------------------------------------------------

    def selective_deepening_criterion(self, state):
        # Simple player does not selectively deepen into certain nodes.
        return False

    def no_more_time(self):
        return (time.time() - self.clock) >= self.time_for_current_move

    def __repr__(self):
        return '{} {}'.format(abstract.AbstractPlayer.__repr__(self),
                              'old_competition')
asssert(res5[0] == 13)
asssert(res6[0] == 10)

no_more_time2.time = 38
res5 = mma.search(root2, 10, True)
no_more_time2.time = 38
res6 = mma.search(root2, 10, False)
asssert(res5[0] == 13)
asssert(res6[0] == 10)


# check alpha betta
abp = MiniMaxWithAlphaBetaPruning(utility, 'X', no_more_time2, None)

no_more_time2.time = 38
res7 = abp.search(root, 10, -INFINITY, INFINITY, True)

no_more_time2.time = 38
res8 = abp.search(root, 10, -INFINITY, INFINITY, False)

no_more_time2.time = 38
res9 = abp.search(root, 2, -INFINITY, INFINITY, True)

no_more_time2.time = 38
res10 = abp.search(root, 2, -INFINITY, INFINITY, False)

asssert(res7[0] == 13)
asssert(res8[0] == 10)
asssert(res9[0] == 6)
asssert(res10[0] == 5)
Beispiel #11
0
class Player(abstract.AbstractPlayer):
    def __init__(self, setup_time, player_color, time_per_k_turns, k):
        abstract.AbstractPlayer.__init__(self, setup_time, player_color, \
                time_per_k_turns, k)
        self.clock = time.time()

        # We are simply providing (remaining time / remaining turns) for each \
        #       turn in round.
        # Taking a spare time of 0.05 seconds.
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
        self.time_for_current_move = self.time_remaining_in_round / \
                self.turns_remaining_in_round - 0.05

        self.alpha_beta_algorithm = MiniMaxWithAlphaBetaPruning(self.utility, \
                self.color, self.no_more_time, None)

        # for performence
        self.max_steps_left = 62

    def get_move(self, game_state, possible_moves):
        self.clock = time.time()
        self.time_for_current_move = self.time_remaining_in_round / \
                self.turns_remaining_in_round - 0.05

        self.max_steps_left -= 2

        if len(possible_moves) == 1:
            best_move = possible_moves[0]
        else:
            curr_depth = 1

            # there is maximum max_steps_left steps in the game
            while curr_depth < self.max_steps_left:
                try:
                    _, best_move = self.alpha_beta_algorithm.search( \
                            game_state, curr_depth, -INFINITY, INFINITY, True)
                    curr_depth += 1
                except ExceededTimeError:
                    break

        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.time() - self.clock)

        return best_move

    def utility(self, state):
        if len(state.get_possible_moves()) == 0:
            return INFINITY if state.curr_player != self.color else -INFINITY

        my_u = 0
        op_u = 0
        for x in range(BOARD_COLS):
            for y in range(BOARD_ROWS):
                if state.board[x][y] == self.color:
                    my_u += 1
                if state.board[x][y] == OPPONENT_COLOR[self.color]:
                    op_u += 1

        if my_u == 0:
            # I have no tools left
            return -INFINITY
        elif op_u == 0:
            # The opponent has no tools left
            return INFINITY
        else:
            return my_u - op_u

    def selective_deepening_criterion(self, state):
        # Simple player does not selectively deepen into certain nodes.
        return False

    def no_more_time(self):
        return (time.time() - self.clock) >= self.time_for_current_move

    def __repr__(self):
        return '{} {}'.format(abstract.AbstractPlayer.__repr__(self),
                              'alpha_beta')
Beispiel #12
0
class Player(AbstractPlayer):
    def __init__(self, setup_time, player_color, time_per_k_turns, k):
        AbstractPlayer.__init__(self, setup_time, player_color,
                                time_per_k_turns, k)

        self.clock = time.time()

        # We are simply providing (remaining time / remaining turns) for each turn in round.
        # Taking a spare time of 0.05 seconds.
        self.turns_remaining_in_round = self.k
        self.time_remaining_in_round = self.time_per_k_turns
        self.time_for_current_move = self.time_remaining_in_round / self.turns_remaining_in_round - 0.05

        self.simple = simplePlayer(setup_time, player_color, time_per_k_turns,
                                   k)

        self.algorithm = MiniMaxWithAlphaBetaPruning(
            utility=self.simple.utility,
            my_color=self.color,
            no_more_time=self.no_more_time,
            selective_deepening=self.selective_deeping)

    def __repr__(self):
        return '{} {}'.format(abstract.AbstractPlayer.__repr__(self),
                              '- alpha_beta_player')

    def no_more_time(self):
        time_passed = (time.time() - self.clock)
        self.clock = time.time()
        self.time_for_current_move -= time_passed
        self.time_remaining_in_round -= time_passed
        if self.time_for_current_move <= 0.05 or self.time_remaining_in_round <= 0.05:
            return True
        return False

    def time_for_step(self):
        return (self.split_time_equally(PERCENTAGE_OF_TIME_TO_SPLIT_EQUALLY *
                                        self.time_remaining_in_round) +
                self.split_time_not_equally(
                    PERCENTAGE_OF_TIME_TO_SPLIT_NOT_EQUALLY *
                    self.time_remaining_in_round)) * 0.97

    def split_time_equally(self, time_remaining):
        return time_remaining / self.turns_remaining_in_round

    def split_time_not_equally(self, time_remaining):
        sum_of_remaining_turns = sum(range(self.turns_remaining_in_round + 1))
        return time_remaining * (self.turns_remaining_in_round /
                                 sum_of_remaining_turns)

    def selective_deeping(self, state):
        sensitive_spots = [(0, 1), (1, 0), (1, 1), (0, 6), (1, 6), (1, 7),
                           (6, 0), (6, 1), (7, 1), (7, 6), (6, 7), (6, 6)]
        corners = [(0, 0), (0, 7), (7, 0), (7, 7)]
        for move in state.get_possible_moves():
            if move in sensitive_spots:
                return True
            if move in corners:
                return True
        return False

    def get_move(self, game_state, possible_moves):
        depth = 0
        self.time_for_current_move = self.time_for_step()
        self.clock = time.time()

        best_move = None
        max_value = 0
        reached_leaves = False
        while not self.no_more_time() and not reached_leaves:
            depth += 1
            [value, move,
             reached_leaves] = self.algorithm.search(game_state, depth,
                                                     -INFINITY, INFINITY, True)
            if best_move is None or value > max_value:
                max_value = value
                best_move = move

        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

        return best_move if best_move is not None else possible_moves[0]