Example #1
0
def test_whenMainBoardIsFinishedThenGetValidBoardsIsEmpty():
    main_board = MainBoard()
    main_board = force_sub_board_win(main_board, 0, 0, Player.ME)
    main_board = force_sub_board_win(main_board, 1, 1, Player.ME)
    main_board = force_sub_board_win(main_board, 2, 2, Player.ME)

    assert len(main_board.get_playable_coords()) == 0
Example #2
0
def test_whenSubBoardsArePlayedThenGetSubBoardReturnsCorrectly():
    main_board = MainBoard(3)
    main_board = force_sub_board_win(main_board, 0, 0, Player.ME)
    sub_board = main_board.get_sub_board(MainBoardCoords(0, 0))
    assert (sub_board.is_finished)
    assert (sub_board.winner == Player.ME)

    other_sub_board = main_board.get_sub_board(MainBoardCoords(0, 1))
    assert (not other_sub_board.is_finished)
Example #3
0
def test_row_col_checks_work():
    main_board = MainBoard()

    for game_event in get_game_events('engine/tests/logs/diag_fail.gamelog'):
        main_board = main_board._add_move(game_event[0], game_event[1], game_event[2])

    assert is_diagonal_won(main_board._board[0][1]._board, Player.OPPONENT) is True
    assert is_col_won(main_board._board[0][2]._board, MainBoardCoords(0, 1), Player.ME) is True
    assert is_row_won(main_board._board[2][1]._board, MainBoardCoords(1, 1), Player.ME) is True
Example #4
0
 def __init__(self):
     super().__init__(
     )  #means: get all initialisation attributes from base class
     self.children = []
     self.visited = True
     self.plays = 0
     self.wins = 0
     self.player = 1
     self.board_state = MainBoard(
         3)  #should be an array storing the game state
     self.sub_board = MonteCarlo.pick_next_main_board_coords(board_state)
Example #5
0
def test_whenBoardInitializedThenAllSubBoardsInitialized():
    board = MainBoard(3)._board

    assert len(board) == 3  # Rows
    for row in board:
        assert len(row) == 3  # Columns
        for sub_board in row:
            assert str(sub_board) == '0 0 0 \n0 0 0 \n0 0 0 \n'
Example #6
0
def test_whenAllSubBoardsAreFinishedThenMainBoardIsFinished():
    main_board = MainBoard(3)

    for row in main_board._board:
        for sub_board in row:
            sub_board._is_finished = True

    assert main_board.is_finished == True
Example #7
0
def test_whenNextBoardIsFinishedThenGetValidBoardsReturnsAllAvailableBoards():
    main_board = MainBoard()
    # Force some sub_board plays to finish a board
    finished_sub_board = main_board._board[2][2] \
        .add_my_move(SubBoardCoords(0, 0)) \
        .add_my_move(SubBoardCoords(1, 1)) \
        .add_my_move(SubBoardCoords(2, 2))

    # Set that sub-board where the sub_board_next_player_must_play will be
    main_board._board[2][2] = finished_sub_board
    # Play a move that will make the finished board the next board (Move 2, 2)
    main_board = main_board.add_my_move(MainBoardCoords(0, 0), SubBoardCoords(2, 2))
    # Playing anywhere is now allowed
    valid_boards = main_board.get_playable_coords()
    assert len(valid_boards) == 8
    assert valid_boards == [MainBoardCoords(0, 0), MainBoardCoords(0, 1), MainBoardCoords(0, 2),
                            MainBoardCoords(1, 0), MainBoardCoords(1, 1), MainBoardCoords(1, 2),
                            MainBoardCoords(2, 0), MainBoardCoords(2, 1)]
Example #8
0
def test_whenRowOfSubBoardsIsWonThenMainBoardIsWon():
    # LTR Diag check
    ltr_check = MainBoard()
    ltr_check = force_sub_board_win(ltr_check, 0, 0, Player.ME)
    ltr_check = force_sub_board_win(ltr_check, 1, 1, Player.ME)
    ltr_check = force_sub_board_win(ltr_check, 2, 2, Player.ME)

    print(str(ltr_check))

    assert ltr_check.is_finished == True
    assert ltr_check.winner == Player.ME

    # RTL Diag check
    rtl_check = MainBoard()
    rtl_check = force_sub_board_win(rtl_check, 0, 2, Player.OPPONENT)
    rtl_check = force_sub_board_win(rtl_check, 1, 1, Player.OPPONENT)
    rtl_check = force_sub_board_win(rtl_check, 2, 0, Player.OPPONENT)

    assert rtl_check.is_finished == True
    assert rtl_check.winner == Player.OPPONENT

    # Row check
    row_check = MainBoard()
    row_check = force_sub_board_win(row_check, 0, 0, Player.ME)
    row_check = force_sub_board_win(row_check, 1, 0, Player.ME)
    row_check = force_sub_board_win(row_check, 2, 0, Player.ME)

    assert row_check.is_finished == True
    assert row_check.winner == Player.ME

    # Col check
    col_check = MainBoard()
    col_check = force_sub_board_win(col_check, 0, 2, Player.OPPONENT)
    col_check = force_sub_board_win(col_check, 1, 2, Player.OPPONENT)
    col_check = force_sub_board_win(col_check, 2, 2, Player.OPPONENT)

    assert col_check.is_finished == True
    assert col_check.winner == Player.OPPONENT
