# The Neighbor Census

*Task 1 of 5 · [Cellular Automata](https://gpu.rocks/learn/cellular-automata-407c2c34.md) · GPU.js Learn*

A cellular automaton is a world of cells, each one dead (`0`) or alive
(`1`), where every cell's next state depends only on its immediate neighborhood.
That makes it embarrassingly parallel: 256 cells, 256 threads, and no thread needs to know
what any other thread is doing — only what the grid looked like.

Every rule in this module starts with the same question: **how many of my eight
neighbors are alive?** This world is a torus — walk off the right edge, reappear on
the left — and wrapping costs one modulo: `(x + dx + 16) % 16`. The
`+ 16` is not decoration: JavaScript's `%` can go negative while the
GPU's cannot, and adding the width first keeps both operands positive so CPU mode and GPU
mode tell the same story.

## Figures

- **sum the 3×3 block, subtract yourself — and the torus has no edges**

## Goal

**Goal:** make the kernel return, for every cell, the number of live
cells among its eight neighbors — with the edges wrapped around.

## Requirements

- Visit the 3×3 block around this cell with nested `dy`/`dx` loops from −1 to 1
- Wrap every coordinate: `(this.thread.x + dx + 16) % 16` (and the same for y)
- Don't count yourself — a cell is not its own neighbor

## Hint 1 — the loop bounds

Two statically bounded loops: `for (let dy = -1; dy < 2; dy++)`
around `for (let dx = -1; dx < 2; dx++)`. Nine visits per cell.

## Hint 2 — the subtract-self trick

Skipping the middle of the 3×3 block needs no `if`: sum all nine
cells, then subtract `grid[this.thread.y][this.thread.x]` at the end. If
you're dead you subtract 0; if you're alive you take yourself back out.

## Hint 3 — the whole loop body

```js
const yy = (this.thread.y + dy + 16) % 16;
const xx = (this.thread.x + dx + 16) % 16;
count += grid[yy][xx];
```

— then

```js
return count - grid[this.thread.y][this.thread.x];
```

## Same idea elsewhere

Reading a fixed window around your own coordinate is the *stencil* pattern,
and it dominates real GPU workloads: CUDA stencil kernels tile the grid into shared memory
with a one-cell "halo" so neighbors are read once, and WebGPU compute shaders do the same
with workgroup memory.

## Starter code

```js
// Every cell asks the same question, all at once:
// how many of my eight neighbors are alive?
// The world wraps — leave one edge, come back on the other.
const gpu = new GPU({ mode });

const census = gpu.createKernel(function (grid) {
  let count = 0;
  // TODO: sum the 3x3 block around this cell (dy and dx from -1 to 1),
  // wrapping each coordinate with (coord + d + 16) % 16.
  // Careful: a cell is not its own neighbor.
  return count;
}, { output: [16, 16] });

const counts = await census(grid);
console.log('cell (8, 8) sees', counts[8][8], 'live neighbors');
```

---

Interactive version: https://gpu.rocks/learn/cellular-automata-407c2c34/1

[Next task](https://gpu.rocks/learn/cellular-automata-407c2c34/2.md)
