def splice_genomes(genomes, init_cell, weighted_probs, genome_len, max_attempts=1000): is_done = False new_genome = [] attempt = 0 while not is_done: attempt += 1 parent_1, parent_2 = choice(a=range(len(genomes)), size=2, replace=False, p=weighted_probs) genome0 = genomes[parent_1] genome1 = genomes[parent_2] new_genome = [] for i in range(0, genome_len, 2): new_genome.append(genome0[i]) new_genome.append(genome1[i + 1]) board = Isolation().result(init_cell) valid_genome = True for action in new_genome: board = Isolation(board=board.board, ply_count=board.ply_count + 1, locs=board.locs) if action not in board.actions(): valid_genome = False break board = board.result(action) is_done = valid_genome and (len(new_genome) == genome_len) is_done = True if attempt >= max_attempts else is_done return new_genome
def symmetric_states(state): """ return the states symmetric to the current one """ board = bin(state.board)[2:] board = [ board[i * (_WIDTH + 2):(i + 1) * (_WIDTH + 2)] for i in range(_HEIGHT) ] # left - right: board_1 = eval('0b' + ''.join([row[::-1] for row in board])) locs_1 = (symmetric_positions(state.locs[0], 'LR') if state.locs[0] != None else None, symmetric_positions(state.locs[1], 'LR') if state.locs[1] != None else None) state_1 = Isolation(board_1, ply_count=state.ply_count, locs=locs_1) # up - down: board_2 = eval('0b' + ''.join(board[::-1])) locs_2 = (symmetric_positions(state.locs[0], 'UD') if state.locs[0] != None else None, symmetric_positions(state.locs[1], 'UD') if state.locs[1] != None else None) state_2 = Isolation(board_2, ply_count=state.ply_count, locs=locs_2) # left - right and up - down: board_3 = eval('0b' + ''.join([row[::-1] for row in board[::-1]])) locs_3 = (symmetric_positions(state.locs[0], 'LRUD') if state.locs[0] != None else None, symmetric_positions(state.locs[1], 'LRUD') if state.locs[1] != None else None) state_3 = Isolation(board_3, ply_count=state.ply_count, locs=locs_3) return [(state_1, 'LR'), (state_2, 'UD'), (state_3, 'LRUD')]
def build_table(num_rounds=NUM_ROUNDS, num_plies=NUM_PLIES): """build opening book return it as dictionary :num_rounds: number of build_tree to call :num_plies: number of plies for this opening book :returns: a dictionary mapping state to the best action """ # init from collections import defaultdict, Counter book = defaultdict(Counter) # build printProgressBar(0, num_rounds, prefix='Progress:', suffix='Complete', length=50) for i in range(num_rounds): # build tree state = Isolation() build_tree(state, book, num_plies) # show progress printProgressBar(i + 1, num_rounds, prefix='Progress:', suffix='Complete', length=50) # return return {k: max(v, key=v.get) for k, v in book.items()}
def test_custom_player(self): """ CustomPlayer successfully completes a game against itself """ agents = (Agent(CustomPlayer, "Player 1"), Agent(CustomPlayer, "Player 2")) initial_state = Isolation() winner, game_history, _ = play( (agents, initial_state, self.time_limit, 0)) state = initial_state moves = deque(game_history) while moves: state = state.result(moves.popleft()) if not state.terminal_test(): print( "Your agent with id:{state.player()} was not able to make a move in state:" ) print(state.player()) debug_state = DebugState.from_state(state) print(debug_state) raise Exception("Your agent did not play until a terminal state.") debug_state = DebugState.from_state(state) print(debug_state) print("Winner is: " + str(winner) + "!")
def build_table(num_rounds=NUM_ROUNDS): # You should run no more than `num_rounds` simulations -- the # goal of this quiz is to understand one possible way to develop # an opening book; not to develop a good one # NOTE: the GameState object is not hashable, and the python3 # runtime includes security features that make object # hashes non-portable. There is a new attribute on # GameState objects in this quiz called `hashable` that # can be used as a dictionary key # TODO: return a table {k:v} where each k is a game state # and each v is the best action to take in that state from collections import defaultdict, Counter book = defaultdict(Counter) for _ in range(num_rounds): #print(_) state = Isolation() #build_tree(state, book) #build_minimax_tree(state,book) build_alphabeta_tree(state, book) move = {k: max(v, key=v.get) for k, v in book.items()} #with open("data.pickle", 'wb') as f: #pickle.dump(move, f) return move
def play_matches(custom_agent, test_agent, cli_args): """ Play a specified number of rounds between two agents. Each round consists of two games, and each player plays as first player in one game and second player in the other. (This mitigates "unfair" games where the first or second player has an advantage.) If fair_matches is true, then the agents repeat every game they played, but the agents switch initiative and use their opponent's opening move. In some games, picking a winning move for the opening guarantees the player a victory. Playing "fair" matches this way will balance out the advantage of picking perfect openings (the player would win the first time, and then lose when their opponent uses that move against them). """ matches = [] for match_id in range(cli_args.rounds): # initialize all games with a random move and response state = Isolation() matches.append( ((test_agent, custom_agent), state, cli_args.time_limit, match_id)) matches.append( ((custom_agent, test_agent), state, cli_args.time_limit, match_id)) results = _run_matches(matches, custom_agent.name, cli_args.processes) if cli_args.fair_matches: _matches = make_fair_matches(matches, results) results.extend( _run_matches(_matches, custom_agent.name, cli_args.processes)) wins = sum(int(r[0].name == custom_agent.name) for r in results) return wins, len(matches) * (1 + int(cli_args.fair_matches))
def build_table(num_rounds): from collections import defaultdict, Counter book = defaultdict(Counter) for _ in range(num_rounds): gameState = Isolation() buildTree(gameState, book, 3) return {k: max(v, key=v.get) for k, v in book.items()}
def make_fair_matches(matches, results): new_matches = [] for _, game_history, match_id in results: if len(game_history) < 2: logger.warn( textwrap.dedent(""" Unable to duplicate match {} -- one of the players forfeit at the first move """.format(match_id))) continue match = matches[match_id] state = Isolation().result(game_history[0]).result(game_history[1]) fair_match = Match(players=match.players[::-1], initial_state=state, time_limit=match.time_limit, match_id=-match.match_id, debug_flag=match.debug_flag) new_matches.append(fair_match) return new_matches
def make_fair_matches(matches, results): new_matches = [] for _, game_history, match_id in results: match = matches[match_id] state = Isolation() state = state.result(game_history[0]).result(game_history[1]) new_matches.append((match[0][::-1], match[1], match[2], -match_id)) return new_matches
def setUp(self): self.time_limit = 150 self.move_0_state = Isolation() self.move_1_state = self.move_0_state.result(choice(self.move_0_state.actions())) self.move_2_state = self.move_1_state.result(choice(self.move_1_state.actions())) terminal_state = self.move_2_state while not terminal_state.terminal_test(): terminal_state = terminal_state.result(choice(terminal_state.actions())) self.terminal_state = terminal_state
def run(self): state = Isolation() num_rounds = 100 book = defaultdict(Counter) for i in range(num_rounds): self.build_tree(state, book) opening_book = {k: max(v, key=v.get) for k, v in book.items()} with open("data.pickle", "wb") as f: pickle.dump(opening_book, f)
def __init__(self, init_cell, genome, search_depth): assert (init_cell <= 114) and (init_cell >= 0), "Invalid opening cell value" self.init_cell = init_cell self.board = Isolation() self.player0_moves = 0 self.player1_moves = 0 self.genome = genome self.search_depth = search_depth self.active_player = 0 self.move_history = []
def build_table(num_rounds=NUM_ROUNDS): # Builds a table that maps from game state -> action # by choosing the action that accumulates the most # wins for the active player. (Note that this uses # raw win counts, which are a poor statistic to # estimate the value of an action; better statistics # exist.) from collections import defaultdict, Counter book = defaultdict(Counter) _board = defaultdict(Counter) for _ in range(num_rounds): print(_) state = Isolation() #GameState() build_tree_random(state, book, _board) state = Isolation() build_tree_minmax(state, book, _board) result = {k: max(v, key=v.get) for k, v in book.items()} with open("data.pickle", 'wb') as f: pickle.dump(result, f) return result
def test_custom_player(self): """ CustomPlayer successfully completes a game against itself """ agents = (Agent(CustomPlayer, "Player 1"), Agent(CustomPlayer, "Player 2")) initial_state = Isolation() winner, game_history, _ = play((agents, initial_state, self.time_limit, 0)) state = initial_state moves = deque(game_history) while moves: state = state.result(moves.popleft()) self.assertTrue(state.terminal_test(), "Your agent did not play until a terminal state.")
def build_table(num_rounds=NUM_ROUNDS): # Builds a table that maps from game state -> action # by choosing the action that accumulates the most # wins for the active player. (Note that this uses # raw win counts, which are a poor statistic to # estimate the value of an action; better statistics # exist.) book = defaultdict(Counter) for _ in range(num_rounds): state = Isolation() build_tree(state, book) return {k: max(v, key=v.get) for k, v in book.items()}
def main(): init_cells = Isolation().actions() with MPICommExecutor(MPI.COMM_WORLD, root=0) as executor: if executor is None: return # worker process results = list(executor.map(test_cell_genomes, init_cells, chunksize=1)) print("Main proc done...") sys.stdout.flush() pickle.dump(results, open("./" + dir_name + "/" + "summary.pickle", "wb"))
def play_matches(custom_agent, test_agent, cli_args): """ Play a specified number of rounds between two agents. Each round consists of two games, and each player plays as first player in one game and second player in the other. (This mitigates "unfair" games where the first or second player has an advantage.) If fair_matches is true, then the agents repeat every game they played, but the agents switch initiative and use their opponent's opening move. In some games, picking a winning move for the opening guarantees the player a victory. Playing "fair" matches this way will balance out the advantage of picking perfect openings (the player would win the first time, and then lose when their opponent uses that move against them). """ matches = [] for match_id in range(cli_args.rounds): state = Isolation() matches.append( Match(players=(test_agent, custom_agent), initial_state=state, time_limit=cli_args.time_limit, match_id=2 * match_id, debug_flag=cli_args.debug)) matches.append( Match(players=(custom_agent, test_agent), initial_state=state, time_limit=cli_args.time_limit, match_id=2 * match_id + 1, debug_flag=cli_args.debug)) # Run all matches -- must be done before fair matches in order to populate # the first move from each player; these moves are reused in the fair matches results = _run_matches(matches, custom_agent.name, cli_args.processes) ### Code Added to print more data ### ## if not cli_args.fair_matches: ## print("Match Run report before fair matches. (Show data for first 6 games only, to reduce report size).:") ## print() ## _for_print(matches, results) ### End of code added ### if cli_args.fair_matches: print("Outcome of Fair Matches:") _matches = make_fair_matches(matches, results) results.extend( _run_matches(_matches, custom_agent.name, cli_args.processes)) wins = sum(int(r[0].name == custom_agent.name) for r in results) return wins, len(matches) * (1 + int(cli_args.fair_matches))
def build_table(num_rounds=NUM_ROUNDS): # Builds a table that maps from game state -> action # by choosing the action that accumulates the most # wins for the active player. from collections import defaultdict, Counter book = defaultdict(Counter) print("Round :", end=' ') for index in range(num_rounds): state = Isolation() print(index + 1, end=' ') build_tree(state, book) #_print_data(book) print() return {k: max(v, key=v.get) for k, v in book.items()}
def main(): start_time = time.time() state = Isolation() book = OpeningBook(initial_state=state, num_rounds=99 * 98 * 8 * 8 * (10), tree_depth=4).get_book() OpeningBook.save_opening_book(book) end_time = time.time() # time taken to build opening book = 332.32017993927 print('time taken to build opening book = ', end_time - start_time)
def play_matches(custom_agent, test_agent, cli_args): """ Play a specified number of rounds between two agents. Each round consists of two games, and each player plays as first player in one game and second player in the other. (This mitigates "unfair" games where the first or second player has an advantage.) If fair_matches is true, then the agents repeat every game they played, but the agents switch initiative and use their opponent's opening move. In some games, picking a winning move for the opening guarantees the player a victory. Playing "fair" matches this way will balance out the advantage of picking perfect openings (the player would win the first time, and then lose when their opponent uses that move against them). """ matches = [] for match_id in range(cli_args.rounds): state = Isolation() matches.append( Match(players=(test_agent, custom_agent), heuristics=(cli_args.opponent_heuristic, cli_args.heuristic), initial_state=state, time_limit=cli_args.time_limit, match_id=2 * match_id, debug_flag=cli_args.debug)) matches.append( Match(players=(custom_agent, test_agent), heuristics=(cli_args.heuristic, cli_args.opponent_heuristic), initial_state=state, time_limit=cli_args.time_limit, match_id=2 * match_id + 1, debug_flag=cli_args.debug)) # Run all matches -- must be done before fair matches in order to populate # the first move from each player; these moves are reused in the fair matches results = _run_matches(matches, custom_agent.name, cli_args.processes) total_depths = [] for result in results: total_depths += result[3] print("Average Depth: {}".format(sum(total_depths) / len(total_depths))) print("Time Limit: {}".format(cli_args.time_limit)) if cli_args.fair_matches: _matches = make_fair_matches(matches, results) results.extend( _run_matches(_matches, custom_agent.name, cli_args.processes)) wins = sum(int(r[0].name == custom_agent.name) for r in results) return wins, len(matches) * (1 + int(cli_args.fair_matches))
def build_rand_genomes(n_genomes, init_cell, genome_len=4): assert (init_cell <= 114) and (init_cell >= 0), "Invalid opening cell value" genomes = [] for i in range(n_genomes): genome = [] board = Isolation().result(init_cell) for j in range(genome_len): try: board = Isolation(board=board.board, ply_count=board.ply_count + 1, locs=board.locs) next_action = random.choice(board.actions()) genome.append(next_action) board = board.result(next_action) except Exception as e: # try random sample from previous genomes, otherwise skip genome if len(genomes) > 0: genome = random.choice(genomes) else: break if len(genome) == genome_len: genomes.append(genome) return genomes
def build_table(self): # Builds a table that maps from game state -> action # by choosing the action that accumulates the most # wins for the active player. (Note that this uses # raw win counts, which are a poor statistic to # estimate the value of an action; better statistics # exist.) from collections import defaultdict, Counter book = defaultdict(Counter) for n in range(self.num_rounds): if n % 10000 == 0: print(n) state = Isolation() self.build_tree(state, book, self.depth) return {k: max(v, key=v.get) for k, v in book.items()}
def _for_print(matches, results): for winner_agent, game_history, match_id in results: if match_id < 6: match = matches[match_id] state_opening_moves = Isolation().result(game_history[0]).result( game_history[1]) print("Match Id: {}.".format(match_id), end=' ') print("Players One: {}.".format(match.players[0].name), end=' ') print("Players Two: {}.".format(match.players[1].name)) print("State after opening moves: {}".format(state_opening_moves)) print("Winner: {}".format(winner_agent.name)) print(DebugState.from_state(state_opening_moves)) print() else: break
def build_table(num_rounds=NUM_ROUNDS): # You should run no more than `num_rounds` simulations -- the # goal of this quiz is to understand one possible way to develop # an opening book; not to develop a good one # NOTE: the GameState object is not hashable, and the python3 # runtime includes security features that make object # hashes non-portable. There is a new attribute on # GameState objects in this quiz called `hashable` that # can be used as a dictionary key book = defaultdict(Counter) for _ in range(num_rounds): state = Isolation() build_tree(state, book) return {k: max(v, key=v.get) for k, v in book.items()}
def build_table(num_rounds=NUM_ROUNDS): """ Creates the table of opening moves, returns a dictionary with the game state as the key and the best found move as value. """ # Creates a dictionary for counting purposes, # it has a game state as a key, and the values are other dictionaries. # This inner dictionaries have actions (taken in a particular state) as keys # and total reward (#won-matches - #lost-matches) as values book = defaultdict(Counter) for _ in range(num_rounds): state = Isolation() # Initial state (a blank board) build_tree(state, book) return {k: max(v, key=v.get) for k, v in book.items()}
def build_book(book, num_rounds=100): for num in range(num_rounds): state = Isolation() states = [] while state.ply_count <= 3: action = random.choice(state.actions()) player = state.player() states.append((state, player, action)) state = state.result(action) while not state.terminal_test(): action = alpha_beta(state, state.player()) player = state.player() state = state.result(action) win_0 = state.utility(0) > 0 win_1 = state.utility(1) > 0 assert win_0 != win_1 for s in states: state = s[0] player = s[1] action = s[2] if win_0: if player == 0: book[state][action] += 1 else: book[state][action] += -1 else: if player == 0: book[state][action] += -1 else: book[state][action] += 1 return book
def build_table(self, num_rounds): # Builds a table that maps from game state -> action # by choosing the action that accumulates the most # wins for the active player. (Note that this uses # raw win counts, which are a poor statistic to # estimate the value of an action; better statistics # exist.) book = defaultdict(Counter) for _ in range(num_rounds): # progress checking, feedback every 1000 rounds if _ % 1000 == 0: print('round=', _) # new blank state for each round state = Isolation() self.build_tree(state, book, self.tree_depth) # this line chooses the max score action of each board state, # effectively removing all other possible actions of the board state which scored less return {k: max(v, key=v.get) for k, v in book.items()}
from collections import defaultdict, Counter from isolation import DebugState import pickle f = open("data.pickle", 'rb') book = pickle.load(f) from isolation import Isolation state = Isolation() if state in book: print("empty state is in data.pickle") # first move action = book[state] print("The best action for an empty board is ", action) state = state.result(action) debug_board = DebugState.from_state(state) print("Board after first move") print(debug_board) # best response action = book[state] print("The best response for it from the opponent is ", action) state = state.result(action) debug_board = DebugState.from_state(state) print("Board after the response") print(debug_board) else: print("empty state is NOT found in data.pickle")
# key, val # locs , action # ( first, second) int # int int # Count the number of wins for key, value in first_n.items(): if key in second_n: print(key, "is in both") for key, value in second_n.items(): if key in first_n: print(key, "is in both") start_state = Isolation() for action in start_state.actions(): first_state = start_state.result(action) first_state_string = '{} {} {}'.format(first_state.board, first_state.locs[0], first_state.locs[1]) for action_s in first_state.actions(): # print(action,action_s) second_state = first_state.result(action_s) second_state_string = '{} {} {}'.format(second_state.board, second_state.locs[0], second_state.locs[1]) for action_t in second_state.actions(): # print(action,action_s) third_state = second_state.result(action_t) third_state_string = '{} {} {}'.format(third_state.board, third_state.locs[0], third_state.locs[1]) for action_f in third_state.actions(): # print(action,action_s) state = third_state.result(action_f)
import pickle import queue from isolation import Isolation, DebugState # Loading the opening book form a pickle file with open("data.pickle", "rb") as f: book = pickle.load(f) # Creating the initial state (a blank board) initial_statate = Isolation() # Displaying the initial move taken by the first player first_move_state = initial_statate.result(book[initial_statate]) print('OPENING MOVE FOR PLAYER 1') print(DebugState().from_state(first_move_state)) # Displaying the reply taken by the second player response_move_state = first_move_state.result(book[first_move_state]) print('BEST REPLY BY PLAYER 2') print(DebugState().from_state(response_move_state))