def test_generate_move_no_valid_moves() -> None: # No possible moves, chooses first option without rotation second_s = SecondS() second_s.set_color(AllColors[0]) second_s.set_rule_checker(RuleChecker()) b = Board() assert b.initial_move( InitialMove(BoardPosition(1, 0), index_to_tile(34), Port.BottomRight, second_s.color)).is_ok() tiles = [ Tile( cast( List[Tuple[PortID, PortID]], [ tuple(Port.all()[i:i + 2]) for i in range(0, len(Port.all()), 2) ], )), Tile( cast( List[Tuple[PortID, PortID]], [ tuple(Port.all()[i:i + 2]) for i in range(0, len(Port.all()), 2) ], )), ] r = second_s.generate_move(tiles, b.get_board_state()) assert id(r.assert_value()) == id(tiles[0])
def test_board_to_html() -> None: # Just test that it returns a string and rely on manual testing to verify that it # looks roughly correct b = Board() assert isinstance(b.get_board_state().to_html(), str) board_r = Board.create_board_from_moves( [ InitialMove(BoardPosition(5, 0), index_to_tile(2), Port.BottomRight, "blue"), InitialMove(BoardPosition(9, 2), index_to_tile(3), Port.TopLeft, "white"), InitialMove(BoardPosition(9, 4), index_to_tile(4), Port.TopLeft, "green"), ], [ IntermediateMove(index_to_tile(5), "blue"), IntermediateMove(index_to_tile(6), "white"), ], ) assert board_r.is_ok() b2 = board_r.value().get_board_state() assert isinstance(b2.to_html(), str) assert b2.to_html() != b.get_board_state().to_html() assert b2.to_html(automatic_refresh=True) != b2.to_html( automatic_refresh=False)
def _run_game_initial_turns(self, board: Board) -> Result[None]: """ Run the first step of a Tsuro game: prompting every player for their initial move. Apply the changes to this board to the fields contained within this referee. :param board: The board to run the game on :return: A result containing either None or an error """ r_components = self._confirm_all_components() if r_components.is_error(): return r_components for color, player in self._players.items(): tiles = self._get_tiles(3) for observer in self._observers: observer.initial_move_offered(color, tiles, board.get_board_state()) r_initial_move = self._get_check_initial_move( board, color, player, tiles) if r_initial_move.is_error(): continue r = board.initial_move(r_initial_move.value()) if r.is_error(): return error(r.error()) self._remove_cheaters(board) return ok(None)
def test_place_tile_remove_other_player() -> None: # Black kills red by driving them off the edge of the board rc = RuleChecker() bs = BoardState() bs = bs.with_live_players( bs.live_players.set("red", (BoardPosition(2, 2), Port.RightBottom)) ) bs = bs.with_live_players( bs.live_players.set("black", (BoardPosition(4, 2), Port.LeftTop)) ) bs = bs.with_tile(index_to_tile(2), BoardPosition(2, 0)) bs = bs.with_tile(index_to_tile(2), BoardPosition(2, 1)) bs = bs.with_tile(index_to_tile(3), BoardPosition(2, 2)) bs = bs.with_tile(index_to_tile(2), BoardPosition(4, 0)) bs = bs.with_tile(index_to_tile(2), BoardPosition(4, 1)) bs = bs.with_tile(index_to_tile(32).rotate(), BoardPosition(4, 2)) r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(2), "red")) assert r.is_ok() assert r.value() move = IntermediateMove(index_to_tile(2), "black") r = rc.is_move_suicidal(bs, move) assert r.is_ok() assert not r.value() assert rc.validate_move(bs, [index_to_tile(2), index_to_tile(3)], move).is_ok() board = Board(bs) assert board.intermediate_move(move).is_ok() assert "red" not in board.live_players assert board.live_players["black"] == (BoardPosition(x=2, y=2), 6) bs = bs.with_tile(index_to_tile(2), BoardPosition(4, 2))
def intermediate_move_played(self, player: ColorString, tiles: List[Tile], board_state: BoardState, move: IntermediateMove, validMove: bool) -> None: """ An observer method that is called to describe when a player returns an intermediate move to be placed. :param player: The player who is being asked for a move :param tiles: The list of tiles that the player is allowed to choose between :param board_state: The board state that the player is playing against :param move: The intermediate move that the player placed on the board """ self._current_player_color = player board = Board(deepcopy(board_state)) r = board.intermediate_move(move) if r.is_ok() and validMove: self._most_recent_board_state = board.get_board_state() self._render_update(tiles, move.tile) elif r.is_ok(): self._render_update(tiles, move.tile) else: logging.warning( "GameObserver.intermediate_move_played failed to render updated board after " "an intermediate move because the given intermediate move is invalid. Ignoring..." )
def _get_check_intermediate_move( self, color: ColorString, board: Board, tiles: List[Tile], player: PlayerInterface) -> Result[IntermediateMove]: """ Gets the intermediate move from the player and checks whether it is valid based on the rulechecker. If any errors, the player is added as a cheater. Returns an error if cheating, or the chosen move if it is valid """ r_move = self._handle_player_timeout( color, lambda: player.generate_move(deepcopy(tiles), board.get_board_state())) if r_move.is_error(): self._cheaters.add(color) return error(r_move.error()) intermediate_move = IntermediateMove(r_move.value(), color) r_rule = self._rule_checker.validate_move(board.get_board_state(), tiles, intermediate_move) for observer in self._observers: observer.intermediate_move_played(color, tiles, board.get_board_state(), intermediate_move, r_rule.is_ok()) if r_rule.is_error(): self._cheaters.add(color) return error(r_rule.error()) return ok(intermediate_move)
def validate_move(self, board_state: BoardState, tile_choices: List[Tile], move: IntermediateMove) -> Result[None]: """ Validate the given intermediate move when the player was given the choice of tile_choices. :param board_state: The board state the move is being applied to :param tile_choices: The list of tiles the player was allowed to choose from :param move: The intermediate move to validate :return: A result containing either None (if the move is valid) or an error if the move is invalid. If the move is invalid, the error contains a description of why it is invalid. """ conditions_r = self.check_valid_move_params( tile_choices, move.tile, EXPECTED_TILE_COUNT_INTERMEDIATE_MOVE) if conditions_r.is_error(): return conditions_r board = Board(deepcopy(board_state)) r = board.validate_intermediate_move(move) if r.is_error(): return r loop_r = self.is_legal_for_condition(self.move_creates_loop, board_state, tile_choices, move, LOOP_ERROR) if loop_r.is_error(): return loop_r suicide_r = self.is_legal_for_condition(self.is_move_suicidal, board_state, tile_choices, move, SUICIDE_ERROR) if suicide_r.is_error(): return suicide_r return ok(None)
class TestFirstMoveCheckNeighbors(TestCase): def setUp(self): self.board = Board() self.board.add_tile(get_tile(0), x=5, y=5, rotation=0) self.player = Player() self.rule = FirstMoveCheckNeighbors() def test_valid(self): placement = dummy_placement(x=1, y=1) is_valid, _ = self.rule.is_valid(placement, self.board, self.player) self.assertTrue(is_valid) def test_invalid(self): invalid_coordinates = ( (5, 4), # north (5, 6), # south (4, 5), # east (6, 5), # west ) for x, y in invalid_coordinates: with self.subTest(x=x, y=y): placement = dummy_placement(x=x, y=y) is_valid, msg = self.rule.is_valid(placement, self.board, self.player) self.assertFalse(is_valid) self.assertEqual(msg, FirstMoveCheckNeighbors.ERROR_MSG)
def test_is_valid_initial_position() -> None: b = Board() assert b.place_tile_at_index_with_scissors( index_to_tile(2), BoardPosition(0, 5) ).is_ok() assert ( PhysicalConstraintChecker.is_valid_initial_port( b._board_state, BoardPosition(0, 5), Port.TopRight ).error() == "cannot place tile at position BoardPosition(x=0, y=5) since there is already a tile at that position" ) assert ( PhysicalConstraintChecker.is_valid_initial_port( b._board_state, BoardPosition(3, 5), Port.TopRight ).error() == "cannot make an initial move at position BoardPosition(x=3, y=5) since it is not on the edge" ) assert ( PhysicalConstraintChecker.is_valid_initial_port( b._board_state, BoardPosition(0, 6), Port.TopRight ).error() == "cannot make an initial move at position BoardPosition(x=0, y=6) since the surrounding tiles are not all empty" ) assert ( PhysicalConstraintChecker.is_valid_initial_port( b._board_state, BoardPosition(0, 4), Port.TopRight ).error() == "cannot make an initial move at position BoardPosition(x=0, y=4) since the surrounding tiles are not all empty" )
def test_run() -> None: """ Test function to run the graphical player observer locally with some test data. Meant to be run locally and inspected in order to ensure the GUI is working properly. :return: None """ gpo = GraphicalPlayerObserver() gpo.set_color("red") gpo.set_players(["red", "blue", "green", "black", "white"]) b = Board() for move in TEST_RUN_MOVES: if isinstance(move, InitialMove): tile_choices = [move.tile, rand_tile(), rand_tile()] if move.player == "red": gpo.initial_move_offered(tile_choices, b.get_board_state()) time.sleep(0.5) if move.player == "red": gpo.initial_move_played(tile_choices, b.get_board_state(), move) b.initial_move(move).assert_value() elif isinstance(move, IntermediateMove): tile_choices = [move.tile, rand_tile()] if move.player == "red": gpo.intermediate_move_offered(tile_choices, b.get_board_state()) time.sleep(0.5) if move.player == "red": gpo.intermediate_move_played(tile_choices, b.get_board_state(), move) b.intermediate_move(move).assert_value() time.sleep(0.5)
def test_board_move_player_along_path_error() -> None: b = Board() r = b._move_player_along_path("red") assert r.is_error() assert ( r.error() == "failed to move player red along path: player red is not on the board")
def test_board_place_tile_at_index_with_scissors() -> None: b = Board() assert b.place_tile_at_index_with_scissors(index_to_tile(5), BoardPosition(3, 0)).is_ok() assert b.get_board_state().get_tile(BoardPosition(3, 0)) == index_to_tile(5) r = b.place_tile_at_index_with_scissors(index_to_tile(5), BoardPosition(3, 0)) assert r.is_ok()
def try_display_board(board: Board) -> None: """ :param board: :return: """ try: if DEBUG: board.get_board_state().debug_display_board() except Exception: # pylint: disable=broad-except pass
def test_add_tile(self, mock): board = Board() tile = Tile() board.add_tile(Tile(), 0, 0) self.assertEqual(board.grid[0][0], tile) mock.assert_has_calls([ call(OutOfBounds, Direction.NORTH), call(None, Direction.SOUTH), call(None, Direction.EAST), call(OutOfBounds, Direction.WEST), ])
def test_board_intermediate_move_loop_moves_no_one_else() -> None: # If player A places a tile that sends them into a loop and player B is next to the would be placed tile, # player B does not move b = Board() logging_observer = LoggingObserver() b.add_observer(logging_observer) # An initial move for green r = b.initial_move( InitialMove(BoardPosition(0, 1), index_to_tile(4), Port.RightBottom, "green")) assert r.is_ok() assert b._board_state.get_tile(BoardPosition(0, 1)) == index_to_tile(4) assert b.live_players["green"] == (BoardPosition(0, 1), Port.RightBottom) # More moves for green to setup what we need to make a loop r = b.intermediate_move(IntermediateMove(index_to_tile(4), "green")) assert r.is_ok() assert b._board_state.get_tile(BoardPosition(1, 1)) == index_to_tile(4) assert b._board_state.live_players["green"] == ( BoardPosition(1, 1), Port.BottomLeft, ) r = b.intermediate_move(IntermediateMove(index_to_tile(4), "green")) assert r.is_ok() assert b._board_state.get_tile(BoardPosition(1, 2)) == index_to_tile(4) assert b._board_state.live_players["green"] == (BoardPosition(1, 2), Port.LeftTop) # And set up white next to the where the would-be loop would be created assert b.place_tile_at_index_with_scissors(index_to_tile(4), BoardPosition(0, 3)).is_ok() b._board_state = b._board_state.with_live_players( b._board_state.live_players.set("white", (BoardPosition(0, 3), Port.TopRight))) # This tile placement will make a loop. Test that it is detected, the player is removed, and a message is broadcast # to all of the defined observers. According to assignment 6 the player should be removed but the tile # should not be on the board. assert logging_observer.all_messages() == [] r = b.intermediate_move(IntermediateMove(index_to_tile(4), "green")) assert r.is_ok() assert "green" not in b.live_players assert b._board_state.get_tile(BoardPosition(0, 2)) is None assert logging_observer.all_messages() == [ "entered_loop: green", "exited_board: green", ] # And white is still in the same place assert b._board_state.live_players["white"] == (BoardPosition(0, 3), Port.TopRight)
def setUp(self): self.b = Board() self.tile1 = Tile([[0, 1], [2, 3], [4, 5], [6, 7]]) self.tile2 = Tile([[1, 6], [0, 2], [3, 7], [4, 5]]) # Same orientation with connections in different order self.tile3 = Tile([[4, 5], [6, 1], [2, 0], [7, 3]]) # Same tile rotated 90 degree self.tile4 = Tile([[3, 0], [2, 4], [5, 1], [6, 7]]) # Same tile rotated 180 degree self.tile5 = Tile([[5, 2], [4, 6], [7, 3], [0, 1]]) # Rotated 270 self.tile6 = Tile([[7, 4], [6, 0], [1, 5], [2, 3]])
def _remove_cheaters(self, board: Board) -> None: """ Remove anyone in self.cheaters from the list of players and from the list of currently live players :param board: The board to remove players from """ for player in self._cheaters: if player in self._players: del self._players[player] if player in board.live_players: board.remove_player(player) for observer in self._observers: observer.cheater_removed(player, board.get_board_state())
def test_generate_move_takes_first_tile_no_rotation() -> None: # Test that the first tile is taken when valid second_s = SecondS() second_s.set_color(AllColors[0]) second_s.set_rule_checker(RuleChecker()) b = Board() b.initial_move( InitialMove(BoardPosition(4, 0), index_to_tile(34), Port.BottomRight, second_s.color)) tiles = [index_to_tile(6), index_to_tile(34)] r = second_s.generate_move(tiles, b.get_board_state()) assert r.assert_value().edges == tiles[0].edges
def test_board_surrounding_positions_are_empty() -> None: b = Board() assert b.place_tile_at_index_with_scissors(index_to_tile(1), BoardPosition(3, 2)).is_ok() assert b._board_state.surrounding_positions_are_empty(BoardPosition(3, 2)) assert not b._board_state.surrounding_positions_are_empty( BoardPosition(2, 2)) assert not b._board_state.surrounding_positions_are_empty( BoardPosition(4, 2)) assert not b._board_state.surrounding_positions_are_empty( BoardPosition(3, 1)) assert not b._board_state.surrounding_positions_are_empty( BoardPosition(3, 3))
def test_board_intermediate_move_single_player() -> None: b = Board() logging_observer = LoggingObserver() b.add_observer(logging_observer) # Can't place a tile if they haven't moved r = b.intermediate_move(IntermediateMove(make_tiles()[2], "green")) assert r.is_error() assert r.error( ) == "cannot place a tile for player green since they are not alive" # An initial move for green r = b.initial_move( InitialMove(BoardPosition(9, 4), index_to_tile(0), Port.TopLeft, "green")) assert r.is_ok() assert b._board_state.get_tile(BoardPosition(9, 4)) == index_to_tile(0) assert b._board_state.live_players["green"] == (BoardPosition(9, 4), Port.TopLeft) # Add another tile and they move r = b.intermediate_move(IntermediateMove(index_to_tile(1), "green")) assert r.is_ok() assert b._board_state.live_players["green"] == ( BoardPosition(x=9, y=3), Port.TopRight, ) # And place a tile that will draw them off the edge of the board assert logging_observer.all_messages() == [] r = b.intermediate_move(IntermediateMove(index_to_tile(4), "green")) assert r.is_ok() assert "green" not in b._board_state.live_players assert logging_observer.all_messages() == ["exited_board: green"]
class MyTestCase(unittest.TestCase): def setUp(self): self.b = Board() self.tile1 = Tile([[0, 1], [2, 3], [4, 5], [6, 7]]) self.tile2 = Tile([[1, 6], [0, 2], [3, 7], [4, 5]]) # Same orientation with connections in different order self.tile3 = Tile([[4, 5], [6, 1], [2, 0], [7, 3]]) # Same tile rotated 90 degree self.tile4 = Tile([[3, 0], [2, 4], [5, 1], [6, 7]]) # Same tile rotated 180 degree self.tile5 = Tile([[5, 2], [4, 6], [7, 3], [0, 1]]) # Rotated 270 self.tile6 = Tile([[7, 4], [6, 0], [1, 5], [2, 3]]) def test_initial_tile_add(self): print(self.b.get_tile(0, 1).get_paths()) self.b.add_initial_tile(self.tile1, 0, 1, 6) print(self.b.get_tile(0, 1).get_paths()) def test_initial_tile_add_multiple(self): print(self.b.get_tile(0, 1).get_paths()) print(self.b.get_tile(0, 3).get_paths()) self.b.add_initial_tile(self.tile1, 0, 1, 6) self.b.add_initial_tile(self.tile3, 0, 3, 6) print(self.b.get_tile(0, 1).get_paths()) print(self.b.get_tile(0, 3).get_paths())
def test_generate_move_needs_rotation() -> None: # Test that the first tile is rotated to a valid rotation when the second tile is invalid third_s = ThirdS() third_s.set_color(AllColors[0]) third_s.set_rule_checker(RuleChecker()) b = Board() b.initial_move( InitialMove( BoardPosition(9, 0), index_to_tile(34), Port.BottomRight, third_s.color ) ) tiles = [index_to_tile(11), index_to_tile(34)] r = third_s.generate_move(tiles, b.get_board_state()) assert r.assert_value().edges == tiles[0].rotate().edges
def test_reachable_spaces_north(self): board = Board.make_uniform_board(5, 5, 1) spaces = board.reachable_spaces_north(0, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_north(1, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_north(2, 0) self.assertTrue(spaces == [(0, 0)]) spaces = board.reachable_spaces_north(3, 0) self.assertTrue(spaces == [(1, 0)]) spaces = board.reachable_spaces_north(4, 0) self.assertTrue(spaces == [(2, 0), (0, 0)]) spaces = board.reachable_spaces_north(4, 0, depth=1) self.assertTrue(spaces == [(2, 0)]) spaces = board.reachable_spaces_north(4, 0, depth=2) self.assertTrue(spaces == [(2, 0), (0, 0)]) spaces = board.reachable_spaces_north(4, 0, depth=3) self.assertTrue(spaces == [(2, 0), (0, 0)]) board.remove_tile(2, 0) spaces = board.reachable_spaces_north(4, 0) self.assertTrue(len(spaces) == 0)
def test_reachable_spaces_northeast(self): board = Board.make_uniform_board(5, 5, 1) spaces = board.reachable_spaces_northeast(0, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_northeast(1, 0) self.assertTrue(spaces == [(0, 1)]) spaces = board.reachable_spaces_northeast(2, 0) self.assertTrue(spaces == [(1, 0), (0, 1)]) spaces = board.reachable_spaces_northeast(3, 0) self.assertTrue(spaces == [(2, 1), (1, 1), (0, 2)]) spaces = board.reachable_spaces_northeast(4, 0) self.assertTrue(spaces == [(3, 0), (2, 1), (1, 1), (0, 2)]) spaces = board.reachable_spaces_northeast(4, 0, depth=1) self.assertTrue(spaces == [(3, 0)]) spaces = board.reachable_spaces_northeast(4, 0, depth=2) self.assertTrue(spaces == [(3, 0), (2, 1)]) spaces = board.reachable_spaces_northeast(4, 0, depth=4) self.assertTrue(spaces == [(3, 0), (2, 1), (1, 1), (0, 2)]) spaces = board.reachable_spaces_northeast(4, 0, depth=5) self.assertTrue(spaces == [(3, 0), (2, 1), (1, 1), (0, 2)]) board.remove_tile(1, 1) spaces = board.reachable_spaces_northeast(4, 0) self.assertTrue(spaces == [(3, 0), (2, 1)])
def test_reachable_spaces_southeast(self): board = Board.make_uniform_board(5, 5, 1) spaces = board.reachable_spaces_southeast(0, 0) self.assertTrue(spaces == [(1, 0), (2, 1), (3, 1), (4, 2)]) spaces = board.reachable_spaces_southeast(1, 0) self.assertTrue(spaces == [(2, 1), (3, 1), (4, 2)]) spaces = board.reachable_spaces_southeast(0, 1) self.assertTrue(spaces == [(1, 1), (2, 2), (3, 2), (4, 3)]) spaces = board.reachable_spaces_southeast(0, 2) self.assertTrue(spaces == [(1, 2), (2, 3), (3, 3), (4, 4)]) spaces = board.reachable_spaces_southeast(0, 2, depth=1) self.assertTrue(spaces == [(1, 2)]) spaces = board.reachable_spaces_southeast(0, 2, depth=2) self.assertTrue(spaces == [(1, 2), (2, 3)]) spaces = board.reachable_spaces_southeast(0, 2, depth=4) self.assertTrue(spaces == [(1, 2), (2, 3), (3, 3), (4, 4)]) spaces = board.reachable_spaces_southeast(0, 2, depth=5) self.assertTrue(spaces == [(1, 2), (2, 3), (3, 3), (4, 4)]) board.remove_tile(3, 1) spaces = board.reachable_spaces_southeast(0, 0) self.assertTrue(spaces == [(1, 0), (2, 1)])
def test_reachable_spaces_southwest(self): board = Board.make_uniform_board(5, 5, 1) spaces = board.reachable_spaces_southwest(0, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_southwest(1, 0) self.assertTrue(spaces == [(2, 0)]) spaces = board.reachable_spaces_southwest(0, 1) self.assertTrue(spaces == [(1, 0), (2, 0)]) spaces = board.reachable_spaces_southwest(0, 2) self.assertTrue(spaces == [(1, 1), (2, 1), (3, 0), (4, 0)]) spaces = board.reachable_spaces_southwest(4, 4) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_southwest(0, 2, depth=1) self.assertTrue(spaces == [(1, 1)]) spaces = board.reachable_spaces_southwest(0, 2, depth=2) self.assertTrue(spaces == [(1, 1), (2, 1)]) spaces = board.reachable_spaces_southwest(0, 2, depth=10) self.assertTrue(spaces == [(1, 1), (2, 1), (3, 0), (4, 0)]) board.remove_tile(2, 1) spaces = board.reachable_spaces_southwest(0, 2) self.assertTrue(spaces == [(1, 1)])
def test_reachable_spaces_northwest(self): board = Board.make_uniform_board(5, 5, 1) spaces = board.reachable_spaces_northwest(0, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_northwest(1, 0) self.assertTrue(spaces == [(0, 0)]) spaces = board.reachable_spaces_northwest(2, 0) self.assertTrue(len(spaces) == 0) spaces = board.reachable_spaces_northwest(4, 4) self.assertTrue(spaces == [(3, 3), (2, 3), (1, 2), (0, 2)]) spaces = board.reachable_spaces_northwest(4, 4, depth=1) self.assertTrue(spaces == [(3, 3)]) spaces = board.reachable_spaces_northwest(4, 4, depth=2) self.assertTrue(spaces == [(3, 3), (2, 3)]) spaces = board.reachable_spaces_northwest(4, 4, depth=float("inf")) self.assertTrue(spaces == [(3, 3), (2, 3), (1, 2), (0, 2)]) board.remove_tile(1, 2) spaces = board.reachable_spaces_northwest(4, 4) self.assertTrue(spaces == [(3, 3), (2, 3)])
def run_game(self) -> Result[GameResult]: """ Run an entire game of Tsuro with the players that have been added to this referee. Returns the result of the game. A list of players, a rule checker, and a tile iterator must have already been set on this referee prior to calling run_game. :return: The GameResult at the end of the game, or an error if something goes wrong. """ if not self._players: return error("must add players to this referee") if not self._rule_checker: return error("must add a rule checker to this referee") if not self._tile_iterator: return error("must add a tile iterator to this referee") self._initialize_players() board = Board() # Run the initial turns r = self._run_game_initial_turns(board) if r.is_error(): return error(r.error()) # Run the intermediate turns while True: if len(board.live_players) <= 1: break r = self._run_game_single_round(board) if r.is_error(): return error(r.error()) return self._generate_game_result(board)
def test_remove_tile(self): board = Board.make_uniform_board(5, 4, 3) tiles = board.get_board() self.assertEqual(5, len(tiles)) self.assertEqual(4, len(tiles[0])) for i in range(len(tiles)): for j in range(len(tiles[i])): self.assertTrue(tiles[i][j] == 3) board.remove_tile(0, 0) board.remove_tile(1, 1) tiles = board.get_board() for i in range(len(tiles)): for j in range(len(tiles[i])): if (i, j) == (0, 0) or (i, j) == (1, 1): self.assertTrue(tiles[i][j] == 0) else: self.assertTrue(tiles[i][j] == 3) board.remove_tile(0, 0) tiles = board.get_board() for i in range(len(tiles)): for j in range(len(tiles[i])): if (i, j) == (0, 0) or (i, j) == (1, 1): self.assertTrue(tiles[i][j] == 0) else: self.assertTrue(tiles[i][j] == 3)
def test_board_port_faces_interior() -> None: b = Board() assert not b._board_state.port_faces_interior(BoardPosition(0, 5), Port.LeftTop) assert not b._board_state.port_faces_interior(BoardPosition(0, 5), Port.LeftBottom) assert b._board_state.port_faces_interior(BoardPosition(0, 5), Port.RightTop) assert not b._board_state.port_faces_interior(BoardPosition(5, 0), Port.TopLeft) assert not b._board_state.port_faces_interior(BoardPosition(5, 0), Port.TopRight) assert b._board_state.port_faces_interior(BoardPosition(5, 0), Port.LeftBottom) assert not b._board_state.port_faces_interior(BoardPosition(9, 5), Port.RightTop) assert not b._board_state.port_faces_interior(BoardPosition(9, 5), Port.RightBottom) assert b._board_state.port_faces_interior(BoardPosition(9, 5), Port.LeftTop) assert not b._board_state.port_faces_interior(BoardPosition(5, 9), Port.BottomRight) assert not b._board_state.port_faces_interior(BoardPosition(5, 9), Port.BottomLeft) assert b._board_state.port_faces_interior(BoardPosition(5, 9), Port.RightTop)