Beispiel #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])
Beispiel #2
0
def test_port_all_order() -> None:
    assert Port.all() == [
        Port.TopLeft,
        Port.TopRight,
        Port.RightTop,
        Port.RightBottom,
        Port.BottomRight,
        Port.BottomLeft,
        Port.LeftBottom,
        Port.LeftTop,
    ]

    assert Port.all() == list(sorted(Port.all()))
Beispiel #3
0
 def __post_init__(self) -> None:
     if not isinstance(self.tile, Tile):
         raise ValueError("Created an InitialMove with an invalid tile!")
     if self.player not in AllColors:
         raise ValueError("Created an InitialMove with an invalid player!")
     if not isinstance(self.pos, BoardPosition):
         raise ValueError("Created an InitialMove with an invalid board position!")
     if self.port not in Port.all():
         raise ValueError("Created an InitialMove with an invalid port!")
Beispiel #4
0
    def _move_player_along_path(self, player: ColorString) -> Result[bool]:
        """
        Move the given player along their path until they hit the end of a path or the edge of a board. Returns a
        result containing a boolean that indicates whether or not the player hit the edge of the board.

        If the player's path forms an infinite loop, removes the player from the board.

        :param player:  The color of the player
        :return:        An result containing whether the player hit the edge of the board or an error
        """
        seen_pos_port: Set[Tuple[BoardPosition, PortID]] = set()

        while True:
            r = self._board_state.get_position_of_player(player)
            if r.is_error():
                return error(
                    "failed to move player %s along path: %s" % (player, r.error())
                )
            pos, port = r.value()

            if (pos, port) in seen_pos_port:
                for observer in self._observers:
                    observer.player_entered_loop(player)
                # They entered an infinite loop and must be removed
                return ok(True)
            seen_pos_port.add((pos, port))

            r2 = self._board_state.calculate_adjacent_position_of_player(player)
            if r2.is_error():
                return error(
                    "failed to move player %s along path: %s" % (player, r.error())
                )
            next_pos = r2.value()
            if next_pos is None:
                # They hit the edge of the board so remove them from the list of live players
                return ok(True)

            next_tile = self._board_state.get_tile(next_pos)

            if next_tile is None:
                # They didn't hit the edge of the board so they don't need to be removed
                return ok(False)

            next_port = Port.get_adjoining_port(port)

            next_next_port = next_tile.get_port_connected_to(next_port)

            self._board_state = self._board_state.with_live_players(
                self._board_state.live_players.set(player, (next_pos, next_next_port))
            )
Beispiel #5
0
    def _find_valid_port(self, board_state: BoardState,
                         pos: BoardPosition) -> Result[PortID]:
        """
        Find a valid port on the board state for a move at the given position

        :param board_state:     The board state to apply the move to
        :param pos:             The position for the move
        :return:                A result containing the port or an error if there is no valid port to play on at the
                                given position
        """
        for port in Port.all():
            if PhysicalConstraintChecker.is_valid_initial_port(
                    board_state, pos, port).is_ok():
                return ok(port)
        return error("No valid ports on given tile.")
Beispiel #6
0
    def _find_valid_port(
        self, board_state: BoardState, pos: BoardPosition
    ) -> Result[PortID]:
        """
        Find the first port on the board state for a move at the given position going counter-clockwise

        :param board_state:     The board state to apply the move to
        :param pos:             The position for the move
        :return:                A result containing the port or an error if there is no valid port to play on at the
                                given position
        """
        ports = [Port.TopLeft]
        ports.extend(reversed(Port.all()))
        ports = ports[:8]

        for port in ports:
            if PhysicalConstraintChecker.is_valid_initial_port(
                board_state, pos, port
            ).is_ok():
                return ok(port)
        return error("No valid ports on given tile.")