예제 #1
0
def test_validate_initial_move_allowed() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(2, 0), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_ok()
    assert bs == BoardState()  # board state is unchanged

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(0, 2), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_ok()
    assert bs == BoardState()  # board state is unchanged

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(2), index_to_tile(3), index_to_tile(4)],
        InitialMove(BoardPosition(9, 2), index_to_tile(2), Port.BottomLeft, "white"),
    )
    assert r.is_ok()
    assert bs == BoardState()  # board state is unchanged
예제 #2
0
def test_validate_place_tile_unnecessary_loop() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightBottom))
    )
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 1))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(3, 1))
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(5), "red"))
    assert r.is_ok()
    assert r.value()
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(5).rotate(), "red"))
    assert r.is_ok()
    assert not r.value()

    r2 = rc.validate_move(
        bs,
        [index_to_tile(5), index_to_tile(4)],
        IntermediateMove(index_to_tile(4), "red"),
    )
    assert r2.is_error()
    assert (
        r2.error()
        == "player chose a loopy move when this does not create a loop: Tile(idx=5, edges=[(0, 7), (1, 5), (2, 6), (3, 4)])"
    )
예제 #3
0
def test_generate_first_move_0_5() -> None:
    # The first move is placing a tile at 0,5 since there are tiles blocking the other positions
    second_s = SecondS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(1, 0))
    bs = bs.with_tile(index_to_tile(1), BoardPosition(3, 0))
    bs = bs.with_tile(index_to_tile(2), BoardPosition(5, 0))
    bs = bs.with_tile(index_to_tile(3), BoardPosition(7, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(9, 0))
    bs = bs.with_tile(index_to_tile(5), BoardPosition(9, 2))
    bs = bs.with_tile(index_to_tile(6), BoardPosition(9, 4))
    bs = bs.with_tile(index_to_tile(7), BoardPosition(9, 6))
    bs = bs.with_tile(index_to_tile(8), BoardPosition(9, 8))
    bs = bs.with_tile(index_to_tile(9), BoardPosition(8, 9))
    bs = bs.with_tile(index_to_tile(10), BoardPosition(6, 9))
    bs = bs.with_tile(index_to_tile(11), BoardPosition(4, 9))
    bs = bs.with_tile(index_to_tile(12), BoardPosition(2, 9))
    bs = bs.with_tile(index_to_tile(13), BoardPosition(0, 9))
    bs = bs.with_tile(index_to_tile(14), BoardPosition(0, 7))

    r = second_s.generate_first_move(
        [index_to_tile(22),
         index_to_tile(23),
         index_to_tile(4)], bs)
    assert r.assert_value() == (BoardPosition(x=0, y=5), index_to_tile(4),
                                Port.TopLeft)
예제 #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 test_is_move_suicidal_walk_off_edge() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightTop))
    )
    bs = bs.with_tile(index_to_tile(2), BoardPosition(2, 0))
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
예제 #6
0
def test_is_move_suicidal_loop() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightBottom))
    )
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 1))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(3, 1))
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
예제 #7
0
def test_generate_first_move_2_9() -> None:
    # The first move is placing a tile at 9,2 since there are tiles blocking the other positions
    third_s = ThirdS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(0, 1))
    bs = bs.with_tile(index_to_tile(0), BoardPosition(0, 3))
    bs = bs.with_tile(index_to_tile(1), BoardPosition(0, 5))
    bs = bs.with_tile(index_to_tile(3), BoardPosition(0, 7))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(0, 9))

    r = third_s.generate_first_move(
        [index_to_tile(22), index_to_tile(23), index_to_tile(4)], bs
    )
    assert r.assert_value() == (BoardPosition(x=2, y=9), index_to_tile(4), Port.TopLeft)
