Beispiel #1
0
def test_directions():
    r""" Verify the four direction operations """
    l = Location(1, 1)
    assert l.up() == l.relative(row_diff=-1)
    assert l.right() == l.relative(col_diff=1)
    assert l.down() == l.relative(row_diff=1)
    assert l.left() == l.relative(col_diff=-1)
Beispiel #2
0
def test_is_identical():
    r""" Verify the \p piece_has_move method of the \p State class """
    path = STATES_PATH / "state_move_verify.txt"
    state = State.importer(path, STD_BRD)

    orig, new = Location(0, 0), Location(1, 0)
    # Get the state information
    p_state = state.red.get_piece_at_loc(orig)
    m_state = state.red.get_move(p_state, new)
    # Build a move for comparison
    p = copy.deepcopy(state.red.get_piece_at_loc(orig))
    m = Move(p, orig, new)

    assert m_state != m, "Equality fails since different references"
    assert Move.is_identical(m, m_state), "Verify the two moves are identical"
    assert Move.is_identical(m_state, m), "Verify the two moves are identical"

    # Color checks
    m._piece._color = Color.BLUE
    assert not Move.is_identical(
        m, m_state), "Verify if color does not match test fails"
    assert not Move.is_identical(
        m_state, m), "Verify if color does not match test fails"
    m._piece._color = Color.RED
    assert Move.is_identical(m, m_state), "Verify move correctly restored"

    # Rank checks
    prev_rank, m._piece._rank = m.piece.rank, Rank.flag()
    assert not Move.is_identical(
        m, m_state), "Verify if rank does not match test fails"
    assert not Move.is_identical(m_state,
                                 m), "Verify if rank does not match test fails"
    m._piece._rank = prev_rank
    assert Move.is_identical(m_state, m), "Verify move correctly restored"

    # New checks
    m._new = orig
    assert not Move.is_identical(m, m_state), "Verify new will cause a failure"
    assert not Move.is_identical(m_state, m), "Verify new will cause a failure"
    m._new = new
    assert Move.is_identical(m, m_state), "Verify move correctly restored"

    # Old checks
    m._orig = new
    assert not Move.is_identical(m,
                                 m_state), "Verify orig will cause a failure"
    assert not Move.is_identical(m_state,
                                 m), "Verify orig will cause a failure"
    m._orig = orig
    assert Move.is_identical(m, m_state), "Verify move correctly restored"

    attacked, m._attacked = m._attacked, []  # Just give it so not None
    assert not Move.is_identical(
        m, m_state), "Verify attacked will cause a failure"
    assert not Move.is_identical(m_state,
                                 m), "Verify attacked will cause a failure"
    m._attacked = attacked
    assert Move.is_identical(m, m_state), "Verify move correctly restored"
 def _get_move(plyr: Player, l1, l2) -> Move:
     available_moves = plyr.move_set.avail
     values = list(available_moves.values())
     v = [
         v for v in values
         if v.orig == Location(*l1) and v.new == Location(*l2)
     ]
     assert v
     return v[0]
Beispiel #4
0
def test_verify_neighbor_movements():
    r""" Verifies basic movement of a piece that ensures basic movement works """
    l_orig = Location(1, 1)
    p = Piece(Color.RED, Rank.marshall(), l_orig)

    # Verify all the neighbor locations are valid
    for l_new in l_orig.neighbors():
        Move(p, l_orig, l_new)

    # Verify with attacking
    other = Piece(Color.BLUE, Rank.bomb(), Location(0, 0))
    for l_new in l_orig.neighbors():
        other.loc = l_new
        Move(p, l_orig, l_new, other)
Beispiel #5
0
def _get_move_from_player(plyr: Player, _orig: Tuple[int, int], new: Tuple[int, int]) -> Move:
    r"""
    Get the move from (row1, col1) in \p l1 to (row2, col2) in \p l2.

    :param plyr: Player whose move will be extracted
    :param _orig: Original location to move from
    :param new: New location to move to
    :return: Move corresponding to the move pair
    """
    available_moves = plyr.move_set.avail
    values = list(available_moves.values())
    v = [v for v in values if v.orig == Location(*_orig) and v.new == Location(*new)]
    assert v
    return v[0]
