def test_whenNewMoveIsInFinishedBoardThenExceptionRaised(): finished_board = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_my_move(SubBoardCoords(0, 1))\ .add_my_move(SubBoardCoords(0, 2)) with pytest.raises(MoveInFinishedBoardError): finished_board.add_my_move(SubBoardCoords(1, 1))
def test_whenBoardIsFinishedThenGetValidMovesIsEmpty(): board = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_opponent_move(SubBoardCoords(0, 1))\ .add_my_move(SubBoardCoords(1, 1))\ .add_opponent_move(SubBoardCoords(0, 2))\ .add_my_move(SubBoardCoords(2, 2)) assert len(board.get_playable_coords()) is 0
def test_whenRowIsBlockedThenBoardIsNotFinished(): blocked = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_my_move(SubBoardCoords(1, 1))\ .add_opponent_move(SubBoardCoords(2, 2)) assert blocked.is_finished == False with pytest.raises(BoardNotFinishedError): blocked.winner
def test_whenNewMoveIsInAlreadyPlayedCellThenExceptionRaised(): board = SubBoard().add_my_move(SubBoardCoords(1, 2)) string_board = str(board) move_count_before = board._moves_so_far with pytest.raises(MoveInPlayedCellError): board = board.add_opponent_move(SubBoardCoords(1, 2)) #Ensure board state has not changed assert string_board == str(board) assert board._moves_so_far == move_count_before
def getMaxValue(self, arr): maxCoord = SubBoardCoords(0, 0) maxValue = -9999 for x in range(3): for y in range(3): if (arr[x][y] > maxValue): maxCoord = SubBoardCoords(x, y) maxValue = arr[x][y] return maxCoord
def test_whenBoardIsPlayedThenGetValidMovesReturnsCorrectly(): board = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_opponent_move(SubBoardCoords(1, 1))\ .add_my_move(SubBoardCoords(2, 1)) assert board.get_playable_coords() == \ [SubBoardCoords(0, 1), SubBoardCoords(0, 2), \ SubBoardCoords(1, 0), SubBoardCoords(1, 2), \ SubBoardCoords(2, 0), SubBoardCoords(2, 2)]
def force_sub_board_tie(main_board, board_row, board_col): return main_board \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(0, 0), Player.ME) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(1, 1), Player.OPPONENT) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(2, 2), Player.ME) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(0, 2), Player.OPPONENT) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(2, 0), Player.ME) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(1, 0), Player.OPPONENT) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(1, 2), Player.ME) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(2, 1), Player.OPPONENT) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(0, 1), Player.ME)
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"
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))
def parse_move(received_move: str): main_board_coords_str, opponent_move_str = received_move.split(";") main_board_coords = MainBoardCoords( *map(int, main_board_coords_str.split(","))) sub_board_coords = SubBoardCoords( *map(int, opponent_move_str.split(","))) return main_board_coords, sub_board_coords
def get_game_events(filename): log_file = open(filename, 'r') lines = log_file.readlines() log_file.close() game_events = [] for line in lines: line = line.strip() player = Player.NONE if 'opponent' in line: player = Player.OPPONENT elif 'player' in line: player = Player.ME else: continue move_str = line[-7:] main_board_coords = MainBoardCoords(int(move_str[0]), int(move_str[2])) sub_board_coords = SubBoardCoords(int(move_str[4]), int(move_str[6])) game_events.append((main_board_coords, sub_board_coords, player)) return game_events
def test_whenBoardReachesMaxMovesThenBoardIsFinishedAndTied(): tied_board = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_opponent_move(SubBoardCoords(2, 2))\ .add_my_move(SubBoardCoords(2, 0))\ .add_opponent_move(SubBoardCoords(1, 0))\ .add_my_move(SubBoardCoords(0, 2))\ .add_opponent_move(SubBoardCoords(0, 1))\ .add_my_move(SubBoardCoords(1, 2))\ .add_opponent_move(SubBoardCoords(1, 1))\ .add_my_move(SubBoardCoords(2, 1)) assert tied_board.is_finished == True assert tied_board.winner == Player.NONE
def read_move(input_line: str): received_move = input_line.split(" ")[1] main_board_coords_str, opponent_move_str = received_move.split(";") main_board_coords = MainBoardCoords( *map(int, main_board_coords_str.split(","))) sub_board_coords = SubBoardCoords( *map(int, opponent_move_str.split(","))) return main_board_coords, sub_board_coords
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)]
def winnableBy(self, subBoard: SubBoard): #print(subBoard) playable = subBoard.get_playable_coords() for x in range(0, len(subBoard.get_playable_coords())): tmpBoard = subBoard.add_opponent_move( SubBoardCoords(playable[x].row, playable[x].col)) if tmpBoard.is_finished: if tmpBoard.winner == Player.ME or tmpBoard.winner == Player.OPPONENT: #print(tmpBoard.winner) return tmpBoard.winner for x in range(0, len(subBoard.get_playable_coords())): tmpBoard = subBoard.add_my_move( SubBoardCoords(playable[x].row, playable[x].col)) if tmpBoard.is_finished: if tmpBoard.winner == Player.ME or tmpBoard.winner == Player.OPPONENT: #print(tmpBoard.winner) return tmpBoard.winner return 0
def get_closeable_positions(self, board, playerNo): subBoard = self.main_board.get_sub_board(board) rows = ([ SubBoardCoords(i, x) for i, x in enumerate( [self.get_winning_position(row, playerNo) for row in subBoard]) if x is not None ] + [ SubBoardCoords(x, i) for i, x in enumerate([ self.get_winning_position(column, playerNo) for column in self._columns(subBoard) ]) if x is not None ] + (lambda x: [SubBoardCoords(x, x)] if x is not None else [])(self.get_winning_position( self._major_diagonal(subBoard), playerNo)) + (lambda x: [SubBoardCoords(x, len(subBoard[0]) - 1 - x)] if x is not None else [])(self.get_winning_position( self._minor_diagonal(subBoard), playerNo))) return [x for x in rows if x is not None]
def test_whenRowIsWonThenBoardIsFinishedAndWon(): #LTR Diag check i_win = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_my_move(SubBoardCoords(1, 1))\ .add_my_move(SubBoardCoords(2, 2)) assert i_win.is_finished == True assert i_win.winner == Player.ME #RTL Diag check i_win = SubBoard().add_my_move(SubBoardCoords(0, 2))\ .add_my_move(SubBoardCoords(1, 1))\ .add_my_move(SubBoardCoords(2, 0)) assert i_win.is_finished == True assert i_win.winner == Player.ME #Row check opponent_wins = SubBoard().add_opponent_move(SubBoardCoords(1, 0))\ .add_opponent_move(SubBoardCoords(1, 1))\ .add_opponent_move(SubBoardCoords(1, 2)) assert opponent_wins.is_finished == True assert opponent_wins.winner == Player.OPPONENT #Col check opponent_wins = SubBoard().add_opponent_move(SubBoardCoords(0, 1))\ .add_opponent_move(SubBoardCoords(1, 1))\ .add_opponent_move(SubBoardCoords(2, 1)) assert opponent_wins.is_finished == True assert opponent_wins.winner == Player.OPPONENT
def test_whenBoardIsInProgressThenBoardIsNotFinished(): assert SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_my_move(SubBoardCoords(0, 1))\ .add_opponent_move(SubBoardCoords(0, 2))\ .is_finished == False
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)
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))
def test_whenNewMoveIsOutsideValidSubBoardBoundsThenExceptionRaised(): with pytest.raises(MoveOutsideSubBoardError): MainBoard().add_my_move(MainBoardCoords(1, 1), SubBoardCoords(1, 3))
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))
def test_whenBoardIsPlayedThenStringRepresentationIsCorrect(): board = SubBoard().add_my_move(SubBoardCoords(0, 0))\ .add_opponent_move(SubBoardCoords(1, 1))\ .add_my_move(SubBoardCoords(2, 2)) assert str(board) == "1 0 0 \n0 2 0 \n0 0 1 \n"
def force_sub_board_win(main_board, board_row, board_col, player): return main_board.copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(0, 0), player) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(1, 1), player) \ .copy_applying_move(MainBoardCoords(board_row, board_col), SubBoardCoords(2, 2), player)
def test_whenNewMoveIsOutsideBoardBoundsThenExceptionRaised(): with pytest.raises(MoveOutsideSubBoardError): SubBoard().add_my_move(SubBoardCoords(1, 3)) with pytest.raises(MoveOutsideSubBoardError): SubBoard().add_opponent_move(SubBoardCoords(-1, 1))
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))
def getSub_state(self, board): counter = 0 empty_counter = 0 winning_col = 0 diagonal_counter = 0 diagonal_counter_empty = 0 for row in range(3): for column in range(3): cell = self.main_board.get_sub_board(board).get_cell( SubBoardCoords(row, column)) if cell == 2: counter += 1 elif cell == 0: emtpy_counter += 1 if counter == 2 and empty_counter == 1: counter = 0 empty_counter = 0 return 1 else: counter = 0 empty_counter = 0 continue for column in range(3): for row in range(3): cell = self.main_board.get_sub_board(board).get_cell( SubBoardCoords(row, column)) if cell == 2: counter += 1 elif cell == 0: empty_counter == 0 if counter == 2 and empty_counter == 1: counter = 0 empty_counter = 1 return 1 else: counter = 0 empty_counter = 0 continue for row in range(3): column = row cell = self.main_board.get_sub_board(board).get_cell( SubBoardCoords(row, column)) if cell == 2: counter += 1 elif cell == 0: empty_counter == 0 if diagonal_counter == 2 and diagonal_counter_empty == 1: diagonal_counter_empty = 0 diagonal_counter = 0 return 1 else: diagonal_counter = 0 diagonal_counter_empty = 0 continue for row in range(2, -1, -1): for column in range(3): cell = self.main_board.get_sub_board(board).get_cell( SubBoardCoords(row, column)) if cell == 2: counter += 1 elif cell == 0: empty_counter += 1 if counter == 2 and empty_counter == 1: counter = 0 empty_counter = 0 return 1 else: counter = 0 empty_counter = 0 continue return 0
def test_whenNewMoveIsInValidCellThenReturnedBoardHasMove(): assert SubBoard().add_my_move(SubBoardCoords(0, 0))\ ._board[0][0].played_by == Player.ME assert SubBoard().add_opponent_move(SubBoardCoords(0, 0))\ ._board[0][0].played_by == Player.OPPONENT