예제 #8
0
def test_validate_initial_move_not_in_choices() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(3), index_to_tile(4)],
        InitialMove(BoardPosition(0, 2), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "tile Tile(idx=2, edges=[(0, 5), (1, 4), (2, 7), (3, 6)]) is not in the list of tiles [Tile(idx=1, edges=[(0, 4), (1, 5), (2, 6), (3, 7)]), Tile(idx=3, edges=[(0, 4), (1, 3), (2, 6), (5, 7)]), Tile(idx=4, edges=[(0, 7), (1, 2), (3, 4), (5, 6)])] the player was given"
    )
    assert bs == BoardState()  # board state is unchanged
예제 #9
0
def test_validate_initial_move_on_top_of() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(5), BoardPosition(0, 2))
    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(0, 2), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "cannot place tile at position BoardPosition(x=0, y=2) since there is already a tile at that position"
    )
예제 #10
0
def test_is_move_suicidal_inexistent() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(22), "red"))
    assert r.is_error()
    assert r.error() == "player red is not alive thus the move cannot be suicidal"
예제 #11
0
def test_validate_initial_move_facing_edge() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(0, 3), index_to_tile(2), Port.LeftTop, "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "cannot make an initial move at position BoardPosition(x=0, y=3), port 7 since it does not face the interior of the board"
    )

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(3, 0), index_to_tile(2), Port.TopRight, "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "cannot make an initial move at position BoardPosition(x=3, y=0), port 1 since it does not face the interior of the board"
    )
예제 #12
0
def test_generate_first_move_9_2() -> None:
    # The first move is placing a tile at 9,2 since there are tiles blocking the other positions
    second_s = SecondS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(1, 0))
    bs = bs.with_tile(index_to_tile(1), BoardPosition(3, 0))
    bs = bs.with_tile(index_to_tile(2), BoardPosition(5, 0))
    bs = bs.with_tile(index_to_tile(3), BoardPosition(7, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(9, 0))

    r = second_s.generate_first_move(
        [index_to_tile(22),
         index_to_tile(23),
         index_to_tile(4)], bs)
    assert r.assert_value() == (BoardPosition(x=9, y=2), index_to_tile(4),
                                Port.TopLeft)
예제 #13
0
def test_validate_place_tile_not_in_choices() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.TopRight))
    )
    r = rc.validate_move(
        bs,
        [index_to_tile(2), index_to_tile(3)],
        IntermediateMove(index_to_tile(1), "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "tile Tile(idx=1, edges=[(0, 4), (1, 5), (2, 6), (3, 7)]) is not in the list of tiles [Tile(idx=2, edges=[(0, 5), (1, 4), (2, 7), (3, 6)]), Tile(idx=3, edges=[(0, 4), (1, 3), (2, 6), (5, 7)])] the player was given"
    )
예제 #14
0
def test_validate_place_tile_required_suicide() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightTop))
    )
    bs = bs.with_tile(index_to_tile(2), BoardPosition(2, 0))
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
    r2 = rc.validate_move(
        bs,
        [index_to_tile(4), index_to_tile(4)],
        IntermediateMove(index_to_tile(4).rotate(), "red"),
    )
    assert r2.is_ok()
예제 #15
0
def test_validate_initial_move_double_play() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(5, 0), Port.RightBottom))
    )
    copied = deepcopy(bs)
    r = rc.validate_initial_move(
        copied,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(0, 2), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_error()
    assert (
        r.error() == "cannot place player red since the player is already on the board"
    )
    assert bs == copied  # board state is unchanged
예제 #16
0
def test_generate_first_move_5_0() -> None:
    # The first move is placing a tile at 5,0 since there are tiles blocking the other positions
    second_s = SecondS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(1, 0))
    bs = bs.with_tile(index_to_tile(0), BoardPosition(1, 0))
    bs = bs.with_tile(index_to_tile(1), BoardPosition(3, 0))

    r = second_s.generate_first_move(
        [index_to_tile(22),
         index_to_tile(23),
         index_to_tile(3)], bs)
    assert r.assert_value() == (
        BoardPosition(x=5, y=0),
        index_to_tile(3),
        Port.RightTop,
    )