Example #9
0
def test_whenAllSubBoardsFinishedWithNoWinnerThenResultIsATie():
    main_board = MainBoard(3)
    main_board = force_sub_board_win(main_board, 0, 0, Player.ME)
    main_board = force_sub_board_win(main_board, 1, 1, Player.OPPONENT)
    main_board = force_sub_board_tie(main_board, 2, 2)
    main_board = force_sub_board_tie(main_board, 0, 1)
    main_board = force_sub_board_tie(main_board, 1, 0)
    main_board = force_sub_board_tie(main_board, 1, 2)
    main_board = force_sub_board_tie(main_board, 2, 1)
    main_board = force_sub_board_win(main_board, 0, 2, Player.ME)
    main_board = force_sub_board_win(main_board, 2, 0, Player.OPPONENT)

    assert main_board.is_finished == True
    assert main_board.winner == Player.NONE
Example #10
0
def test_whenBoardIsPrettyPrintedThenItIsRenderedCorrectly():
    string_board = str(MainBoard(3).add_my_move(MainBoardCoords(0, 0), SubBoardCoords(1, 1))
                       .add_opponent_move(MainBoardCoords(1, 1), SubBoardCoords(2, 2))
                       .add_opponent_move(MainBoardCoords(2, 2), SubBoardCoords(0, 0)))

    assert string_board == "0 0 0 | 0 0 0 | 0 0 0 \n" \
                           "0 1 0 | 0 0 0 | 0 0 0 \n" \
                           "0 0 0 | 0 0 0 | 0 0 0 \n" \
                           "- - - | - - - | - - - \n" \
                           "0 0 0 | 0 0 0 | 0 0 0 \n" \
                           "0 0 0 | 0 0 0 | 0 0 0 \n" \
                           "0 0 0 | 0 0 2 | 0 0 0 \n" \
                           "- - - | - - - | - - - \n" \
                           "0 0 0 | 0 0 0 | 2 0 0 \n" \
                           "0 0 0 | 0 0 0 | 0 0 0 \n" \
                           "0 0 0 | 0 0 0 | 0 0 0 \n"
Example #11
0
def test_whenNextBoardIsFinishedThenAnyBoardCanBePlayed():
    main_board = MainBoard()
    # Force some sub_board plays to finish a board
    finished_sub_board = main_board._board[2][2] \
        .add_my_move(SubBoardCoords(0, 0)) \
        .add_my_move(SubBoardCoords(1, 1)) \
        .add_my_move(SubBoardCoords(2, 2))

    # Set that sub-board where the sub_board_next_player_must_play will be
    main_board._board[2][2] = finished_sub_board
    # Play a move that will make the finished board the next board (Move 2, 2)
    main_board = main_board.add_my_move(MainBoardCoords(0, 0), SubBoardCoords(2, 2))
    # Playing anywhere is now allowed
    assert main_board.sub_board_next_player_must_play == None
    assert main_board.is_playing_on_sub_board_allowed(MainBoardCoords(1, 1)) == True
    main_board.add_opponent_move(MainBoardCoords(0, 0), SubBoardCoords(1, 1))
Example #12
0
def test_whenNextBoardIsAvailableThenGetValidBoardsReturnsOnlyThatBoard():
    board = MainBoard().add_my_move(MainBoardCoords(0, 0), SubBoardCoords(2, 2))

    # Only valid board now should be 2, 2
    assert len(board.get_playable_coords()) == 1
    assert board.get_playable_coords()[0] == MainBoardCoords(2, 2)
Example #13
0
def test_whenNoGivenSizeThenSizeIs3():
    board = MainBoard()._board

    assert len(board) == 3  # Rows
    for row in board:
        assert len(row) == 3  # Columns
Example #14
0
def test_whenNewMoveIsOutsideValidSubBoardBoundsThenExceptionRaised():
    with pytest.raises(MoveOutsideSubBoardError):
        MainBoard().add_my_move(MainBoardCoords(1, 1), SubBoardCoords(1, 3))
