def test_choose_move(): np.random.seed(0) start_state = Connect4State() state1 = Connect4State("""\ ....... ....... ....... ...XX.. OXOXO.. XOXOXOO """) expected_display = """\ ....... ....... ....... ..XXX.. OXOXO.. XOXOXOO """ player = MctsPlayer(start_state, iteration_count=200) move = player.choose_move(state1) state2 = state1.make_move(move) display = state2.display() assert display == expected_display
def test_choose_move(): np.random.seed(0) game = Connect4Game() start_board = game.create_board("""\ ....... ....... ....... ...XX.. OXOXO.. XOXOXOO """) expected_display = """\ ....... ....... ....... ..XXX.. OXOXO.. XOXOXOO """ player = MctsPlayer(game, mcts_iterations=[200]) move = player.choose_move(start_board) board = game.make_move(start_board, move) display = game.display(board) assert expected_display == display
def test_annotate(): start_state = TicTacToeState() player = MctsPlayer(start_state, iteration_count=10, heuristic=FirstChoiceHeuristic()) player.choose_move(start_state) move_probabilities = player.get_move_probabilities(start_state) best_move, best_probability, best_count, best_value = move_probabilities[0] assert best_move == '1A' assert best_probability == approx(0.999013) assert best_count == 9 assert best_value == approx(2 / 9)
def test_play_two(): start_state = FirstPlayerWinsGame() controller = PlayController(start_state=start_state, players=[MctsPlayer(start_state), MctsPlayer(start_state)]) expected_p1_wins = 2 expected_ties = 0 expected_p2_wins = 0 p1_wins, ties, p2_wins = controller.play(games=2) assert expected_p1_wins == p1_wins assert expected_ties == ties assert expected_p2_wins == p2_wins
def test_play_one_tie(): start_state = NoPlayerWinsGame() controller = PlayController(start_state=start_state, players=[MctsPlayer(start_state), MctsPlayer(start_state)]) expected_p1_wins = 0 expected_ties = 1 expected_p2_wins = 0 p1_wins, ties, p2_wins = controller.play() assert expected_p1_wins == p1_wins assert expected_ties == ties assert expected_p2_wins == p2_wins
def on_start(self): self.game_start_time = datetime.now() self.display.update_board(self.display.start_state) self.is_history_dirty = False ui = self.ui player_fields = [(ui.player1.currentData(), ui.searches1.value()), (ui.player2.currentData(), ui.searches2.value())] is_shuffled = ui.shuffle_players.isChecked() settings = get_settings(self.start_state) settings.setValue('shuffle_players', is_shuffled) if is_shuffled: shuffle(player_fields) mcts_choices = { self.start_state.players[0]: player_fields[0], self.start_state.players[1]: player_fields[1] } self.display.mcts_players = [ MctsPlayer(self.start_state, player_number, iteration_count=searches, process_count=self.cpu_count) for player_number, (heuristic, searches) in mcts_choices.items() if heuristic is not None ] layout: QGridLayout = ui.display_page.layout() layout.replaceWidget(ui.game_display, self.display) ui.game_display.setVisible(False) ui.game_display = self.display self.display.setVisible(True) self.display.show_coordinates = ui.action_coordinates.isChecked() self.on_view_game()
def test_win_scores_one(): """ Expose bug where search continues after a game-ending position. """ state1 = TicTacToeState("""\ ..X XX. OO. """) player = MctsPlayer(TicTacToeState(), state1.X_PLAYER, iteration_count=100) move = player.choose_move(state1) search_node1 = player.search_manager.current_node.parent for child_node in search_node1.children: if child_node.move == 8: assert child_node.average_value == 1.0 assert move == 8
def test_choose_move_in_pool(): start_state = Connect4State() state1 = Connect4State("""\ ....... ....... ....... ...XX.. OXOXO.. XOXOXOO """) player = MctsPlayer(start_state, iteration_count=200, process_count=2) valid_moves = start_state.get_valid_moves() move = player.choose_move(state1) # Can't rely on which move, because other process has separate random seed. assert valid_moves[move]
def test_display(capsys): game = SecondPlayerWinsGame() heuristic = FirstChoiceHeuristic() players = [MctsPlayer(game, game.X_PLAYER, iteration_count=10, heuristic=heuristic), MctsPlayer(game, game.O_PLAYER, iteration_count=20, heuristic=heuristic)] controller = PlayController(game, players) expected_output = """\ AB 1 .. AB 1 X. AB 1 XO AB 1 .. AB 1 X. AB 1 XO ('mcts', 'first choice', '10 iterations') - 1 wins, ('mcts', 'first choice', '20 iterations') - 1 wins, 0 ties """ controller.play(games=2, flip=True, display=True) out, err = capsys.readouterr() expected_lines = expected_output.splitlines() lines = out.splitlines() assert lines[:-3] == expected_lines[:-3] for line, expected_line in zip(lines[-3:], expected_lines[-3:]): assert line.startswith(expected_line)
def test_player_results(): player = MctsPlayer(FirstPlayerWinsGame(), iteration_count=100) player_results = PlayerResults(player) player_results.move_count = 100 player_results.total_time = 1246 # seconds player_results.win_count = 1 summary = player_results.get_summary() assert summary == "('mcts', 'playout', '100 iterations') - 1 wins, 12.5s/move"
def test_choose_moves_at_random(): """ Early moves are chosen from a weighted random population. """ np.random.seed(0) game = TicTacToeGame() start_board = game.create_board("""\ ... ... X.. """) player = MctsPlayer(game, mcts_iterations=[80], heuristic=[EarlyChoiceHeuristic(game)]) moves = set() for _ in range(10): move = player.choose_move(start_board) moves.add(move) player.search_manager.reset() assert 1 < len(moves)
def test_choose_moves_at_random(): """ Early moves are chosen from a weighted random population. """ np.random.seed(0) start_state = TicTacToeState() state1 = TicTacToeState("""\ ... ... X.. """) player = MctsPlayer(start_state, iteration_count=80, heuristic=EarlyChoiceHeuristic()) moves = set() for _ in range(10): move = player.choose_move(state1) moves.add(move) player.search_manager.reset() assert 1 < len(moves)
def test_choose_move_sets_current_node(): np.random.seed(0) start_state = Connect4State() state1 = Connect4State("""\ ....... ....... ....... ....... OXOXOXO XOXOXOX """) player = MctsPlayer(start_state, iteration_count=20) move1 = player.choose_move(state1) current_node1 = player.search_manager.current_node state2 = state1.make_move(move1) move2 = player.choose_move(state2) current_node2 = player.search_manager.current_node state3 = state2.make_move(move2) assert current_node1.game_state == state2 assert current_node2.game_state == state3
def test_choose_move_no_iterations(): np.random.seed(0) game = Connect4Game() start_board = game.create_board("""\ ....... ....... ....... ...XX.. OXOXO.. XOXOXOO """) test_count = 400 expected_count = test_count/7 expected_low = expected_count * 0.9 expected_high = expected_count * 1.1 move_counts = Counter() for _ in range(test_count): player = MctsPlayer(game, mcts_iterations=[0]) move = player.choose_move(start_board) move_counts[move] += 1 assert expected_low < move_counts[2] < expected_high
def test_choose_move_no_iterations(): np.random.seed(0) start_state = Connect4State() state1 = Connect4State("""\ ....... ....... ....... ...XX.. OXOXO.. XOXOXOO """) test_count = 400 expected_count = test_count / 7 expected_low = expected_count * 0.9 expected_high = expected_count * 1.1 move_counts = Counter() for _ in range(test_count): player = MctsPlayer(start_state, iteration_count=0) move = player.choose_move(state1) move_counts[move] += 1 assert expected_low < move_counts[2] < expected_high
def test_piece_hover_enter_mcts(pixmap_differ: PixmapDiffer): """ Don't display move options while MCTS player is thinking. """ size = 240 with pixmap_differ.create_painters( size, size, 'tictactoe_piece_hover_enter_mcts') as (actual, expected): draw_square_grid(expected) display = TicTacToeDisplay() player = MctsPlayer(display.start_state, TicTacToeState.X_PLAYER) display.mcts_players = (player, ) display.resize(324, 264) display.ui.game_display.grab() display.on_hover_enter(display.spaces[0][1]) render_display(display, actual) display.close() assert display.move_text.text() == 'thinking' expected_icon = display.player1_icon.toImage() assert display.ui.player_pixmap.pixmap().toImage() == expected_icon