Example #1
0
def test_get_adjacent_coordinates():
    """ Tests utils.space.get_adjacent_coordinates function """
    for _ in range(pytest.large_iteration_count):
        random_coordinates = (random.randint(0,
                                             pytest.large_iteration_count - 1),
                              random.randint(0,
                                             pytest.large_iteration_count - 1))
        grid_width = pytest.large_iteration_count
        grid_length = pytest.large_iteration_count
        adjacent_coordinates = space.get_adjacent_coordinates(
            random_coordinates, grid_width, grid_length)
        # There can be at most 4 adjacent coordinates on a 2D grid and a minimum of 2 if grid is this size
        assert 2 <= len(adjacent_coordinates) <= 4
        adjacent_coordinates_list = [
            (random_coordinates[0] - 1, random_coordinates[1]),
            (random_coordinates[0] + 1, random_coordinates[1]),
            (random_coordinates[0], random_coordinates[1] - 1),
            (random_coordinates[0], random_coordinates[1] + 1),
        ]
        # Ensure only adjacent coordinates within grid bounds are returned from get_adjacent_coordinates function
        for expected_adjacent_coordinate in adjacent_coordinates_list:
            if space.are_coordinates_between_limits(
                    expected_adjacent_coordinate, grid_width, grid_length):
                assert expected_adjacent_coordinate in adjacent_coordinates
            else:
                assert expected_adjacent_coordinate not in adjacent_coordinates
Example #2
0
def test_are_coordinates_between_limits():
    """ Tests utils.space.are_coordinates_between_limits function """
    grid_width = 25
    grid_length = 10
    coordinates = (5, 10)
    assert space.are_coordinates_between_limits(coordinates,
                                                grid_length=grid_length,
                                                grid_width=grid_width)
    grid_width = 10
    assert not space.are_coordinates_between_limits(
        coordinates, grid_length=grid_length, grid_width=grid_width)
    for _ in range(pytest.large_iteration_count):
        grid_width = random.randint(1, pytest.large_iteration_count)
        grid_length = random.randint(1, pytest.large_iteration_count)
        coordinates = space.get_coordinates_between_limits(
            grid_width=grid_width, grid_length=grid_length)
        assert space.are_coordinates_between_limits(coordinates, grid_width,
                                                    grid_length)
Example #3
0
def test_guess(mock_player_input):
    """ Tests player.guess method """
    for _ in range(pytest.large_iteration_count):
        players, _, game_board = _initialize_resources()
        for battleship_player in players:
            guess = battleship_player.guess({
                "coordinate": (0, 0),
                "successful_hit": False,
                "ship_destroyed": False,
                "already_hit": False
            })
            assert space.are_coordinates_between_limits(
                guess, game_board.width, game_board.length)
Example #4
0
    def _human_guess(self) -> tuple:
        """ Accept an attack guess from a human player as raw input

        :returns a tuple containing the X and Y coordinates of the square to attack
        """
        input_valid = False
        coordinate = None
        while not input_valid:
            try:
                coordinate = self._get_coordinate_from_input()
            except ValueError:
                print(
                    "Individual coordinate components must be single integers")
                continue
            if space.are_coordinates_between_limits(coordinate,
                                                    self.game_board.width,
                                                    self.game_board.length):
                input_valid = True
        return coordinate
Example #5
0
    def _validate_ship_placement(coordinates: list,
                                 game_board: board.BattleshipBoard) -> None:
        """ Validates that the given coordinates for ship placement on the given board are valid

        :param coordinates - a list of x and y coordinate tuples to check the validity of
        :param game_board - the board object to place the given coordinates in
        """
        for coordinate in coordinates:
            if len(coordinate) != 2:
                raise ValueError(
                    "A coordinate must be a tuple consisting of X and Y integers"
                )
            if not space.are_coordinates_between_limits(
                    coordinate, game_board.width, game_board.length):
                raise ValueError(
                    "The location of the ship is not within the boundaries of the grid"
                )
            if not game_board.is_square_clear(coordinate):
                raise ValueError(
                    "The location of the ship overlaps another ship")
Example #6
0
    def attack(self, coordinate: tuple, fleet: ShipFleet) -> tuple:
        """ Accepts an attack from a player to a given fleet on the board by transmitting the attack to the fleet and
        refreshing the board with ship coordinates (which should include newly damaged segments of ships)

        :param coordinate - a tuple of x and y coordinates to attack on the board
        :param fleet - a fleet residing on the board to attack
        :returns a tuple containing booleans denoting whether a ship was successfully hit and destroyed or whether a
            ship has already been hit at the given coordinates
        """
        assert space.are_coordinates_between_limits(coordinate, self.width,
                                                    self.length)
        successful_hit, ship_destroyed, already_hit = False, False, False
        if fleet.ship_is_hit(coordinate):
            already_hit = True
        else:
            # Attack the fleet
            successful_hit, ship_destroyed, representation = fleet.accept_attack(
                coordinate)
            # If the attack was successful, then refresh the board with the new damaged representation of the ship
            self.refresh([coordinate], representation="@", clear_board=False)
            if successful_hit:
                self.refresh([coordinate], representation, clear_board=False)
        # Emit whether the attack was successful and if a ship was destroyed
        return successful_hit, ship_destroyed, already_hit