```python
def tiles_across(length: int, tile: int) -> int:
    """
    Calculate how many tiles of a given size cover a length, rounding up.
    
    :param length: The total length to be covered by tiles.
    :param tile: The size of each tile.
    :return: The number of tiles needed to cover the length.
    """
    if length < 0 or tile <= 0:
        raise ValueError("Length and tile size must be non-negative.")
    return -(-length // tile)  # Ceiling division

def tiles_needed(width: int, height: int, tile: int, spare: int) -> int:
    """
    Calculate the tiles needed for a wall of a given width and height,
    adding a whole-percent allowance for breakages and rounding up.
    
    :param width: The width of the wall.
    :param height: The height of the wall.
    :param tile: The size of each tile.
    :param spare: The percentage allowance for breakages.
    :return: The total number of tiles needed.
    """
    if width < 0 or height < 0 or tile <= 0 or spare < 0:
        raise ValueError("Width, height, tile size, and spare percentage must be non-negative.")
    total_area = width * height
    tiles_per_area = tiles_across(total_area, tile)
    return -(-tiles_per_area * (1 + spare / 100))  # Ceiling division
```