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.book = OpeningBook() self.prev_state = GameState() self.moves_list = "" self.book_to_our_dic = self.build_book_to_our_dic() self.our_to_book_dic = self.build_our_to_book_dic()
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
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 = None # 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 # New fields - for section F self.dict_for_10_common_openings = self._calculate_ten_common_openings( ) self.moves_till_now = "" self.game_board = GameState().board if self.color == X_PLAYER: self.sign = '+' self.opponent_sign = '-' self.num_round = 1 else: self.sign = '-' self.opponent_sign = '+' self.num_round = 4 self.board_opening_lost_track = False
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 _is_in_immediate_danger(state: GameState, x: int, y: int, player_on_tile, x_direction: int, y_direction: int) -> bool: curr_x = x + x_direction curr_y = y + y_direction opposite_x = x - x_direction opposite_y = y - y_direction if not state.isOnBoard(x-x_direction, y-y_direction): return False if (state.board[curr_x][curr_y] == EM and state.board[opposite_x][opposite_y] == OPPONENT_COLOR[player_on_tile]) \ or (state.board[curr_x][curr_y] == OPPONENT_COLOR[player_on_tile] and state.board[opposite_x][opposite_y] == EM): return True
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._last_game_state = '' self._last_game_board = GameState().board self.opening_dict = ExtractMostPopularOpenningMoves(70) self.opponent_sign = '-' if self.color == 'X' else '+'
def simple_utility(state: GameState, color: str): if len(state.get_possible_moves()) == 0: return INFINITY if state.curr_player != 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] == color: my_u += 1 if state.board[x][y] == OPPONENT_COLOR[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
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.book = OpeningBook() self.prev_state = GameState() self.moves_list = "" self.book_to_our_dic = self.build_book_to_our_dic() self.our_to_book_dic = self.build_our_to_book_dic() 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 = self.opening_move(game_state) if best_move == None: 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 self.moves_list = self.moves_list + "+" + self.our_to_book_dic[ best_move[0]][best_move[1]] self.prev_state = next_state 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): mobility_adv = self.mobility_adv(state) if mobility_adv > 100 or mobility_adv < -100: return mobility_adv coin_adv = self.coin_adv(state) if coin_adv > 100 or coin_adv < -100: return coin_adv corner_adv = self.corner_adv(state) corner_closeness_adv = self.corner_closeness_adv(state) weight_total_adv = (0.50 * coin_adv) + (0.30 * corner_adv) + ( 0.15 * corner_closeness_adv) + (0.05 * mobility_adv) return weight_total_adv def coin_adv(self, state): my_coins = 0 op_coins = 0 for x in range(BOARD_COLS): for y in range(BOARD_ROWS): if state.board[x][y] == self.color: my_coins += 1 if state.board[x][y] == OPPONENT_COLOR[self.color]: op_coins += 1 if my_coins == 0: # I have no tools left return -INFINITY elif op_coins == 0: # The opponent has no tools left return INFINITY if my_coins > op_coins: coin_adv = (100.0 * my_coins) / (my_coins + op_coins) elif my_coins < op_coins: coin_adv = -(100.0 * op_coins) / (my_coins + op_coins) else: coin_adv = 0 return coin_adv def corner_adv(self, state): me, op = self.get_colors() my_corners = 0 op_corners = 0 if state.board[0][0] == me: my_corners += 1 elif state.board[0][0] == op: op_corners += 1 if state.board[0][7] == me: my_corners += 1 elif state.board[0][7] == op: op_corners += 1 if state.board[7][0] == me: my_corners += 1 elif state.board[7][0] == op: op_corners += 1 if state.board[7][7] == me: my_corners += 1 elif state.board[7][7] == op: op_corners += 1 corner_adv = 25 * (my_corners - op_corners) return corner_adv def get_colors(self): me = self.color if me == 'O': op = 'X' else: op = 'O' return me, op def corner_closeness_adv(self, state): me, op = self.get_colors() my_coins = 0 op_coins = 0 if state.board[0][0] == EM: if state.board[0][1] == me: my_coins += 1 elif state.board[0][1] == op: op_coins += 1 if state.board[1][1] == me: my_coins += 1 elif state.board[1][1] == op: op_coins += 1 if state.board[1][0] == me: my_coins += 1 elif state.board[1][0] == op: op_coins += 1 if state.board[0][7] == EM: if state.board[0][6] == me: my_coins += 1 elif state.board[0][6] == op: op_coins += 1 if state.board[1][6] == me: my_coins += 1 elif state.board[1][6] == op: op_coins += 1 if state.board[1][7] == me: my_coins += 1 elif state.board[1][7] == op: op_coins += 1 if state.board[7][0] == EM: if state.board[7][1] == me: my_coins += 1 elif state.board[7][1] == op: op_coins += 1 if state.board[6][1] == me: my_coins += 1 elif state.board[6][1] == op: op_coins += 1 if state.board[6][0] == me: my_coins += 1 elif state.board[6][0] == op: op_coins += 1 if state.board[7][7] == EM: if state.board[6][7] == me: my_coins += 1 elif state.board[6][7] == op: op_coins += 1 if state.board[6][6] == me: my_coins += 1 elif state.board[6][6] == op: op_coins += 1 if state.board[7][6] == me: my_coins += 1 elif state.board[7][6] == op: op_coins += 1 corner_closeness = -8.333 * (my_coins - op_coins) return corner_closeness def mobility_adv(self, state): me, op = self.get_colors() my_state = copy.deepcopy(state) my_state.curr_player = me my_possible_moves = len(my_state.get_possible_moves()) if my_possible_moves == 0: return -INFINITY op_state = copy.deepcopy(state) op_state.curr_player = op op_possible_moves = len(op_state.get_possible_moves()) if op_possible_moves == 0: return INFINITY if my_possible_moves > op_possible_moves: mobility = (100.0 * my_possible_moves) / (my_possible_moves + op_possible_moves) elif my_possible_moves < op_possible_moves: mobility = -(100.0 * op_possible_moves) / (my_possible_moves + op_possible_moves) else: mobility = 0 return mobility def selective_deepening_criterion(self, state): # Better 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), 'better') def opening_move(self, state): if len(self.moves_list) >= 30: return None if self.prev_state.board == state.board: book_move = self.book.dic[self.moves_list] self.moves_list = self.moves_list + book_move reg_move = self.book_to_our_dic[book_move[1:3]] self.prev_state.perform_move(reg_move[0], reg_move[1]) return reg_move opp_move = self.find_opp_move(state) if len(self.moves_list) % 2 == 0: opp_move = "+" + opp_move else: opp_move = "-" + opp_move self.moves_list = self.moves_list + opp_move self.prev_state = copy.deepcopy(state) if self.moves_list in self.book.dic.keys(): book_move = self.book.dic[self.moves_list] self.moves_list = self.moves_list + book_move reg_move = self.book_to_our_dic[book_move[1:3]] self.prev_state.perform_move(reg_move[0], reg_move[1]) return reg_move return None def build_our_to_book_dic(self): dic = {} for x in range(BOARD_COLS): dic[x] = {} for y in range(BOARD_ROWS): key = [x, y] val = chr(ord('h') - 7 + y) + chr(ord('8') - x) dic[x][y] = val return dic def build_book_to_our_dic(self): dic = {} for x in range(BOARD_COLS): for y in range(BOARD_ROWS): key = chr(ord('a') + x) + chr(ord('1') + y) val = [7 - y, x] dic[key] = val return dic def find_opp_move(self, state): for x in range(BOARD_COLS): for y in range(BOARD_ROWS): if (self.prev_state.board[x][y] == EM and state.board[x][y] != EM and state.board[x][y]): return self.our_to_book_dic[x][y]
import sys from players.AI2_302279138_303086854.better_player import Player from Reversi.board import GameState ## __init__ test player = Player(2, 'X', 10, 5) assert (player.moves == '') assert (player.last_state == GameState()) assert (player.book2reality == player.book2reality1) player = Player(2, 'O', 10, 5) assert (player.moves == '') assert (player.last_state == GameState()) assert (player.book2reality == None) # book2reality1 test assert (player.book2reality1('a1') == 'a8') assert (player.book2reality1('f7') == 'f2') # reality2book1 test assert (player.reality2book1('a8') == 'a1') assert (player.reality2book1('f2') == 'f7') assert (player.reality2book1('d6') == 'd3') # book2reality2 test assert (player.book2reality2('a1') == 'h1') assert (player.book2reality2('c4') == 'f4') # reality2book2 test assert (player.reality2book2('h1') == 'a1') assert (player.reality2book2('f4') == 'c4')
def better_utility(state: GameState, color: str): # Add 3 more parameters when calculating how much the state is 'good' opp_color = OPPONENT_COLOR[color] # Calculate Disks parameter curr_disks = 0 opp_disks = 0 for x in range(BOARD_COLS): for y in range(BOARD_ROWS): if state.board[x][y] == color: curr_disks += 1 if state.board[x][y] == opp_color: opp_disks += 1 disks_parameter = 100 * (curr_disks - opp_disks) / (curr_disks + opp_disks) # Calculate Mobility parameter real_curr_player = state.curr_player state.curr_player = color curr_mobility = len(state.get_possible_moves()) state.curr_player = opp_color opp_mobility = len(state.get_possible_moves()) state.curr_player = real_curr_player # Check if we got to a final state and in which condition. if not curr_mobility or not opp_mobility: # Final state return INFINITY if curr_disks > opp_disks else -INFINITY mobility_parameter = 0 if curr_mobility + opp_mobility == 0 else 100 * (curr_mobility - opp_mobility) / (curr_mobility + opp_mobility) # Calculate Corners parameter curr_corners = 0 opp_corners = 0 corners = [(0, 0), (0, 7), (7, 7), (7, 0)] for x, y in corners: curr_board_place = state.board[x][y] if curr_board_place == color: curr_corners += 1 elif curr_board_place == opp_color: opp_corners += 1 corners_parameter = 0 if curr_corners + opp_corners == 0 \ else 100 * (curr_corners - opp_corners) / (curr_corners + opp_corners) # Calculate Stability parameter stability = {color: curr_corners, opp_color: opp_corners} for x in range(BOARD_COLS): for y in range(BOARD_ROWS): if (x, y) in corners: continue else: player_on_tile = state.board[x][y] if player_on_tile == EM: continue for x_direction, y_direction in [(0, 1), (1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1)]: curr_x = x + x_direction # step in the direction curr_y = y + y_direction # step in the direction if state.isOnBoard(curr_x, curr_y): if state.board[curr_x][curr_y] == player_on_tile: # The tile is adjacent to a corner if (curr_x, curr_y) in corners and (x_direction, y_direction) not in [(1, 1), (1, -1), (-1, -1), (-1, 1)]: stability[player_on_tile] += 1 break # The tile is in immediate danger elif _is_in_immediate_danger(state, x, y, player_on_tile, x_direction, y_direction): stability[player_on_tile] -= 1 break stability_parameter = 0 if stability[color] + stability[opp_color] == 0 \ else 100 * (stability[color] - stability[opp_color]) / (stability[color] + stability[opp_color]) return 25*disks_parameter + 8*mobility_parameter + 12*corners_parameter + 25*stability_parameter