```python
from typing import List, Tuple

def region_totals(grid: List[List[int]], queries: List[Tuple[int, int, int, int]]) -> List[int]:
    if not isinstance(grid, list) or not grid:
        raise ValueError("grid must be a non-empty list of rows")
    width = len(grid[0]) if isinstance(grid[0], list) else 0
    if width == 0:
        raise ValueError("rows must be non-empty lists")
    for row in grid:
        if not isinstance(row, list) or len(row) != width:
            raise ValueError("rows must all share one length")
        for cell in row:
            if isinstance(cell, bool) or not isinstance(cell, int):
                raise ValueError("cells must be integers")
    if not all(isinstance(query, list) and len(query) == 4 for query in queries):
        raise ValueError("queries must be lists of exactly four integers")
    for query in queries:
        if query[0] >= query[2] or query[1] >= query[3]:
            raise ValueError("query block must be non-empty")
        if query[0] < 0 or query[1] < 0 or query[2] >= len(grid) or query[3] >= len(grid[0]):
            raise ValueError("query block must be inside the grid")

    # Build a prefix-sum table over the grid
    prefix_sum = [[0] * (width + 1) for _ in range(len(grid) + 1)]
    for i in range(1, len(grid) + 1):
        for j in range(1, width + 1):
            prefix_sum[i][j] = grid[i-1][j-1] + prefix_sum[i-1][j] + prefix_sum[i][j-1] - prefix_sum[i-1][j-1]

    # Answer queries from the table
    return [prefix_sum[query[2]][query[3]] - prefix_sum[query[2]][query[1]] - prefix_sum[query[0]][query[3]] + prefix_sum[query[0]][query[1]] for query in queries]
```