Ejemplo n.º 1
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))
Ejemplo n.º 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)])"
    )
Ejemplo n.º 3
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)])"
    )
Ejemplo n.º 4
0
def test_generate_first_move_no_valid_moves() -> None:
    # No possible first moves
    second_s = SecondS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(2, 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))
    bs = bs.with_tile(index_to_tile(15), BoardPosition(0, 5))
    bs = bs.with_tile(index_to_tile(16), BoardPosition(0, 3))
    bs = bs.with_tile(index_to_tile(17), BoardPosition(0, 1))

    r = second_s.generate_first_move(
        [index_to_tile(22),
         index_to_tile(23),
         index_to_tile(4)], bs)
    assert r.is_error()
    assert r.error() == "Failed to find a valid initial move!"
Ejemplo n.º 5
0
def test_generate_first_move_0_0() -> None:
    # The first move is placing a tile at 0,0 since there are tiles blocking the other positions
    second_s = SecondS()
    bs = BoardState()

    bs = bs.with_tile(index_to_tile(0), BoardPosition(2, 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))
    bs = bs.with_tile(index_to_tile(15), BoardPosition(0, 5))
    bs = bs.with_tile(index_to_tile(16), BoardPosition(0, 3))
    bs = bs.with_tile(index_to_tile(17), BoardPosition(0, 2))

    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=0),
        index_to_tile(4),
        Port.RightTop,
    )
Ejemplo n.º 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()
Ejemplo n.º 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)
Ejemplo n.º 8
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)
Ejemplo n.º 9
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,
    )
Ejemplo n.º 10
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()
Ejemplo n.º 11
0
def test_validate_place_tile_required_loop() -> 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(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.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), "red"),
    )
    assert r2.is_ok()
Ejemplo n.º 12
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)])"
    )
Ejemplo n.º 13
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)])"
    )
Ejemplo n.º 14
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"
    )
Ejemplo n.º 15
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)])"
    )
Ejemplo n.º 16
0
def test_generate_first_move_8_0() -> None:
    # The first move is placing a tile at 8,9 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))
    bs = bs.with_tile(index_to_tile(5), BoardPosition(2, 9))
    bs = bs.with_tile(index_to_tile(6), BoardPosition(4, 9))
    bs = bs.with_tile(index_to_tile(7), BoardPosition(7, 9))
    bs = bs.with_tile(index_to_tile(8), BoardPosition(9, 9))
    bs = bs.with_tile(index_to_tile(6), BoardPosition(9, 6))
    bs = bs.with_tile(index_to_tile(7), BoardPosition(9, 3))
    bs = bs.with_tile(index_to_tile(8), BoardPosition(9, 1))

    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=8, y=0), index_to_tile(4), Port.LeftTop)
Ejemplo n.º 17
0
def test_generate_first_move_4_9() -> None:
    # The first move is placing a tile at 4,9 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))

    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=4, y=9), index_to_tile(4),
                                Port.TopLeft)