def get_neighbours(r: int, c: int, rows: int, cols: int) -> list[tuple[int, int]]:
    """Return a list of neighbouring locations

    For each of the cardinal points, we create a tuple of coordinates.
    Each coordinate is constrained to the size of the array (for example,
    the point to the left of an item in column 0 is at "column - 1 or else 0")
    We also use a "list(set(...))" construction to only return the unique set,
    because, at the edge, many of these constraints will mean the neighbours map
    to the same edge point.

    Args:
        r (int): The row of the point to find neighbours for
        c (int): The column of the point to find neighbours for
        rows (int): The total number of rows available
        cols (int): The total number of columns available

    Returns:
        list[tuple[int, int]]: A list of coordinate pairs
    """
    return list(
        set(
            [
                (max(0, r - 1), max(0, c - 1)),  # Above Left
                (max(0, r - 1), c),  # Above Center
                (max(0, r - 1), min(cols - 1, c + 1)),  # Above Right
                (r, max(0, c - 1)),  # Left
                # Center Center is not a neighbour, it's US :)
                (r, min(cols - 1, c + 1)),  # Right
                (min(rows - 1, r + 1), max(0, c - 1)),  # Below Left
                (min(rows - 1, r + 1), c),  # Below Center
                (min(rows - 1, r + 1), min(cols - 1, c + 1)),  # Below Left
            ]
        )
    )