def recurse(node, player): current_board = node.board possible_turns = current_board.free_cells() if possible_turns is None: return None if len(possible_turns) == 1: new_board = deepcopy(current_board) new_board[possible_turns[0]] = self.markers[player] node.left = Node(new_board) recurse(node.left, "Player 1" if player == "Player 2" else "Player 2") else: shuffle(possible_turns) new_board1 = deepcopy(current_board) new_board2 = deepcopy(current_board) new_board1[possible_turns[0]] = self.markers[player] new_board2[possible_turns[1]] = self.markers[player] node.left = Node(new_board1) node.right = Node(new_board2) recurse(node.left, "Player 1" if player == "Player 2" else "Player 2") recurse(node.right, "Player 1" if player == "Player 2" else "Player 2")
def build_tree(vertex): """(board.Board) -> NoneType """ board = vertex.board winner = board.victory() if winner is None or winner == 't': return elif winner == 'x': vertex.subsum += 1 elif winner == 'o': vertex.subsum -= 1 last_symbol = board.last_symbol() new_symbol = 'x' if last_symbol == 'o' else 'o' free_positions = board.free_positions() position = random.choice(free_positions) free_positions.remove(position) board1 = copy.deepcopy(board) board1.change(position[0], position[1], new_symbol) vertex.left = Node(board1) if not free_positions: # if empty return position = random.choice(free_positions) board2 = copy.deepcopy(board) board2.change(position[0], position[1], new_symbol) vertex.right = Node(board2)
def extend_tree(tree, player_symbol): available_moves = self.empty_cells() next_symbol = o if player_symbol is x else x if self.win(self.current_symbol()): tree.insert_left(Node(1, tree.root)) return if self.lose(self.current_symbol()): tree.insert_left(Node(-1, tree.root)) return elif self.draw(): tree.insert_right(Node(0, tree.root)) return move1 = available_moves.pop(random_index(available_moves)) self.make_a_move(move1) tree.insert_left(Node(move1)) extend_tree(tree.left_child, next_symbol) self[move1[0]][move1[1]] = None self._n_moves -= 1 if available_moves: move2 = available_moves.pop(random_index(available_moves)) self.make_a_move(move2) tree.insert_right(Node(move2)) extend_tree(tree.right_child, next_symbol) self[move2[0]][move2[1]] = None self._n_moves -= 1
def build_tree(node): """ Builds a tree with all posible boards from the given board Prediction: chose next move from all posssible :param node: Node :return: None """ board = node.data if board.num_free() == 0: pass elif board.check_f('x') == "continue": sing = board.pre_pos[0] if sing == 'o': sing = 'x' elif sing == 'x': sing = 'o' free = board.get_free_lst() pos_r = random.choice(free) free.remove(pos_r) if len(free) > 0: pos_l = random.choice(free) else: pos_l = None right = board.get_same() left = board.get_same() right.add_pos(pos_r, sing) if pos_l is not None: left.add_pos(pos_l, sing) node.left = Node(left) node.right = Node(right) if node.left: build_tree(node.left) build_tree(node.right)
def help(self): check_result = self.root.data.check_board() position1 = random.choice(check_result) check_result.pop(check_result.index(position1)) position2 = random.choice(check_result) check_result.pop(check_result.index(position2)) right_board = Board([el for el in self.root.data.coors()]) right_board.add(position1, "O") left_board = Board([el for el in self.root.data.coors()]) left_board.add(position2, "O") def recur(node): if node.count != 0: node.count = node.left.count + node.right.count return node.count if type(node.data.check_board()) == int: node.count = node.data.check_board() return node.count else: check_result = node.data.check_board() if len(check_result) >= 2: position1 = random.choice(check_result) check_result.pop(check_result.index(position1)) pos_against1 = random.choice(check_result) right_board = Board([el for el in node.data.coors()]) right_board.add(position1, "O") right_board.add(pos_against1, "X") position2 = random.choice(check_result) check_result.pop(check_result.index(position2)) check_result.append(position1) left_board = Board([el for el in node.data.coors()]) left_board.add(position2, "O") pos_against2 = random.choice(check_result) left_board.add(pos_against2, "X") node.left = Node(left_board) node.left.parent = node node.right = Node(right_board) node.right.parent = node node.count += recur(node.left) + recur(node.right) return node.count else: position1 = random.choice(check_result) board = Board([el for el in node.data.coors()]) board.add(position1, "O") node.left = Node(board) node.left.parent = node recur(node.left) return node.left.data.check_board() if recur(Node(right_board)) > recur(Node(left_board)): return position1 else: return position2
def compute_score(self): has_winner = self.has_winner() if has_winner: winner_scores = {Board.NOUGHT_WINNER: 1, Board.CROSS_WINNER: -1, Board.DRAW: 0} return winner_scores[has_winner] board_tree = LinkedBinaryTree(Node(self)) left_board = copy.deepcopy(self) right_board = copy.deepcopy(self) moved_left = left_board.make_random_move() moved_right = right_board.make_random_move() board_tree.insert_left(Node(moved_left)) board_tree.insert_right(Node(moved_right)) return left_board.compute_score() + right_board.compute_score()
def _insert(self, value, cur_node): if value < cur_node.value: if cur_node.left_child == None: cur_node.left_child = Node(value) else: self._insert(value, cur_node.left_child) elif value > cur_node.value: if cur_node.right_child == None: cur_node.right_child = Node(value) else: self._insert(value, cur_node.right_child) else: print('Value already in tree!')
def build_tree(node): """ Builds a tree with all posible boards from the given board Prediction: chosse next move from two posssible :param node: Node :return: None """ if node is not None: board = node.data if board.num_free() == 0: pass elif board.check_f('o') == "continue": sing = board.pre_pos[0] if sing == 'o': sing = 'x' elif sing == 'x': sing = 'o' free = board.get_free_lst() ########################### for i in range(len(free)): new = board.get_same() new.add_pos(free[i], sing) node.boors[i] = Node(new) for i in range(len(node.boors)): build_tree(node.boors[i])
def add_child(self, node, item): """Add child to the node""" if node.tree is not self: raise ValueError('Node does not belong to a tree!!!') child = Node(self, item, node) node.children.append(child) return child
def make_step(self, field, current, cur_node=None): """ Makes step on field """ fst = False new_node = Tree(field) if cur_node == None: cur_node = new_node fst = True if field.is_full() or field.winner_sign(): cur_node.add_node(Node(field)) for x in range(3): for y in range(3): if field.field[x][y] == " ": field.field[x][y] = Board.PLAYER_SIGNS[current] self.make_step(deepcopy(field), (current + 1) % 2, new_node) field.field[x][y] = " " if fst: win_rates = [win_rate(node, current) for node in new_node.childs] step = win_rates.index(max(win_rates)) field.field = new_node.childs[step].data.field return else: cur_node.add_node(new_node) return cur_node
def _insert(self, n, key): if n == None: return Node(key) if n.get_key() > key: n.set_left(self._insert(n.get_left(), key)) elif n.get_key() < key: n.set_right(self._insert(n.get_right(), key)) return n
def winning_count(self): end_of_game = self.check_current_table() if end_of_game: if end_of_game == 1: return 1 else: return 0 node = Node(self) tree = BinaryTree(node) left_board = copy.deepcopy(self) right_board = copy.deepcopy(self) left_move = left_board.move_random() right_move = right_board.move_random() tree._root.left = Node(left_move) tree._root.right = Node(right_move) return left_board.winning_count() + right_board.winning_count()
def compute_score(self): has_winner = self.has_winner() if has_winner: winner_scores = { Board.NOUGHT_WINNER: 1, Board.CROSS_WINNER: -1, Board.DRAW: 0 } return winner_scores[has_winner] n1 = Node(self) board = Tree() board.root = n1 right_board = left_board = copy.deepcopy(self) left_move, right_move = left_board.make_random_move( ), right_board.make_random_move() board.root.left = Node(left_move) board.root.right = Node(right_move) return left_board.compute_score() + right_board.compute_score()
def build_tree(self): '''Build a tree for analyzing outcomes of a random game Algorithm: 1. Make a tree 2. recursively: a) pick a random move, update board b) if won, write 1 into tree leaf, if lost, write -1 into tree leaf if draw, write 0 into tree leaf else: a) c) clear move d) make another move, if possible e) b) 3. return the tree ''' tree = BinaryTree(Node(None)) # save to preserve board's initial state last_move = self._last_move def extend_tree(tree, player_symbol): available_moves = self.empty_cells() next_symbol = o if player_symbol is x else x if self.win(self.current_symbol()): tree.insert_left(Node(1, tree.root)) return if self.lose(self.current_symbol()): tree.insert_left(Node(-1, tree.root)) return elif self.draw(): tree.insert_right(Node(0, tree.root)) return move1 = available_moves.pop(random_index(available_moves)) self.make_a_move(move1) tree.insert_left(Node(move1)) extend_tree(tree.left_child, next_symbol) self[move1[0]][move1[1]] = None self._n_moves -= 1 if available_moves: move2 = available_moves.pop(random_index(available_moves)) self.make_a_move(move2) tree.insert_right(Node(move2)) extend_tree(tree.right_child, next_symbol) self[move2[0]][move2[1]] = None self._n_moves -= 1 extend_tree(tree, self.current_symbol()) self._last_move = last_move # return board to its initial state return tree
def add_root(self, e, mark=None): """Place element e at the root of an empty tree and return new Position. Raise ValueError if tree nonempty. """ if self._root is not None: raise ValueError('Root exists') self._size = 1 self._root = Node(e, mark=mark) return self._make_position(self._root)
def __init__(self, start_board=None): """ Initialise tree by starting board. """ # Root is a board without any step. self._root = Node() if start_board is None: self._root.set_board(Board()) else: self._root.set_board(start_board)
def count_score(self): has_winner = self.has_winner() if has_winner: scores = { Board.NOUGHT_WINNER: 1, Board.CROSS_WINNER: -1, Board.DRAW: 0 } return scores[has_winner] else: board = Tree() board.root = Node(self) board_left = copy.deepcopy(self) board_right = copy.deepcopy(self) move_L = board_left.make_random_move() move_R = board_right.make_random_move() board.root.left = Node(move_L) board.root.right = Node(move_R) result = board_left.count_score() + board_right.count_score() return result
def compute_score(self): """ The function returns sum of all scores in binary tree """ board = Tree(self) if self.has_winner(): winner_scores = { Board.NOUGHT_WINNER: 1, Board.CROSS_WINNER: -1, Board.DRAW: 0 } return winner_scores[self.has_winner()] board.key = Node(self) left_board = deepcopy(self) left_move = left_board.make_random_move() board.key.left = Node(left_move) right_board = deepcopy(self) right_move = right_board.make_random_move() board.key.right = Node(right_move) return left_board.compute_score() + right_board.compute_score()
def add_right(self, p, e, mark=None): """Create a new right child for Position p, storing element e. Return the Position of new node. Raise ValueError if Position p is invalid or p already has a right child. """ node = self._validate(p) if node._right is not None: raise ValueError('Right child exists') self._size += 1 node._right = Node(e, node, mark=mark) # node is its parent return self._make_position(node._right)
def take_turn(self): """ Compute next turn to win the game """ self.solutions_tree = LinkedBinaryTree(Node(self)) indexes = self.get_free_places() result = [] for ind in indexes: result.append(self.build_solutions_tree(self, ind, True)) best_choice = indexes[result.index(max(result))] self.place(best_choice, self.automated_player)
def new_node(node, pos): """ Helper function for creating a new node in which player moved to pos. :param node: Node :param pos: tuple :return: Node """ new_node = Node() list_of_lists = copy.deepcopy(node.board.data) new_node.set_field(list_of_lists) new_node.set_last_move(pos, not node.board.last_move_symb) new_node.board.data[pos[0]][ pos[1]] = not node.board.last_move_symb return new_node
def compute_score(self): """ Chooses better move :return: int """ has_winner = self.has_winner() if has_winner: winner_scores = { Board.NOUGHT_WINNER: 1, Board.CROSS_WINNER: -1, Board.DRAW: 0 } return winner_scores[has_winner] board = Tree() board.root = Node(self) left_board = copy.deepcopy(self) right_board = copy.deepcopy(self) left_move = left_board.make_random_move() right_move = right_board.make_random_move() board.root.left = Node(left_move) board.root.right = Node(right_move) return left_board.compute_score() + right_board.compute_score()
def add(root=None, vals=[]) -> 'Node': # Walk through the tree in a breadth-first fashion to add vals. # if not root and vals: root = Node(vals.pop(0)) q = [root] if root else [] while len(q) > 0: n = q.pop() if n.left: q.insert(0, n.left) elif vals: n.left = Node(vals.pop(0)) q.insert(0, n.left) if n.right: q.insert(0, n.right) elif vals: n.right = Node(vals.pop(0)) q.insert(0, n.right) return root
def take_turn(self): """ Compute next turn to win the game """ self.solutions_tree = LinkedBinaryTree(Node(self)) index_1, index_2 = random.sample(self.get_free_places(), 2) res_1 = self.build_solutions_tree(self, index_1, self.second_player, "left") res_2 = self.build_solutions_tree(self, index_2, self.second_player, "right") if res_1 >= res_2: self.place(index_1, self.second_player) else: self.place(index_2, self.second_player)
def build_solutions_tree(self, test_board, index, mark, side): """ Builds a binary tree to find the best next move. """ test_board = Board(copy.deepcopy(test_board.board)) if mark: symbol = self.second_player else: symbol = self.first_player mark = not mark test_board.place(index, symbol) node = Node(test_board) if side == "left": self.solutions_tree.insert_left(node) else: self.solutions_tree.insert_right(node) free_places = test_board.get_free_places() if len(free_places) == 1: return self.build_solutions_tree(test_board, free_places[0], mark, "left") if len(free_places) == 0: status = test_board.check_status() if status[1] == self.first_player: return -1 if status[1] == self.second_player: return 1 return 0 index_1, index_2 = random.sample(free_places, 2) result = 0 result += self.build_solutions_tree(test_board, index_1, mark, "left") result += self.build_solutions_tree(test_board, index_2, mark, "right") return result
def __init__(self, root_board): """(board.Board) -> NoneType """ self.root = Node(root_board) self.build_tree(self.root)
def add_right(node, item): node.right = Node(item)
def add_root(self, item): """Add root to the tree""" root = Node(self, item) self._root = root return root
def add_left(node, item): node.left = Node(item)
def __init__(self, starting_board, player="Player 1"): self._root = Node(starting_board) self.player = player self.markers = {"Player 1": "O", "Player 2": "X"}