예제 #17
0
def test_player_failed_strategy() -> None:
    bs = BoardState()
    p = Player(Strategy())

    r = p.generate_move([], bs)
    assert r.error() == "Strategy does not implement method generate_move!"

    r2 = p.generate_first_move([], bs)
    assert r2.error(
    ) == "Strategy does not implement method generate_first_move!"
예제 #18
0
def test_both_moves_illegal() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 1))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(3, 1))
    bs = bs.with_tile(index_to_tile(24), BoardPosition(2, 0))
    bs = bs.with_tile(index_to_tile(22), BoardPosition(4, 0))
    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightBottom)).set(
            "white", (BoardPosition(4, 0), Port.LeftBottom)
        )
    )
    move = IntermediateMove(index_to_tile(24), "white")
    r = rc.validate_move(bs, [index_to_tile(24), index_to_tile(24)], move)
    assert r.is_error()
    assert (
        r.error()
        == "player chose a loopy move when this does not create a loop: Tile(idx=24, edges=[(0, 7), (1, 2), (3, 6), (4, 5)])"
    )
예제 #19
0
def test_validate_place_tile_inexistent_player() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.validate_move(
        bs,
        [index_to_tile(1), index_to_tile(2)],
        IntermediateMove(index_to_tile(1), "red"),
    )
    assert r.is_error()
    assert r.error() == "cannot place a tile for player red since they are not alive"
예제 #20
0
    def generate_move(self, tiles: List[Tile], board_state: BoardState) -> Result[Tile]:
        """
        Send the board state and tile options to the client player via TCP, and receives the action
        taken by the player.

        :param tiles:           The set of tile options for the first move
        :param board_state:     The state of the current board
        :return:                A result containing the tile that will be placed for the given player
        """        
        state_pats = board_state.to_state_pats()
        message = ["take-turn", [state_pats, tile_to_index(tiles[0]), tile_to_index(tiles[1])]]
        return self._handle_communication(message, self._handle_intermediate_received)
예제 #21
0
def test_incorrect_number_tiles_given() -> None:
    second_s = SecondS()
    bs = BoardState()

    r = second_s.generate_move(
        [index_to_tile(1),
         index_to_tile(2),
         index_to_tile(3)], bs)
    assert r.is_error()
    assert r.error() == "Strategy.generate_move given 3 (expected 2)"
    r2 = second_s.generate_first_move([index_to_tile(1), index_to_tile(2)], bs)
    assert r2.is_error()
    assert r2.error() == "Strategy.generate_first_move given 2 (expected 3)"
예제 #22
0
def test_generate_first_move_0_1() -> None:
    # The first move is just placing a tile at 0,1
    third_s = ThirdS()
    bs = BoardState()

    r = third_s.generate_first_move(
        [index_to_tile(22), index_to_tile(23), index_to_tile(24)], bs
    )
    assert r.assert_value() == (
        BoardPosition(x=0, y=1),
        index_to_tile(24),
        Port.TopLeft,
    )
예제 #23
0
def test_validate_place_tile_forced_loop_or_suicide() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightBottom))
    )
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 1))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(3, 1))
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(7), "red"))
    assert r.is_ok()
    assert r.value()

    r2 = rc.validate_move(
        bs,
        [index_to_tile(7), index_to_tile(4)],
        IntermediateMove(index_to_tile(4), "red"),
    )
    assert r2.is_error()
    assert (
        r2.error()
        == "player chose a loopy move when this does not create a loop: Tile(idx=7, edges=[(0, 3), (1, 6), (2, 5), (4, 7)])"
    )

    r3 = rc.validate_move(
        bs,
        [index_to_tile(7), index_to_tile(4)],
        IntermediateMove(index_to_tile(7), "red"),
    )
    assert r3.is_error()
    assert (
        r3.error()
        == "player chose a suicidal move when this does not cause a suicide: Tile(idx=4, edges=[(0, 7), (1, 2), (3, 4), (5, 6)])"
    )