Beispiel #6
0
def test_attack_color():
    r""" Verify that attacks of different colors either do or do not raise errors """
    # Verify when blue attacks red and red attacks blue, everything works
    loc = Location(0, 0)
    red = Piece(Color.RED, Rank.marshall(), loc)
    blue = Piece(Color.BLUE, Rank.marshall(), loc.down())
    # Red attack blue
    Move(red, loc, blue.loc, blue)
    # Blue attack red
    Move(blue, blue.loc, red.loc, red)

    # Red attack red (exception)
    red2 = Piece(red.color, Rank.flag(), blue.loc)
    with pytest.raises(Exception):
        Move(red, red.loc, red2.loc, red2)
    # Blue attack blue (exception)
    blue2 = Piece(blue.color, Rank.flag(), red.loc)
    with pytest.raises(Exception):
        Move(blue, blue.loc, blue2.loc, blue2)
Beispiel #7
0
def test_scout_movements():
    r""" Verify that only scouts can move multiple squares at once """
    loc = Location(3, STD_BRD.num_cols // 2)

    # Just make sure color of the Scout has not effect (it may be a dumb test)
    for color in [Color.RED, Color.BLUE]:
        scout, miner = Piece(color, Rank.scout(),
                             loc), Piece(color, Rank.miner(), loc)
        for p in [scout, miner]:
            for move_dist in [1, 2]:
                for i in range(2):
                    if i == 0: new_loc = loc.relative(row_diff=move_dist)
                    else: new_loc = loc.relative(col_diff=move_dist)

                    if move_dist == 1 or p.rank == Rank.scout():
                        Move(p, loc, new_loc)
                    else:
                        with pytest.raises(Exception) as e_info:
                            Move(p, p.loc, new_loc)
                        assert substr_in_err("multiple", e_info)
Beispiel #8
0
def test_if_has_move():
    r""" Verify the \p piece_has_move method of the \p State class """
    path = STATES_PATH / "deep_q_verify.txt"
    state = State.importer(path, STD_BRD)

    # Marshall cannot move
    marshall_loc = Location(0, 0)
    p = state.get_player(Color.RED).get_piece_at_loc(marshall_loc)
    assert not state.piece_has_move(p)

    # Rank3 can move
    rank3_loc = Location(1, 0)
    p = state.get_player(Color.RED).get_piece_at_loc(rank3_loc)
    assert state.piece_has_move(p)

    # Bomb cannot move
    bomb_loc = Location(0, 4)
    p = state.get_player(Color.RED).get_piece_at_loc(bomb_loc)
    assert not state.piece_has_move(p)

    # Flag cannot move
    flag_loc = Location(0, 6)
    p = state.get_player(Color.RED).get_piece_at_loc(flag_loc)
    assert not state.piece_has_move(p)

    # verify pieces with known moves
    piece_col = (1, 2, 3, 5)
    for col in piece_col:
        flag_loc = Location(0, col)
        p = state.get_player(Color.RED).get_piece_at_loc(flag_loc)
        assert state.piece_has_move(p)

        flag_loc = Location(state.board.num_rows - 1, col)
        p = state.get_player(Color.BLUE).get_piece_at_loc(flag_loc)
        assert state.piece_has_move(p)
Beispiel #9
0
def test_diagonal_movement():
    r""" Verify diagonal movements fail """
    loc = Location(1, 1)
    move_list = [-1, 0, 1]

    p = Piece(Color.RED, Rank.spy(), loc)
    for row_move in move_list:
        for col_move in move_list:
            man_dist = abs(col_move) + abs(row_move)
            l_new = loc.relative(row_move, col_move)
            # Adjacent moves of (exactly) one are sanity checks and should pass
            if man_dist == 0:
                with pytest.raises(Exception):
                    Move(p, p.loc, l_new)
            # Valid adjacent moves for sanity check
            elif man_dist == 1:
                Move(p, loc, l_new)
            # Diagonal moves should fail
            elif man_dist == 2:
                with pytest.raises(Exception) as e_info:
                    Move(p, p.loc, l_new)
                assert substr_in_err("diagonal", e_info)
Beispiel #10
0
def test_edge_lists_board_corner():
    r""" Verify basic information for two edge lists """
    corners = [
        Location(0, 0),
        Location(0, num_brd_cols - 1),
        Location(num_brd_rows - 1, 0),
        Location(num_brd_rows - 1, num_brd_cols - 1)
    ]
    for c in corners:
        el = brd.to_edge_lists(c)
        num_empty = sum([1 for x in el if len(x) == 0])
        assert num_empty == 2, "Corner to edge list does not have two empty lists"

        # Verify length of the lists
        num_squares = sum([len(x) for x in el])
        expected_count = num_brd_rows + num_brd_cols - 2  # Subtract two to loc itself in each dir
        assert num_squares == expected_count

        num_in_row = len(el.right) + len(el.left)
        assert num_in_row == num_brd_cols - 1
        num_in_col = len(el.up) + len(el.down)
        assert num_in_col == num_brd_rows - 1
Beispiel #11
0
def test_immovable_pieces():
    r""" Verify that an immovable piece raises an error """
    moveable = set(range(Rank.MIN(), Rank.MAX() + 1)) | {Rank.SPY}
    immovable = {Rank.BOMB, Rank.FLAG}
    combined = moveable | immovable

    # Sanity check rank sets
    assert len(moveable) > 0 and len(
        immovable) > 0, "Both rank sets should be non-empty"
    assert moveable & immovable == set(), "Rank sets not disjoint"
    assert len(combined) == len(Rank.get_all()), "One or more ranks missing"

    loc = Location(0, 0)
    # As a sanity make sure color is irrelvant
    for color in [Color.RED, Color.BLUE]:
        # Verify each rank is correctly marked movable or immovable
        for r in combined:
            p = Piece(color, Rank(r), loc)
            new_loc = loc.down()
            if r in moveable:
                Move(p, loc, new_loc)
            if r in immovable:
                with pytest.raises(Exception):
                    Move(p, p.loc, new_loc)
Beispiel #12
0
def test_printer_piece_movement():
    r""" Verify piece movement as part of the \p Printer """
    brd = build_test_board(5, 5)
    p = Printer(brd, {Piece(Color.RED, Rank(1), Location(2, 1))},
                {Piece(Color.BLUE, Rank(2), Location(3, 2))},
                Printer.Visibility.RED)
    assert p._is_loc_empty(Location(0, 0))
    assert not p._is_loc_empty(Location(3, 2))

    # p.move_piece(Location(3, 2), Location(2, 4))
    # assert not p._is_loc_empty(Location(2, 4))
    # assert p._is_loc_empty(Location(3, 2))
    #
    # p.delete_piece(Location(2, 4))
    # assert p._is_loc_empty(Location(2, 4))

    p.delete_piece(Location(3, 2))
    assert p._is_loc_empty(Location(3, 2))
Beispiel #13
0
def test_neighbors():
    r""" Verify the neighbors set contains each direction """
    l = Location(1, 1)
    for direct in [l.up(), l.right(), l.down(), l.left()]:
        assert direct in l.neighbors()
Beispiel #14
0
def test_outside_board_moves():
    r""" Verify that the program raises errors when moves are illegal given the board"""
    l_orig = Location(0, 0)

    # Test top and left boundaries
    p = Piece(Color.RED, Rank.marshall(), l_orig)
    for l_new in [l_orig.up(), l_orig.left()]:
        with pytest.raises(Exception) as e_info:
            Move(p, l_orig, l_new)
        assert e_info.type == ValueError

    # Test right and bottom boundaries
    l_orig = Location(STD_BRD.num_rows - 1, STD_BRD.num_cols - 1)
    p = Piece(Color.RED, Rank.marshall(), l_orig)
    for l_new in [l_orig.right(), l_orig.down()]:
        with pytest.raises(Exception) as e_info:
            Move(p, l_orig, l_new)
        assert e_info.type == ValueError

    blocked_loc = Location(4, 2)
    # Verify a blocked location cannot be used as original location
    p = Piece(Color.RED, Rank.marshall(), blocked_loc)
    with pytest.raises(Exception) as e_info:
        Move(p, blocked_loc, blocked_loc.up())
    assert e_info.type == ValueError

    # Verify a blocked location cannot be used as new location
    p = Piece(Color.RED, Rank.marshall(), blocked_loc.up())
    with pytest.raises(Exception) as e_info:
        Move(p, blocked_loc.up(), blocked_loc)
    assert e_info.type == ValueError
Beispiel #15
0
def test_state_basic_moves():
    r""" Verify the basic movement mechanics work without issue """
    path = STATES_PATH / "state_move_verify.txt"
    assert path.exists(), "Move verify file does not exist"

    state = State.importer(path, STD_BRD)

    # Verify initial state matches expectations
    _verify_num_pieces_and_move_set_size(state, 7, 7, 4 + 3, 4 + 3)

    move_stack = MoveStack()
    # Define a series of moves.  Entries in each tuple are:
    #   0: Original piece location
    #   1: Piece new location
    #   2: Number of red pieces
    #   3: Number of blue pieces
    #   4: Size of the red move set
    #   5: Size of the blue move set
    move_list = [((0, 1), (1, 1), 7, 7, 12, 7),
                 ((9, 1), (8, 1), 7, 7, 12, 12),
                 ((1, 1), (2, 1), 7, 7, 12, 12),
                 ((8, 1), (7, 1), 7, 7, 12, 12),
                 ((2, 1), (3, 1), 7, 7, 12, 12),
                 ((7, 1), (6, 1), 7, 7, 12, 12),
                 ((3, 1), (4, 1), 7, 7, 11, 12),  # One less due to blocked by (4, 2)
                 ((6, 1), (5, 1), 7, 7, 11, 11),  # One less due to blocked by (5, 2)
                 ((4, 1), (5, 1), 6, 6, 8, 8),  # Both lost piece in battle
                 ((9, 3), (6, 3), 6, 6, 8, 18),  # Move blue scout
                 ((0, 3), (3, 3), 6, 6, 18, 18),  # Move red scout
                 ((6, 3), (6, 5), 6, 6, 18, 23),  # Move blue scout
                 ((3, 3), (3, 5), 6, 6, 20, 20),  # Move red scout
                 ((6, 5), (6, 4), 6, 6, 23, 23),  # Move blue scout
                 ((3, 5), (9, 5), 6, 5, 16, 22),  # Red scout attack blue spy
                 ((6, 4), (0, 4), 6, 4, 16, 5)  # Blue scout attack red bomb
                 ]
    printer_out = []
    for orig, new, num_red_p, num_blue_p, num_red_mv, num_blue_mv in move_list:
        orig, new = Location(orig[0], orig[1]), Location(new[0], new[1])
        p = state.next_player.get_piece_at_loc(orig)
        assert p is not None
        attacked = state.get_other_player(state.next_player).get_piece_at_loc(new)

        move_stack.push(Move(p, orig, new, attacked))
        assert state.update(move_stack.top())
        assert state._printer._is_loc_empty(orig)

        _verify_num_pieces_and_move_set_size(state, num_red_p, num_blue_p, num_red_mv, num_blue_mv)
        printer_out.append(state.write_board())

    # Try to move red bomb then the red flag
    for orig in [Location(0, 4), Location(0, 6)]:
        p = state.next_player.get_piece_at_loc(orig)
        assert p is not None
        for new in [orig.left(), orig.right]:
            attacked = state.get_other_player(state.next_player).get_piece_at_loc(new)

            with pytest.raises(Exception):
                Move(p, orig, new, attacked)

    # Verify Undo
    for i in range(2, len(move_list) + 1):
        _, _, num_red_p, num_blue_p, num_red_mv, num_blue_mv = move_list[-i]
        state.undo()

        assert state.write_board() == printer_out[-i], "Printer mismatch after do/undo"
        _verify_num_pieces_and_move_set_size(state, num_red_p, num_blue_p, num_red_mv, num_blue_mv)
Beispiel #16
0
    ~~~~~~~~~~~~~~~~

    Test functions for the Stratego \p Board class.

    :copyright: (c) 2019 by Zayd Hammoudeh.
    :license: MIT, see LICENSE for more details.
"""

from stratego.board import Board
from stratego.location import Location

from testing_utils import build_test_board

# Create a dummy board for use in comparison in the movements
num_brd_rows = num_brd_cols = 10
blocked_loc = Location(5, 5)

brd = build_test_board(num_brd_rows, num_brd_cols,
                       {blocked_loc})  # type: Board


def test_build_test_board():
    r""" Test the function \p build_test_board """
    assert brd.num_rows == num_brd_rows
    assert brd.num_cols == num_brd_cols
    assert {blocked_loc} == brd.blocked


def test_edge_lists_board_corner():
    r""" Verify basic information for two edge lists """
    corners = [