diff --git a/week4/material/MCTS_functions.py b/week4/material/MCTS_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..fb86b7dcfd99677838ad28e6551641eace55435c --- /dev/null +++ b/week4/material/MCTS_functions.py @@ -0,0 +1,13 @@ +import random +import time + +from tictactoe_game_environment import TicTacToeGameEnvironment as gm + +def selection_policy(node, target_player): + pass + +def random_playout(initial_node): + pass + +def mcts(root_node, target_player, max_time=1): + pass \ No newline at end of file diff --git a/week4/material/agent_programs.py b/week4/material/agent_programs.py new file mode 100644 index 0000000000000000000000000000000000000000..d98fa76b5af420c59eaea32c458c592b4e14c7cb --- /dev/null +++ b/week4/material/agent_programs.py @@ -0,0 +1,104 @@ +import random +import time + +from une_ai.models import GraphNode, MCTSGraphNode + +from tictactoe_game_environment import TicTacToeGameEnvironment +from minimax_functions import minimax, minimax_alpha_beta, optimised_minimax +from MCTS_functions import mcts + +def agent_program_random(percepts, actuators): + try: + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + except KeyError: + print("Error. You may have not fully implemented yet the class TicTacToeGameEnvironment") + return [] + + legal_moves = TicTacToeGameEnvironment.get_legal_actions(game_state) + if len(legal_moves) > 0: + return [random.choice(legal_moves)] + + return [] + +def agent_program_minimax(percepts, actuators, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = minimax(state_node, player_turn, max_depth) + toc = time.time() + print("[Minimax (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] + + return [] + +def agent_program_minimax_alpha_beta(percepts, actuators, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = minimax_alpha_beta(state_node, player_turn, float("-Inf"), float("+Inf"), max_depth) + toc = time.time() + print("[Minimax Alpha-Beta (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] + + return [] + +def agent_program_mcts(percepts, actuators, max_time=1): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + if not TicTacToeGameEnvironment.is_terminal(game_state): + tic = time.time() + root_node = MCTSGraphNode(game_state, None, None) + best_move = mcts(root_node, player_turn, max_time) + toc = time.time() + print("[MTCS (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] + + return [] + +def agent_program_optimised_minimax(percepts, actuators, tt, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = optimised_minimax(state_node, player_turn, tt, max_depth) + toc = time.time() + print("[Optimised Minimax (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] + + return [] \ No newline at end of file diff --git a/week4/material/minimax_functions.py b/week4/material/minimax_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..2e43ffa80708244535aac08c3880c1cc49f8c5ac --- /dev/null +++ b/week4/material/minimax_functions.py @@ -0,0 +1,11 @@ +from tictactoe_game_environment import TicTacToeGameEnvironment as gm +from une_ai.models import GraphNode + +def minimax(node, player, depth): + return 0, None + +def minimax_alpha_beta(node, player, alpha, beta, depth): + return 0, None + +def optimised_minimax(node, player, tt, depth): + return 0, None \ No newline at end of file diff --git a/week4/material/tictactoe_app.py b/week4/material/tictactoe_app.py new file mode 100644 index 0000000000000000000000000000000000000000..4c19b54e81d7c049468f87a3dd38f50055452180 --- /dev/null +++ b/week4/material/tictactoe_app.py @@ -0,0 +1,23 @@ +from une_ai.tictactoe import TicTacToeGame +from une_ai.tictactoe import TicTacToePlayer + +from tictactoe_game_environment import TicTacToeGameEnvironment +from tictactoe_ttable import TicTacToeTTable + +from agent_programs import agent_program_random +from agent_programs import agent_program_minimax, agent_program_minimax_alpha_beta, agent_program_optimised_minimax +from agent_programs import agent_program_mcts + +if __name__ == '__main__': + # Creating the two players + # To change their behaviour, change the second parameter + # of the constructor with the desired agent program function + player_X = TicTacToePlayer('X', agent_program_random) + player_O = TicTacToePlayer('O', agent_program_random) + + # DO NOT EDIT THE FOLLOWING INSTRUCTIONS! + environment = TicTacToeGameEnvironment() + environment.add_player(player_X) + environment.add_player(player_O) + + game = TicTacToeGame(player_X, player_O, environment) \ No newline at end of file diff --git a/week4/material/tictactoe_game_environment.py b/week4/material/tictactoe_game_environment.py new file mode 100644 index 0000000000000000000000000000000000000000..8bbdbf883361437ca3d2af4d8dd37c1eae1b3e77 --- /dev/null +++ b/week4/material/tictactoe_game_environment.py @@ -0,0 +1,135 @@ +import numpy as np +from scipy.signal import convolve2d +from une_ai.models import GameEnvironment, GridMap, Agent + +class IllegalMove(Exception): + pass + +class TicTacToeGameEnvironment(GameEnvironment): + + def __init__(self, board_size=3): + super().__init__("Tic Tac Toe") + + # TODO + # implement the abstract method add_player + # the GameEnvironment superclass uses a dictionary self._players + # to store the players of the game. + # For this game, we must limit the players to 2 players and + # The first added player will be X and the second O + def add_player(self, player): + assert isinstance(player, Agent), "The parameter player must be an instance of a subclass of the class Agent" + assert len(self._players) < 2, "It is not possible to add more than 2 players for this game." + + pass + + # TODO + # implement the abstract method get_game_state + # the method must return the current state of the game + # as a dictionary with the following keys: + # 'game-board' -> a copy of the game board (as 3x3 GridMap) + # 'player-turn' -> 'X' or 'O' depending on the current player turn + # You may first create properties in the constructor function __init__ + # to store the game board and the current turn + def get_game_state(self): + pass + + # TODO + # implement the abstract method get_percepts + # this method returns a dictionary with keys the sensors of the agent + # and values the percepts gathered for that sensor at time t + # the sensors are: + # 'game-board-sensor' -> the 'game-board' value from the current game state + # 'turn-taking-indicator' -> the 'player-turn' value from the current game state + def get_percepts(self): + pass + + # TODO + # implement the abstract method get_legal_actions + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns the list of + # legal actions in that game state + # An action is legal in a given game state if the game board cell + # for that action is free from marks + def get_legal_actions(game_state): + pass + + # TODO + # implement the abstract method transition_result + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state and an action to perform as input and it returns + # the new game state. + def transition_result(game_state, action): + pass + + # TODO + # implement the abstract method state_transition + # this method takes as input the agent's actuators + # and it changes the game environment state based + # on the values of the agent's actuators + # This agent has only one actuator, 'marker' + # the value of this actuator is a tuple with the x and y + # coordinates where the agent will place its marker on the game board + # We can implement this method by re-using the static method + # transition_result we just implemented + def state_transition(self, agent_actuators): + assert agent_actuators['marker'] is not None, "During a turn, the player must have set the 'marker' actuator value to a coordinate (x, y) of the game board where to place the marker." + + pass + + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It returns the turn of the player given a game state. + def turn(game_state): + assert 'player-turn' in game_state.keys(), "Invalid game state. A game state must have the key 'player-turn'" + + return game_state['player-turn'] + + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns the winner ('X' or 'O') if there is any + # or None if there is no winner (a tie or a non-terminal state) + # This method is already provided to you. You should look at its implementation + # and try to understand how it is finding a winner with the convolution operation + def get_winner(game_state): + game_board = game_state['game-board'] + + horizontal_kernel = np.array([[ 1, 1, 1]]) + vertical_kernel = np.transpose(horizontal_kernel) + diag_kernel = np.eye(3, dtype=np.uint8) + flipped_diag_kernel = np.fliplr(diag_kernel) + detection_kernels = [horizontal_kernel, vertical_kernel, diag_kernel, flipped_diag_kernel] + + for marker in ['X', 'O']: + player_markers = game_board.get_map() == marker + for kernel in detection_kernels: + convolved_values = convolve2d(player_markers, kernel, mode="valid") + if (convolved_values == 3).any(): + return marker + + return None + + # TODO + # implement the abstract method is_terminal + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns True if the game state + # is terminal and False otherwise. + # In this game, a state is terminal if there are no more legal actions + # or if there is a winner. + def is_terminal(game_state): + pass + + # TODO + # implement the abstract method payoff + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state and the player name ('X' or 'O') as input and it returns + # the payoff value for that player in the given game state + # In this scenario, we are only considering terminal states with a winner + # if there is not a winner yet (or there is a tie) we return 0 + # In other games the payoff function may be more complex + def payoff(game_state, player_name): + pass + \ No newline at end of file diff --git a/week4/material/tictactoe_ttable.py b/week4/material/tictactoe_ttable.py new file mode 100644 index 0000000000000000000000000000000000000000..80303dec3f37091f181d9234190ed0ea2f803ac2 --- /dev/null +++ b/week4/material/tictactoe_ttable.py @@ -0,0 +1,40 @@ +import random + +from une_ai.models import TTable + +class TicTacToeTTable(TTable): + + def __init__(self, saving_directory='./transposition-tables/', instance_id=None, verbose=False): + super().__init__(saving_directory, instance_id, verbose) + + def generate_zobrist_table(self): + random_int = lambda: random.randint(0, pow(2, 64)) + + markers = ['X', 'O'] + board_size = 3 + table = {} + for i in range(board_size): + for j in range(board_size): + for k in markers: + table["{0}-{1}-{2}".format(i, j, k)] = random_int() + + table["player-turn-X"] = random_int() + table["player-turn-O"] = random_int() + + return table + + def compute_hash(self, state): + zobrist_table = self.get_zobrist_table() + + player = state['player-turn'] + + h = 0 + h ^= zobrist_table['player-turn-{0}'.format(player)] + game_board = state['game-board'] + for i in range(game_board.get_width()): + for j in range(game_board.get_height()): + board_value = game_board.get_item_value(i, j) + if (board_value is not None): + h ^= zobrist_table["{0}-{1}-{2}".format(i, j, board_value)] + + return str(h) \ No newline at end of file diff --git a/week4/solution/MCTS_functions.py b/week4/solution/MCTS_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..6b0b09c994908bb1b3443dd6784585d3f0e7167a --- /dev/null +++ b/week4/solution/MCTS_functions.py @@ -0,0 +1,72 @@ +import random +import time +import math + +from tictactoe_game_environment import TicTacToeGameEnvironment as gm + +def selection_policy(node, target_player): + # In this case, we select a node that was not explored yet + # or, if all nodes were explored, the one with highest wins + # Better version may use different policies (e.g. see UCT policy) + successors = node.get_successors() + best_uct_score = 0 + best_node = None + for s in successors: + if s.n() > 0: + uct = (s.wins(target_player) / s.n()) + math.sqrt(2) * math.sqrt(math.log(s.get_parent_node().n()) / s.n()) + if best_node is None or uct > best_uct_score: + best_uct_score = uct + best_node = s + else: + # unexplored child, choose it + return s + + return best_node + +def random_playout(initial_node): + current_playout_state = initial_node.get_state() + while not gm.is_terminal(current_playout_state): + possible_moves = gm.get_legal_actions(current_playout_state) + action = random.choice(possible_moves) + current_playout_state = gm.transition_result(current_playout_state, action) + + return gm.get_winner(current_playout_state) + +def mcts(root_node, target_player, max_time=1): + start_time = time.time() + + # Performing simulations until the time is up + while (time.time() - start_time) < max_time: + # SELECTION PHASE + current_node = root_node + while not gm.is_terminal(current_node.get_state()) and not current_node.is_leaf_node(): + current_node = selection_policy(current_node, target_player) + + # EXPANSION PHASE + selected_node = current_node + legal_moves = gm.get_legal_actions(selected_node.get_state()) + for a in legal_moves: + if not selected_node.was_action_expanded(a): + successor_state = gm.transition_result(selected_node.get_state(), a) + selected_node.add_successor(successor_state, a) + + # SIMULATION PHASE + winner = random_playout(selected_node) + if winner is None: + # we consider a tie as a win + # if we don't do that, we might find an optimal opponent + # always 1 step ahead of us and the only best option + # for us is to achieve a tie + winner = target_player + + # BACKPROPAGATION PHASE + selected_node.backpropagate(winner) + + # Time is up, choosing the child of the root node with highest wins + best_node = None + max_wins = 0 + for successor in root_node.get_successors(): + if best_node is None or successor.wins(target_player)/successor.n() > max_wins: + best_node = successor + max_wins = successor.wins(target_player) / successor.n() + return best_node.get_action() \ No newline at end of file diff --git a/week4/solution/agent_programs.py b/week4/solution/agent_programs.py index f2f39265ef66aa64e2d8eb912a3a4ef5322900c8..d98fa76b5af420c59eaea32c458c592b4e14c7cb 100644 --- a/week4/solution/agent_programs.py +++ b/week4/solution/agent_programs.py @@ -1,141 +1,104 @@ import random import time -from une_ai.tictactoe import TicTacToeGameEnvironment as gm -def player_marker(player_name): - if player_name == 'MAX': - return 'X' - else: - return 'Y' +from une_ai.models import GraphNode, MCTSGraphNode -def minimax(game_state, depth, player, is_maximising): - move_best = None - - if is_maximising: - value = float('-Inf') - else: - value = float('+Inf') - if depth == 0 or gm.is_terminal(game_state): - value = gm.payoff(game_state, player) - return value, move_best - - legal_actions = gm.get_legal_actions(game_state) - for action in legal_actions: - new_state = gm.transition_result(game_state, action) - value_new, move_new = minimax(new_state, depth - 1, player, not is_maximising) - if (is_maximising and value_new > value) or (not is_maximising and value_new < value): - value = value_new - move_best = action - - return value, move_best +from tictactoe_game_environment import TicTacToeGameEnvironment +from minimax_functions import minimax, minimax_alpha_beta, optimised_minimax +from MCTS_functions import mcts -def minimax_alpha_beta(game_state, depth, player, is_maximising, alpha, beta): - move_best = None - legal_actions = gm.get_legal_actions(game_state) - if is_maximising: - value = float('-Inf') - else: - value = float('+Inf') - if depth == 0 or gm.is_terminal(game_state): - value = gm.payoff(game_state, player) - return value, move_best +def agent_program_random(percepts, actuators): + try: + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + except KeyError: + print("Error. You may have not fully implemented yet the class TicTacToeGameEnvironment") + return [] - for action in legal_actions: - new_state = gm.transition_result(game_state, action) - value_new, move_new = minimax_alpha_beta(new_state, depth - 1, player, not is_maximising, alpha, beta) - if is_maximising: - if value_new > value: - value = value_new - move_best = action - alpha = max(value, alpha) - if value >= beta: - break - else: - if value_new < value: - value = value_new - move_best = action - beta = min(value, beta) - if value <= alpha: - break - - - return value, move_best - -def random_game_simulation(game_state, player, next_move): - new_game_state = gm.transition_result(game_state, next_move) - if gm.is_terminal(new_game_state): - value = gm.payoff(new_game_state, player) - return value - else: - new_legal_actions = gm.get_legal_actions(new_game_state) - next_move_rnd = random.choice(new_legal_actions) - value = random_game_simulation(new_game_state, player, next_move_rnd) + legal_moves = TicTacToeGameEnvironment.get_legal_actions(game_state) + if len(legal_moves) > 0: + return [random.choice(legal_moves)] - return value + return [] -def montecarlo_simulation(game_state, player, N): - if gm.is_terminal(game_state): - return None +def agent_program_minimax(percepts, actuators, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } - legal_actions = gm.get_legal_actions(game_state) - k = len(legal_actions) - payoffs = [None]*k - for i in range(0, k): - total_payoff = 0 - for j in range(0, N): - cur_payoff = random_game_simulation(game_state, player, legal_actions[i]) - total_payoff += cur_payoff - - avg_payoff = total_payoff / N - payoffs[i] = avg_payoff - avg_payoff_best = float('-Inf') - move_best = None - for i, avg in enumerate(payoffs): - if move_best is None or avg > avg_payoff_best: - avg_payoff_best = avg - move_best = legal_actions[i] - - return move_best - -def max_agent_program_random(percepts, actuators): - game_state = percepts['game-board-sensor'] - free_pos = game_state.find_value(None) - if len(free_pos) > 0: - move = random.choice(free_pos) - actions = ['mark-{0}-{1}'.format(move[0], move[1])] - return actions + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = minimax(state_node, player_turn, max_depth) + toc = time.time() + print("[Minimax (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] return [] -def max_agent_program_minimax(percepts, actuators): - game_state = percepts['game-board-sensor'] - free_pos = game_state.find_value(None) - if len(free_pos) > 0: - _, best_move = minimax(game_state, 'MAX') - return [best_move] +def agent_program_minimax_alpha_beta(percepts, actuators, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = minimax_alpha_beta(state_node, player_turn, float("-Inf"), float("+Inf"), max_depth) + toc = time.time() + print("[Minimax Alpha-Beta (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] return [] -def max_agent_program(percepts, actuators): - game_state = percepts['game-board-sensor'] - free_pos = game_state.find_value(None) - if len(free_pos) > 0: - _, best_move = minimax_alpha_beta(game_state, 100, 'X', True, float("-Inf"), float("+Inf")) #, float('-Inf'), float('+Inf')) - #best_move = montecarlo_simulation(game_state, 'X', 100) - return [best_move] +def agent_program_mcts(percepts, actuators, max_time=1): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + if not TicTacToeGameEnvironment.is_terminal(game_state): + tic = time.time() + root_node = MCTSGraphNode(game_state, None, None) + best_move = mcts(root_node, player_turn, max_time) + toc = time.time() + print("[MTCS (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] return [] -def min_agent_program(percepts, actuators): - game_state = percepts['game-board-sensor'] - free_pos = game_state.find_value(None) - if len(free_pos) > 0: - #move = random.choice(free_pos) - #actions = ['mark-{0}-{1}'.format(move[0], move[1])] - #return actions - #_, best_move = minimax_alpha_beta(game_state, 100, 'O', True, float("-Inf"), float("+Inf")) #, float('-Inf'), float('+Inf')) - best_move = montecarlo_simulation(game_state, 'O', 100) - return [best_move] +def agent_program_optimised_minimax(percepts, actuators, tt, max_depth=4): + game_board = percepts['game-board-sensor'] + player_turn = percepts['turn-taking-indicator'] + game_state = { + 'game-board': game_board.copy(), + 'player-turn': player_turn + } + + + if not TicTacToeGameEnvironment.is_terminal(game_state): + state_node = GraphNode(game_state, None, None, 0) + tic = time.time() + _, best_move = optimised_minimax(state_node, player_turn, tt, max_depth) + toc = time.time() + print("[Optimised Minimax (player {0})] Elapsed (sec): {1:.6f}".format(player_turn, toc-tic)) + if best_move is not None: + return [best_move] return [] \ No newline at end of file diff --git a/week4/solution/minimax_functions.py b/week4/solution/minimax_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..8c3868002fab2f5e3f8b3e5d978fbe99ac23e6d1 --- /dev/null +++ b/week4/solution/minimax_functions.py @@ -0,0 +1,107 @@ +from tictactoe_game_environment import TicTacToeGameEnvironment as gm +from une_ai.models import GraphNode + +def minimax(node, player, depth): + move_best = None + + game_state = node.get_state() + player_turn = game_state['player-turn'] + is_maximising = player_turn == player + + if is_maximising: + value = float('-Inf') + else: + value = float('+Inf') + if depth <= 0 or gm.is_terminal(game_state): + value = gm.payoff(game_state, player) + return value, move_best + + legal_actions = gm.get_legal_actions(game_state) + for action in legal_actions: + new_state = gm.transition_result(game_state, action) + child_node = GraphNode(new_state, node, action, 1) + value_new, _ = minimax(child_node, player, depth - 1) + if (is_maximising and value_new > value) or (not is_maximising and value_new < value): + value = value_new + move_best = action + + return value, move_best + +def minimax_alpha_beta(node, player, alpha, beta, depth): + game_state = node.get_state() + move_best = None + legal_actions = gm.get_legal_actions(game_state) + + player_turn = game_state['player-turn'] + is_maximising = player_turn == player + + if is_maximising: + value = float('-Inf') + else: + value = float('+Inf') + if depth <= 0 or gm.is_terminal(game_state): + value = gm.payoff(game_state, player) + return value, move_best + + for action in legal_actions: + new_state = gm.transition_result(game_state, action) + child_node = GraphNode(new_state, node, action, 1) + value_new, _ = minimax_alpha_beta(child_node, player, alpha, beta, depth - 1) + if is_maximising: + if value_new > value: + value = value_new + move_best = action + alpha = max(value, alpha) + if value >= beta: + break + else: + if value_new < value: + value = value_new + move_best = action + beta = min(value, beta) + if value <= alpha: + break + + return value, move_best + +def optimised_minimax(node, player, tt, depth): + game_state = node.get_state() + player_turn = game_state['player-turn'] + is_maximising = player_turn == player + + # using transposition table + tt_entry = tt.lookup(node) + if tt_entry is not None and tt_entry['depth'] >= depth: + return tt_entry['value'], tt_entry["move_best"] + + move_best = None + + if is_maximising: + value = float('-Inf') + else: + value = float('+Inf') + if depth <= 0 or gm.is_terminal(game_state): + value = gm.payoff(game_state, player) + return value, move_best + + legal_actions = gm.get_legal_actions(game_state) + for action in legal_actions: + new_state = gm.transition_result(game_state, action) + child_node = GraphNode(new_state, node, action, 1) + value_new, _ = optimised_minimax(child_node, player, tt, depth - 1) + + if (is_maximising and value_new > value) or (not is_maximising and value_new < value): + value = value_new + move_best = action + + # storing value in transposition table + if tt_entry is None or tt_entry['depth'] <= depth: + entry_dict = { + "value": int(value), + "depth": depth, + "move_best": move_best + } + + tt.store_node(node, entry_dict) + + return value, move_best \ No newline at end of file diff --git a/week4/solution/tictactoe.py b/week4/solution/tictactoe.py deleted file mode 100644 index 12f665044f591ca9b827016daad8586bd925801f..0000000000000000000000000000000000000000 --- a/week4/solution/tictactoe.py +++ /dev/null @@ -1,8 +0,0 @@ -from une_ai.tictactoe import TicTacToeGame -from agent_programs import max_agent_program, min_agent_program - -if __name__ == '__main__': - game = TicTacToeGame( - max_agent_program, - min_agent_program - ) \ No newline at end of file diff --git a/week4/solution/tictactoe_app.py b/week4/solution/tictactoe_app.py new file mode 100644 index 0000000000000000000000000000000000000000..bded234d1570eb658a78558802bcebfc7461a7f1 --- /dev/null +++ b/week4/solution/tictactoe_app.py @@ -0,0 +1,30 @@ +from une_ai.tictactoe import TicTacToeGame +from une_ai.tictactoe import TicTacToePlayer + +from tictactoe_game_environment import TicTacToeGameEnvironment +from tictactoe_ttable import TicTacToeTTable + +from agent_programs import agent_program_random +from agent_programs import agent_program_minimax, agent_program_minimax_alpha_beta, agent_program_optimised_minimax +from agent_programs import agent_program_mcts + +if __name__ == '__main__': + # Creating the transposition table + tt = TicTacToeTTable(instance_id='6879eb26-1ba1-11ee-8577-9e02763478a3') + print("Initialised a Transposition table with instance id {0}".format(tt.get_instance_id())) + + wrapped_minimax_tt = lambda perc, act: agent_program_optimised_minimax(perc, act, tt, max_depth=4) + + # Creating the two players + # To change their behaviour, change the second parameter + # of the constructor with the desired agent program function + player_X = TicTacToePlayer('X', wrapped_minimax_tt) + player_O = TicTacToePlayer('O', lambda perc, act: agent_program_minimax_alpha_beta(perc, act, 10)) + + # DO NOT EDIT THE FOLLOWING INSTRUCTIONS! + environment = TicTacToeGameEnvironment() + environment.add_player(player_X) + environment.add_player(player_O) + + game = TicTacToeGame(player_X, player_O, environment) + diff --git a/week4/solution/tictactoe_game_environment.py b/week4/solution/tictactoe_game_environment.py new file mode 100644 index 0000000000000000000000000000000000000000..ad36b9ed2016cb5e01d689783ce53595c047771a --- /dev/null +++ b/week4/solution/tictactoe_game_environment.py @@ -0,0 +1,192 @@ +import numpy as np +from scipy.signal import convolve2d +from une_ai.models import GameEnvironment, GridMap, Agent + +class IllegalMove(Exception): + pass + +class TicTacToeGameEnvironment(GameEnvironment): + + def __init__(self, board_size=3): + super().__init__("Tic Tac Toe") + + self._board_size = board_size + self._game_board = GridMap(board_size, board_size, None) + self._player_turn = 'X' # X always starts + + # TODO + # implement the abstract method add_player + # the GameEnvironment superclass uses a dictionary self._players + # to store the players of the game. + # For this game, we must limit the players to 2 players and + # The first added player will be X and the second O + def add_player(self, player): + assert isinstance(player, Agent), "The parameter player must be an instance of a subclass of the class Agent" + assert len(self._players) < 2, "It is not possible to add more than 2 players for this game." + + if len(self._players) == 0: + marker = 'X' + else: + marker = 'O' + + self._players[marker] = player + + return marker + + # TODO + # implement the abstract method get_game_state + # the method must return the current state of the game + # as a dictionary with the following keys: + # 'game-board' -> a copy of the game board (as 3x3 GridMap) + # 'player-turn' -> 'X' or 'O' depending on the current player turn + # You may first create properties in the constructor function __init__ + # to store the game board and the current turn + def get_game_state(self): + gs = { + 'game-board': self._game_board.copy(), + 'player-turn': self._player_turn + } + return gs + + # TODO + # implement the abstract method get_percepts + # this method returns a dictionary with keys the sensors of the agent + # and values the percepts gathered for that sensor at time t + # the sensors are: + # 'game-board-sensor' -> the 'game-board' value from the current game state + # 'turn-taking-indicator' -> the 'player-turn' value from the current game state + def get_percepts(self): + gs = self.get_game_state() + return { + 'game-board-sensor': gs['game-board'], + 'turn-taking-indicator': gs['player-turn'] + } + + # TODO + # implement the abstract method get_legal_actions + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns the list of + # legal actions in that game state + # An action is legal in a given game state if the game board cell + # for that action is free from marks + def get_legal_actions(game_state): + legal_actions = [] + game_board = game_state['game-board'] + empty_cells = game_board.find_value(None) + for empty_cell in empty_cells: + legal_actions.append('mark-{0}-{1}'.format(empty_cell[0], empty_cell[1])) + + return legal_actions + + # TODO + # implement the abstract method transition_result + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state and an action to perform as input and it returns + # the new game state. + def transition_result(game_state, action): + legal_actions = TicTacToeGameEnvironment.get_legal_actions(game_state) + if action not in legal_actions: + raise(IllegalMove('The action {0} is not a legal move for the given game state {1}.'.format(action, game_state.get_map()))) + + marker = TicTacToeGameEnvironment.turn(game_state) + + tokens = action.split('-') + x, y = (int(tokens[1]), int(tokens[2])) + new_game_board = game_state['game-board'].copy() + new_game_board.set_item_value(x, y, marker) + + new_game_state = { + 'game-board': new_game_board, + 'player-turn': 'O' if game_state['player-turn'] == 'X' else 'X' + } + + return new_game_state + + # TODO + # implement the abstract method state_transition + # this method takes as input the agent's actuators + # and it changes the game environment state based + # on the values of the agent's actuators + # This agent has only one actuator, 'marker' + # the value of this actuator is a tuple with the x and y + # coordinates where the agent will place its marker on the game board + # We can implement this method by re-using the static method + # transition_result we just implemented + def state_transition(self, agent_actuators): + assert agent_actuators['marker'] is not None, "During a turn, the player must have set the 'marker' actuator value to a coordinate (x, y) of the game board where to place the marker." + + x, y = agent_actuators['marker'] + gs = self.get_game_state() + action = 'mark-{0}-{1}'.format(x, y) + new_gs = TicTacToeGameEnvironment.transition_result(gs, action) + + self._player_turn = new_gs['player-turn'] + self._game_board = new_gs['game-board'].copy() + + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It returns the turn of the player given a game state. + def turn(game_state): + assert 'player-turn' in game_state.keys(), "Invalid game state. A game state must have the key 'player-turn'" + + return game_state['player-turn'] + + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns the winner ('X' or 'O') if there is any + # or None if there is no winner (a tie or a non-terminal state) + # This method is already provided to you. You should look at its implementation + # and try to understand how it is finding a winner with the convolution operation + def get_winner(game_state): + game_board = game_state['game-board'] + + horizontal_kernel = np.array([[ 1, 1, 1]]) + vertical_kernel = np.transpose(horizontal_kernel) + diag_kernel = np.eye(3, dtype=np.uint8) + flipped_diag_kernel = np.fliplr(diag_kernel) + detection_kernels = [horizontal_kernel, vertical_kernel, diag_kernel, flipped_diag_kernel] + + for marker in ['X', 'O']: + player_markers = game_board.get_map() == marker + for kernel in detection_kernels: + convolved_values = convolve2d(player_markers, kernel, mode="valid") + if (convolved_values == 3).any(): + return marker + + return None + + # TODO + # implement the abstract method is_terminal + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state as input and it returns True if the game state + # is terminal and False otherwise. + # In this game, a state is terminal if there are no more legal actions + # or if there is a winner. + def is_terminal(game_state): + # game is over if the board is full + remaining_actions = TicTacToeGameEnvironment.get_legal_actions(game_state) + winner = TicTacToeGameEnvironment.get_winner(game_state) + + return len(remaining_actions) == 0 or winner is not None + + # TODO + # implement the abstract method payoff + # This method is a static method (i.e. we do not have access to self + # and it can only be accessed via the class TicTacToeGameEnvironment) + # It takes a game_state and the player name ('X' or 'O') as input and it returns + # the payoff value for that player in the given game state + # In this scenario, we are only considering terminal states with a winner + # if there is not a winner yet (or there is a tie) we return 0 + # In other games the payoff function may be more complex + def payoff(game_state, player_name): + winner = TicTacToeGameEnvironment.get_winner(game_state) + if winner is None: + return 0 + elif winner == player_name: + return 1 + else: + return -1 + \ No newline at end of file diff --git a/week4/solution/tictactoe_ttable.py b/week4/solution/tictactoe_ttable.py new file mode 100644 index 0000000000000000000000000000000000000000..80303dec3f37091f181d9234190ed0ea2f803ac2 --- /dev/null +++ b/week4/solution/tictactoe_ttable.py @@ -0,0 +1,40 @@ +import random + +from une_ai.models import TTable + +class TicTacToeTTable(TTable): + + def __init__(self, saving_directory='./transposition-tables/', instance_id=None, verbose=False): + super().__init__(saving_directory, instance_id, verbose) + + def generate_zobrist_table(self): + random_int = lambda: random.randint(0, pow(2, 64)) + + markers = ['X', 'O'] + board_size = 3 + table = {} + for i in range(board_size): + for j in range(board_size): + for k in markers: + table["{0}-{1}-{2}".format(i, j, k)] = random_int() + + table["player-turn-X"] = random_int() + table["player-turn-O"] = random_int() + + return table + + def compute_hash(self, state): + zobrist_table = self.get_zobrist_table() + + player = state['player-turn'] + + h = 0 + h ^= zobrist_table['player-turn-{0}'.format(player)] + game_board = state['game-board'] + for i in range(game_board.get_width()): + for j in range(game_board.get_height()): + board_value = game_board.get_item_value(i, j) + if (board_value is not None): + h ^= zobrist_table["{0}-{1}-{2}".format(i, j, board_value)] + + return str(h) \ No newline at end of file diff --git a/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/transposition-table.json b/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/transposition-table.json new file mode 100644 index 0000000000000000000000000000000000000000..3528ad1a239201d420b7b0b4bf943e35f77c3b8e --- /dev/null +++ b/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/transposition-table.json @@ -0,0 +1 @@ +{"transposition-table": {"4099513482171967435": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "12700593112692420742": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "14323438788086110165": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "12290224288476396075": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "16600449493354487025": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "2424825604341255177": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "8006745252878637748": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "8523175948323812633": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "9464698414721115307": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "2656719099727350006": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "5933508334205267877": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "4472276789333328475": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8286545286395225217": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13058657568752874617": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "18123243245819601604": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16345668109111987561": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "4873986929362077606": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "7818746312443706550": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10566203537467788456": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "18368498760995152214": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "12827664949386397580": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8485652068589803380": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "4285190370057421257": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "2462843153991642724": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "1417746014942991085": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-2-0"}}, "4363703731967699453": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-0"}}, "12982481909370994352": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-2"}}, "12602546724929582109": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-0"}}, "16287897498683888327": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-1"}}, "2723603191680434751": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-0"}}, "7743716104275727490": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-0"}}, "8224417310648941359": {"dict-values": {"value": 0, "depth": 4, "move_best": "mark-1-0"}}, "5129414005310253333": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "7497776283224527365": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16188334144042255688": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10821593238622052891": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13153240841404262719": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8164920629073738183": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "4608513263990927226": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "2783630672894673111": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "6294204677320075257": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "8681713988093861097": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "17356401480962853796": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9680719006100335863": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16866091426899050761": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "7005761671723448107": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "3423419027475095958": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "3951810040719560251": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "3992583512307102202": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "1750392397553552106": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10443657814814252455": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16603033388518816500": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9953347193554523914": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "14325499109472252368": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "5743054023784789909": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "6261874885942827064": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "15703617676110193203": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "17783677000977471779": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9108996358312742510": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "643775569895336253": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "7252924156310734019": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "2902729476678230553": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "17261879291647062753": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13285709705323039729": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "9800942438101338278": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-0"}}, "824693508656095906": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "9499236824170722799": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "17677349931228074684": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "11032172523101880130": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "15417272290151864728": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "1311450882063518048": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "6667631784432033757": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "5034431698535903344": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "11125698827003037641": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17068903960491745434": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9270760818212965732": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "14719833806689790910": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "829023031358307142": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4988390131134279163": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6660710984896512598": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "15148182301677695881": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3177942585167561623": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4635021634322837097": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "918143464253049011": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "14662581618847979595": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9637965036805885686": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "11282965259766014299": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "9382720682090735298": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "762209292513161615": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1179343501967571746": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6679647115918401016": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "11201804119318334720": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "15406769347641875389": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "14743127301689193488": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "15471430557664271674": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6778031725901957751": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2924778325624204580": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "590342122025920000": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "14985520907763807992": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9316920369633517637": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10959952290685210600": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "14322369360585184214": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5649397272956060827": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4098330044768330696": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6100274240405491254": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16105317347729799188": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10464833522055442089": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9831153032365654276": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "12029755961770558933": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3339331850462941848": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6399950651167389131": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3790209384570902581": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8680273049955942127": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17369133514562238634": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16743897272295511815": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "5220995581107394076": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13893961359161246033": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13139187777397466626": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "15717408513108069372": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10876319300905839910": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5851970392549948894": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "493339069460038862": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "3943766700382832537": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "12463206873826152191": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "15740279756638923180": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13130248445502932050": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "18074918271439970952": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "4400316665181041264": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8334485990054880461": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "7710094277978540896": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "2439636977051518121": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6295422543179359226": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4257417999698284036": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8645330319637522654": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12699149056355989542": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18340745244464508571": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16704591661759709494": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "232063886430566535": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8030132058972755321": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2566985319446115235": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16454412899713491803": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12313627749392528870": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12949819315065002571": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "2716176633016060575": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4575652527888728114": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8327431383280215784": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12994829337154172432": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18081374187687911597": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16408928165961928448": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "8156655408722407783": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "555283563684795956": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2815721845675924752": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16200968277603601896": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12569120667175705429": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13203348612456215800": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "7008891789982007179": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1711953243789465816": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8902105769924228390": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17339898556286419716": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13697887061483902393": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12055397923097475604": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "105154756160383368": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8643274258534928091": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1998369302762185509": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6292834112241206783": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16008515425483375546": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "14374470534518959127": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "17290270251938970177": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "11057991553278680338": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17671375986758643948": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13389861222932518454": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9084962217678784206": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3024893190485376990": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "1844567072886586505": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "5968750430480056033": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "4512031281291645727": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8246923835075507653": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13093344411366843709": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "18090956636955210624": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16310408420570946605": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "16138687323514877111": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12948012698517100873": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18401591466488872851": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4078439539869282155": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8512539211838585302": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8031983512815326843": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "5433381060539272391": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2823626289492566329": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7764355452969600995": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12395765396645582619": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16338356426844635558": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18151841482285624843": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "13247914811907905407": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18101388946710622629": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4391888701398131037": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8234838420322203616": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7718552750657968205": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "10309078858142220665": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12661452495585217117": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7525674545805154981": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2795481137550609432": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4584172339232269237": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "11486399548526628757": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17523319129091400299": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8648677316295644233": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3944410393336595188": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3452175580839144793": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "18399143790469552534": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10601004738074539112": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16136772017366766258": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6236460850661119223": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5753796184956697434": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "1283551548990229087": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9050160724652386209": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3564493798751764859": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17776185944724197763": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "11628122417844840595": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "10465450832035605444": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "5195875366878032972": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "357037941664633494": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "14065417610619290222": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10198819872617829587": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10726650309147016062": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "14210569209720258074": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9932992873119930560": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5629225421899925560": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "46193621914459781": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1869512705057468712": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "5884243953037461098": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2109384130331386032": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "15744614424486539336": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10681132102774875893": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "10191305326003013976": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "10471912523189216615": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "15977845649527669693": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1908021150276080453": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6107370688770426360": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5590223281129351765": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "15650011330561600782": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2230989035097767414": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5786293044825500491": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5267172937231566054": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "9631462867092735288": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1045054634259297050": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4628536926873232807": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6444113350100027914": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16544206541822825275": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12211463326030198241": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2308901354768708516": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4134047929620372489": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "801113723371094258": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5183961669194212904": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "9238909761057109712": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "15553711476962529216": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16697730587295550615": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "7547120871071956840": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "12644648308385738640": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "16267506309027035437": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "17911943749804840576": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "16542181078457333054": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2474640986209150406": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7848835946449892219": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8482918616606989526": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "8146659741101215054": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13170967366163307958": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17902854573408979723": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "16223791448009155750": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "12822877995390856771": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8516888878044200635": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4073799602726545414": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2440036321796458411": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16283673396545387272": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2755403058881866736": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7531762485087812941": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8202173328935064288": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "7118064318163803876": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3203022095959279705": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "3829925129102518260": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "14213188203423373343": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "5495073119943515738": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "6131546300415078903": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "3150716282339331030": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17041485843234904878": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13515676597049057854": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "10084395125053776233": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "16399244136225769802": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "12479135708840009719": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "13004989395262189658": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "7978322308641587996": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2306876234996389281": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4131595855438166540": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "18025565195473746796": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13014477556663152081": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12522678084231316092": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "4241564345357228129": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8387402507253632732": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7868845285186527601": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "7697260310618164522": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "2623684404013423511": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "4412674604102710330": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "4490554854452934354": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "8136524248362164335": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7619939442780049346": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "48812684341262464": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "1871423613579532077": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "11569892674708913652": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "17833785317557863652": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "14347895481683969971": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "7703645864474988303": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "8339842038613565602": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "16700958618664387929": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18343287022160145140": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "8312137155670326569": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "7642449726084747908": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "12943372757112954404": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12318985241186382217": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16406369105207004015": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "18085025613136045250": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "13199117467379036311": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "12572190178377588538": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "12059083399179697787": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-0"}}, "13695362120084115926": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "3510634610711090204": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "61893959169464139": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "4397211213709604383": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "12694354550997089353": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "2644868486793790521": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16451308204301330228": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "12988927314350355071": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "16195645970291214727": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "17344674026326083435": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "10413915955099521384": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-0"}}, "5647793563612856822": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-0"}}, "6283987603423227483": {"dict-values": {"value": 0, "depth": 4, "move_best": "mark-0-0"}}, "13794990427957187261": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-0-2"}}, "11943424501003573264": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-0-2"}}, "16812096072711519946": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-0-1"}}, "3357014176790277682": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-0-1"}}, "6930363572922939535": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-0-1"}}, "8752838027429992226": {"dict-values": {"value": 0, "depth": 4, "move_best": "mark-0-2"}}, "7297288283860663069": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "3002260530717269447": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "17180175799679536447": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "11589772528003931010": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "13367510018738320431": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-2-0"}}, "8865245049487924995": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "3253458884945015668": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "16924678342093906828": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "11843221415038367025": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "13622922801042627228": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-2-0"}}, "7742103878004969967": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "8196355126314113858": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "18056723497256529248": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "12983108286017747933": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "12499898056421577840": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-2-0"}}, "810782307065497580": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "1265034087672909121": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "6728743770868116379": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "15284166489941355998": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "14792512013460046451": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-2-0"}}, "16557077933638620197": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "18377142044992970376": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "12963532710928054354": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "8368157080824621226": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "2580417259349381562": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-2-0"}}, "345825483077849565": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "2162477187090652016": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "5975617585291132330": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "10748889852077911378": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "15821321645463682031": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "14034741508256666690": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-2"}}, "5361262787521560589": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "470636169844500183": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "13929101260829849135": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "10373199124594778258": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "10853897856763514687": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-1-0"}}, "6063402516246733843": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "145450613044430948": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "14250141671703255196": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "10050264366855818785": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "10532931126055084428": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-1-0"}}, "4923383703770835711": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "6817720439771209810": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "15399068591025329776": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "11173256004791468237": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9393007025220661088": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-1-0"}}, "2621762558357650684": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "4516099826657343057": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "8233540949014958219": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "18104014617062545102": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "16315321390605547875": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-1-0"}}, "14619999104669921077": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "14999973321698682264": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "11296608140941443906": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "6558243360038228922": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "931504889300953770": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-1-0"}}, "10855749213970074685": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "2129725097955736095": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "5995795071202143394": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "5359456065745617679": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "159952210444874829": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "9876763855023096431": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "14387393381111813330": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "16068704045718043519": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "5577527501214191569": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "278169702540253548": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "1912212220770399937": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "15436263033453590303": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "6706295957106295101": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "1417110838902101888": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "792455344965269549": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "13117190431019901212": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "8330417479033225603": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "7696191837767544366": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "6381437586810516181": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "15251009650559124727": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9532054624204733927": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "13872890728240209994": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "522552022917722290": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "5330960288156231183": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "5813772322478885282": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-2"}}, "6060003731362158650": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10655349176505682114": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "15953014283734310527": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "14137281689086947794": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "10728639805169842999": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "5991436604617452495": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "2134356243292552562": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "345381397676479199": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "5179064111916059536": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "676843098559683885": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "1166830371850760832": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "16152346755892039019": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "7590150270990256942": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "8070567397488829571": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "1057885584478068386": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "14512937226581511770": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "11422992155239069514": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "5453713223223760488": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "366024263698890965": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-2"}}, "2036095544353124216": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "16082467093180132888": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "10487613545229924517": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "9862522307503658760": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "2290883993929288981": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "5868683660951067560": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "5198292578285302789": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-1"}}, "1965378474925417382": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "6196239674651505947": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "5523871768862186166": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "2718661756984749556": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-1-0"}}, "4390846127425831513": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "9621745440602548352": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-1-0"}}, "15161825354251719056": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "14038410491664994349": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-2-0"}}, "15818815395761045376": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "6218747754642696285": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "5699486879492229104": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "10860380354978368336": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "10367877160743724285": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-1"}}, "10537127842699126243": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "10047160014904986190": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-1"}}, "9389357489450396431": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-0"}}, "11175816474185303202": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "1562622637540245864": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "10753648829442631997": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-2"}}, "118148530375905613": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "13932170428298293824": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-1"}}, "14255498819763674355": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-1"}}, "15394257592992535071": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-0"}}, "13083629770297082908": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-0"}}, "5061473692851856348": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "614439985365611873": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "1284413017393289932": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "13642303794290838801": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "8701300517689126286": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "7031510471259079203": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "6040953945375497944": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "15635605441739942138": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "10309308109920981482": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-2"}}, "11509341618124674874": {"dict-values": {"value": 0, "depth": 3, "move_best": "mark-1-2"}}, "6376947464499201986": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "1640556587857056127": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "1121861102204600018": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "16965629326505779558": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "7065880920213350179": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "8888635060842449038": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "429233268511027887": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "13993497356060615255": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-2"}}, "10798561945551788871": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "1481815039621718296": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-2-1"}}, "6497406208223475621": {"dict-values": {"value": -1, "depth": 3, "move_best": "mark-2-1"}}, "4863509061750872072": {"dict-values": {"value": 0, "depth": 4, "move_best": "mark-2-1"}}, "1161015529181515691": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "6820661022617737494": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "5184223905499690683": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "3377713195537957369": {"dict-values": {"value": 0, "depth": 1, "move_best": "mark-0-1"}}, "4014333985444245076": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "10294633601646068877": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "15650910182611631517": {"dict-values": {"value": 1, "depth": 2, "move_best": "mark-0-1"}}, "11379890731682277213": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-2-1"}}, "9563593297296918768": {"dict-values": {"value": -1, "depth": 2, "move_best": "mark-2-1"}}, "11052336813930105326": {"dict-values": {"value": -1, "depth": 1, "move_best": "mark-0-1"}}, "9238012010780223043": {"dict-values": {"value": -1, "depth": 2, "move_best": "mark-0-1"}}, "2230725705575001445": {"dict-values": {"value": -1, "depth": 2, "move_best": "mark-0-1"}}, "14556670869290655309": {"dict-values": {"value": -1, "depth": 2, "move_best": "mark-2-1"}}, "14884142310784823550": {"dict-values": {"value": -1, "depth": 2, "move_best": "mark-0-1"}}, "13747466299443505169": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-0-2"}}, "4709694322703583140": {"dict-values": {"value": 0, "depth": 4, "move_best": "mark-2-2"}}, "12671658851982464109": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-1-2"}}, "2662706289029833295": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-1"}}, "9569651910559459131": {"dict-values": {"value": 0, "depth": 2, "move_best": "mark-2-1"}}}, "instance-id": "6879eb26-1ba1-11ee-8577-9e02763478a3", "saving-dir": "./transposition-tables/", "zobrist-table-file": "./transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/zobrist-table.json", "tt-file": "./transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/transposition-table.json"} \ No newline at end of file diff --git a/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/zobrist-table.json b/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/zobrist-table.json new file mode 100644 index 0000000000000000000000000000000000000000..1f3b4d62242805d4f4ec97e4d107a1b823107b9e --- /dev/null +++ b/week4/solution/transposition-tables/6879eb26-1ba1-11ee-8577-9e02763478a3/zobrist-table.json @@ -0,0 +1 @@ +{"0-0-X": 1209582850043935205, "0-0-O": 13590033504523610353, "0-1-X": 717897652890327687, "0-1-O": 7336854807314348506, "0-2-X": 6906070904567346928, "0-2-O": 8154855730136177029, "1-0-X": 12570020322885269210, "1-0-O": 3581521696718611111, "1-1-X": 9183118409133211092, "1-1-O": 3881689084203609233, "1-2-X": 10957636347025221128, "1-2-O": 1232541916524302214, "2-0-X": 9318945930148859338, "2-0-O": 11901609554673605335, "2-1-X": 1384940336963637290, "2-1-O": 7015773718815102825, "2-2-X": 15468248830439387317, "2-2-O": 18418643623026842703, "player-turn-X": 6283987603423227483, "player-turn-O": 11009818989127872835} \ No newline at end of file