예제 #24
0
def test_validate_place_tile_loop_someone_else() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightBottom))
    )
    bs = bs.with_live_players(
        bs.live_players.set("white", (BoardPosition(4, 0), Port.LeftTop))
    )
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 0))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(2, 1))
    bs = bs.with_tile(index_to_tile(4), BoardPosition(3, 1))
    bs = bs.with_tile(index_to_tile(2), BoardPosition(4, 0))

    # The move is suicidal for red but not for white
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(13).rotate(), "white"))
    assert r.is_ok()
    assert not r.value()
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(13).rotate(), "red"))
    assert r.is_ok()
    assert r.value()
    # But it does create a loop no matter who places it
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(13).rotate(), "white"))
    assert r.is_ok()
    assert r.value()
    r = rc.move_creates_loop(bs, IntermediateMove(index_to_tile(13).rotate(), "red"))
    assert r.is_ok()
    assert r.value()
    # And thus it is illegal
    r = rc.is_move_illegal(bs, IntermediateMove(index_to_tile(13).rotate(), "white"))
    assert r.is_ok()
    assert r.value()
    r = rc.is_move_illegal(bs, IntermediateMove(index_to_tile(13).rotate(), "red"))
    assert r.is_ok()
    assert r.value()

    # Red and white are both not allowed to place the move since it causes a loop
    r2 = rc.validate_move(
        bs,
        [index_to_tile(13).rotate().rotate(), index_to_tile(6)],
        IntermediateMove(index_to_tile(13).rotate(), "white"),
    )
    assert r2.is_error()
    assert (
        r2.error()
        == "player chose a loopy move when this does not create a loop: Tile(idx=13, edges=[(0, 7), (1, 2), (3, 5), (4, 6)])"
    )
    r2 = rc.validate_move(
        bs,
        [index_to_tile(13).rotate().rotate(), index_to_tile(6)],
        IntermediateMove(index_to_tile(13).rotate(), "red"),
    )
    assert r2.is_error()
    assert (
        r2.error()
        == "player chose a loopy move when this does not create a loop: Tile(idx=13, edges=[(0, 7), (1, 2), (3, 5), (4, 6)])"
    )
예제 #25
0
def test_validate_initial_move_middle() -> None:
    rc = RuleChecker()
    bs = BoardState()

    r = rc.validate_initial_move(
        bs,
        [index_to_tile(1), index_to_tile(2), index_to_tile(3)],
        InitialMove(BoardPosition(2, 3), index_to_tile(2), Port.BottomLeft, "red"),
    )
    assert r.is_error()
    assert (
        r.error()
        == "cannot make an initial move at position BoardPosition(x=2, y=3) since it is not on the edge"
    )
예제 #26
0
def test_generate_first_move_1_0() -> None:
    # The first move is just placing a tile at 0,1
    second_s = SecondS()
    bs = BoardState()

    r = second_s.generate_first_move(
        [index_to_tile(22),
         index_to_tile(23),
         index_to_tile(24)], bs)
    assert r.assert_value() == (
        BoardPosition(x=1, y=0),
        index_to_tile(24),
        Port.RightTop,
    )
예제 #27
0
    def generate_first_move(
        self, tiles: List[Tile], board_state: BoardState
    ) -> Result[Tuple[BoardPosition, Tile, PortID]]:
        """
        Send the board state and tile options to the client player via TCP, and receives the initial action
        taken by the player.

        :param tiles:           The set of tile options for the first move
        :param board_state:     The state of the current board
        :return:                A result containing a tuple containing the board position, tile, and port ID
                                for the player's initial move
        """
        state_pats = board_state.to_state_pats()
        message = ["initial", [state_pats, tile_to_index(tiles[0]), tile_to_index(tiles[1]), tile_to_index(tiles[2])]]
        return self._handle_communication(message, self._handle_initial_received)
