示例#1
0
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])
示例#2
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)
示例#3
0
    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)
示例#4
0
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))
示例#5
0
    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..."
            )
示例#6
0
    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)
示例#7
0
    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)
示例#8
0
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)
示例#9
0
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"
    )
示例#10
0
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)
示例#11
0
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")
示例#12
0
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()
示例#13
0
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
示例#14
0
 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),
     ])
示例#15
0
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)
示例#16
0
 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]])
示例#17
0
    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())
示例#18
0
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
示例#19
0
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))
示例#20
0
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"]
示例#21
0
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())
示例#22
0
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
示例#23
0
    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)
示例#24
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)])
示例#25
0
    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)])
示例#26
0
    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)])
示例#27
0
    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)])
示例#28
0
    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)
示例#29
0
    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)
示例#30
0
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)