Example #15
0
def test_whenNewMoveIsNotOnGameNextBoardThenExceptionRaised():
    board = MainBoard().add_my_move(MainBoardCoords(0, 0), SubBoardCoords(1, 1))

    # Move must now be on board at 1, 1
    with pytest.raises(MoveNotOnNextBoardError):
        board.add_opponent_move(MainBoardCoords(1, 0), SubBoardCoords(1, 1))
Example #16
0
def test_whenNewMoveSubBoardCoordsAreOutOfBoundsThenExceptionRaised():
    with pytest.raises(MoveOutsideMainBoardError):
        MainBoard().add_my_move(MainBoardCoords(1, 3), SubBoardCoords(0, 0))

    with pytest.raises(MoveOutsideMainBoardError):
        MainBoard().add_opponent_move(MainBoardCoords(3, 1), SubBoardCoords(0, 0))
Example #17
0
def test_whenInitSizeIsStringThenExceptionRaised():
    with pytest.raises(ValueError):
        MainBoard("mustFail")
Example #18
0
def test_whenBoardNewThenBoardIsNotFinished():
    assert MainBoard().is_finished == False
Example #19
0
def test_whenInitSizeNot3ExceptionRaised():
    with pytest.raises(ValueError):
        MainBoard(4)

    with pytest.raises(ValueError):
        MainBoard(2)
Example #20
0
def test_whenMainBoardIsNotFinishedThenWinnerCheckRaisesException():
    with pytest.raises(BoardNotFinishedError):
        MainBoard().winner
Example #21
0
def test_whenMainBoardIsFinishedThenNewMoveRaisesException():
    main_board = MainBoard()
    main_board._is_finished = True

    with pytest.raises(MoveInFinishedBoardError):
        main_board.add_my_move(MainBoardCoords(1, 1), SubBoardCoords(1, 1))
Example #22
0
class MonteCarlo(StdOutPlayer):
    def __init__(self):
        super().__init__(
        )  #means: get all initialisation attributes from base class
        self.children = []
        self.visited = True
        self.plays = 0
        self.wins = 0
        self.player = 1
        self.board_state = MainBoard(
            3)  #should be an array storing the game state
        self.sub_board = MonteCarlo.pick_next_main_board_coords(board_state)

    def CreateChildren(self):
        legal_moves = list(
            self.board_state.get_sub_board.get_playable_coords())
        for move in legal_moves:
            self.children.append(Node(self.board_state.add_my_move(move)))

    def get_my_move(self):  # -> Tuple[MainBoardCoords, SubBoardCoords
        main_board_coords = self.pick_next_main_board_coords()
        sub_board = self.main_board.get_sub_board(main_board_coords)
        sub_board_coords = self.pick_random_sub_board_coords(sub_board)
        return main_board_coords, sub_board_coords

    def pick_next_main_board_coords(self) -> MainBoardCoords:
        if self.main_board.sub_board_next_player_must_play is None:
            return random.choice(self.main_board.get_playable_coords())
        else:
            return self.main_board.sub_board_next_player_must_play

    @staticmethod
    def pick_random_sub_board_coords(
        sub_board: SubBoard
    ) -> SubBoardCoords:  #this means: argument should be of type 'SubBoard' and
        # #do we need to pass legal moves now so we can make the kids?)
        self.CreateChildren()
        print(main_board)
        return monte_carlo_tree_search(self)

    def monte_carlo_tree_search(node):
        begin = datetime.datetime.utcnow()

    while datetime.datetime.utcnow() - begin < datetime.timedelta(
            milliseconds=4.9):
        #if all root node's children are visited:
        if all(child.visited for child in node.children):
            for child in node.children:
                print(child.visited)
                #next node to explore is one with max UCT
            return max_uct(node)  #this returns the best poss next move
        #if some unvisited:
        else:
            node.run_simulation(node)
    return max_uct(node)

    def run_simulation(node):
        pdb.set_trace()

    print('mainboard:' + self.main_board)
    if self.MainBoard.is_finished():  ###
        node.plays += 1  #shouldn't be self.?
        if MainBoard.winner == 1:
            node.wins += 1
            return node.plays, node.wins
        elif MainBoard.winner == 2:
            node.wins -= 1
            return node.plays, node.wins
        else:  #draw
            return node.plays  #just return result? don't need three if statements
    else:
        node.CreateChildren()
        next_child = random.choice(node.children)
        print('next child:', next_child)
        node.visited = True
        node.wins = wins + run_simulation(next_child)
        print('wins:', node.wins)
        #make this wins, play = ?
    def max_uct(node, c=1.4):
        for child in node.children:
            print('wins:', child.wins, 'plays:', child.plays)
        uct_vals = [
            (child.wins / (child.plays)) + c * np.sqrt(
                (2 * np.log(node.wins) / (node.plays)))
            for child in node.children
        ]  #first terms = ratio wins of child, second term is total ratio wins
        return 'hello'  #node.children[np.argmax(uct_vals)]