예제 #28
0
def test_validate_place_tile_unnecessary_suicide() -> None:
    rc = RuleChecker()
    bs = BoardState()

    bs = bs.with_live_players(
        bs.live_players.set("red", (BoardPosition(2, 0), Port.RightTop))
    )
    bs = bs.with_tile(index_to_tile(2), BoardPosition(2, 0))
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(4), "red"))
    assert r.is_ok()
    assert r.value()
    r = rc.is_move_suicidal(bs, IntermediateMove(index_to_tile(3), "red"))
    assert r.is_ok()
    assert not r.value()
    r2 = rc.validate_move(
        bs,
        [index_to_tile(3), index_to_tile(4)],
        IntermediateMove(index_to_tile(4), "red"),
    )
    assert r2.is_error()
    assert (
        r2.error()
        == "player chose a suicidal move when this does not cause a suicide: Tile(idx=3, edges=[(0, 4), (1, 3), (2, 6), (5, 7)])"
    )
예제 #29
0
def test_create_board_from_initial_placements() -> None:
    assert (Board.create_board_from_initial_placements(
        []).assert_value().get_board_state() == BoardState())

    board_r = Board.create_board_from_initial_placements([
        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"),
    ])
    assert board_r.is_ok()
    board_state = board_r.value().get_board_state()
    for x in range(MIN_BOARD_COORDINATE, MAX_BOARD_COORDINATE + 1):
        for y in range(MIN_BOARD_COORDINATE, MAX_BOARD_COORDINATE + 1):
            tile = board_state.get_tile(BoardPosition(x, y))
            if (x, y) == (5, 0):
                assert tile == index_to_tile(2)
            elif (x, y) == (9, 2):
                assert tile == index_to_tile(3)
            elif (x, y) == (9, 4):
                assert tile == index_to_tile(4)
            else:
                assert tile is None
    assert board_r.value().live_players == pmap({
        "blue": (BoardPosition(x=5, y=0), 4),
        "green": (BoardPosition(x=9, y=4), 0),
        "white": (BoardPosition(x=9, y=2), 0),
    })

    board_r = Board.create_board_from_initial_placements([
        InitialMove(BoardPosition(5, 0),
                    make_tiles()[2], Port.BottomRight, "blue"),
        InitialMove(BoardPosition(9, 2),
                    make_tiles()[2], Port.TopLeft, "white"),
        InitialMove(BoardPosition(9, 4),
                    make_tiles()[2], Port.TopLeft, "green"),
        # And an invalid one
        InitialMove(BoardPosition(9, 7),
                    make_tiles()[2], Port.TopLeft, "green"),
    ])
    assert board_r.is_error()
    assert (
        board_r.error() ==
        "failed to create board from set of initial placements: cannot place player green since the player is already on the board"
    )
예제 #30
0
def test_player_calls_observers() -> None:
    bs = BoardState()

    lo = LoggingPlayerObserver()
    p = Player(FirstS())
    p.add_observer(lo)

    p.set_color("red")
    assert lo.set_colors == ["red"]
    p.set_color("green")
    assert lo.set_colors == ["red", "green"]

    assert p.generate_first_move(
        [index_to_tile(3),
         index_to_tile(4),
         index_to_tile(5)], bs).is_ok()
    assert lo.initial_move_offereds == [
        ([index_to_tile(3),
          index_to_tile(4),
          index_to_tile(5)], bs)
    ]
    assert lo.initial_move_playeds == [(
        [index_to_tile(3),
         index_to_tile(4),
         index_to_tile(5)],
        bs,
        InitialMove(BoardPosition(1, 0), index_to_tile(5), Port.RightTop,
                    "green"),
    )]

    assert p.generate_move([index_to_tile(10), index_to_tile(11)], bs).is_ok()
    assert lo.intermediate_move_offereds == [
        ([index_to_tile(10), index_to_tile(11)], bs)
    ]
    assert lo.intermediate_move_playeds == [(
        [index_to_tile(10), index_to_tile(11)],
        bs,
        IntermediateMove(index_to_tile(10), "green"),
    )]

    gr = ([{"red"}, {"black", "green"}], {"white"})
    p.game_result(gr)  # type: ignore
    assert lo.game_results == [gr]