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
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)
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)
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
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")
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