def apply_rules_block(start, end, state):
    """
    Use a separate Ray task for computing a block update, rather than a
    method that can only run in the ``RayConwaysRulesBlocks`` actor's worker.
    Otherwise, this implementation follows ``RayConwaysRules.apply_rules``.
    Args:
        start: Starting row index in ``State.grid`` for this block, inclusive.
        end: Ending row index in ``State.grid`` for this block, exclusive.
        state: The current ``State`` object.
    """
    x = state.x_dim
    y = state.y_dim
    g = state.grid
    block = g[start:end].copy()
    for n in range(end-start):
        i = n+start
        for j in range(y):
            im1 = i-1 if i > 0   else x-1
            ip1 = i+1 if i < x-1 else 0
            jm1 = j-1 if j > 0   else y-1
            jp1 = j+1 if j < y-1 else 0
            num_live_neighbors = (
                g[im1][jm1] + g[im1][j] + g[im1][jp1] +
                g[i][jm1] + g[i][jp1] +
                g[ip1][jm1] + g[ip1][j] + g[ip1][jp1])
            cell = block[n][j]  # default value is no change in state
            if cell == 1:
                if num_live_neighbors < 2 or num_live_neighbors > 3:
                    block[n][j] = 0
            elif num_live_neighbors == 3:
                block[n][j] = 1
    return block