← back to the simulation

HOW IT WORKS

the core loop of the synchronous sandpile

Every square holds a pile of sand grains. A pile of 4 or more collapses, throwing a quarter of itself onto each of its 4 neighbors. Those piles might now have 4 themselves… so they collapse too. That's the entire game.

Try it — 30 seconds

This is the real engine on a tiny grid. Click cells to drop grains (shift-click drops 4), then hit STEP and watch piles collapse. Hover any pile to see its math.

generation 0 · 0 grains
click a cell to add a grain

Everything below is that one rule, examined closely.

One generation

  1. Freeze the grid. Every cell is read from the same snapshot, and all updates land in a fresh, empty grid. Nothing happens “one cell at a time” — the entire grid updates at once. That's what synchronous means here.
  2. Split each pile. A cell holding v grains keeps v % 4 (the remainder) and prepares to ship out the rest in equal quarters: q = ⌊v / 4⌋.
  3. Send the quarters. Each of the 4 neighbors — up, down, left, right — receives q grains. A cell with 16 grains sends 4 to each side in a single tick, not one topple at a time.
  4. Sum what arrived. A cell's new value is its own remainder plus everything its neighbors shipped in. If that sum is 4 or more, it will topple next generation — this is how avalanches travel outward as waves.

The math of one topple

Everything is division with remainder, base 4. A pile of v splits like this:

pile vkeeps v % 4sends ⌊v/4⌋ to each neighbortotal leaving
330 — stable, nothing moves0
4014
6214
9128
160416

And on the receiving side, a cell's next value is one sum — its own remainder plus one quarter-share from each neighbor that toppled:

next = v % 4 + qnorth + qsouth + qwest + qeast

That one sum produces the surprise you'll see below at generation 2: the center topples to 0, but all four neighbors topple back 1 each —

nextcenter = 0 + 1 + 1 + 1 + 1 = 4  → critical again

Watch 16 grains topple

Drop 16 grains in the center of an empty 5×5 grid. Glowing cells are critical (≥4) and will topple next tick:

16
generation 0
4 44 4
generation 1
1 22 141 22 1
generation 2
1 212 1111 212 1
generation 3 — settled

Every grid above was produced by the actual engine, not drawn by hand.

Notice generation 2: the center toppled to zero, but its four neighbors each toppled back exactly one grain — so the center hits 4 again and topples a second time. Piles feeding each other like this is where all the complex behavior comes from.

The loop in code

This is the real engine (sim.js), lightly trimmed. One call = one generation:

for (row of rows) {
  for (col of cols) {
    v = grid[row][col]
    q = v >> 2                 // ⌊v / 4⌋ — one quarter per neighbor
    next[row][col] += v & 3    // v % 4  — the remainder stays home
    if (q === 0) continue       // stable pile, nothing to do

    if (row > 0)        next[row - 1][col] += q   // north
    if (row < rows - 1) next[row + 1][col] += q   // south
    if (col > 0)        next[row][col - 1] += q   // west
    if (col < cols - 1) next[row][col + 1] += q   // east
    // no neighbor on that side? those grains fall off the world
  }
}
grid = next                    // the whole grid flips at once

The edge of the world

A cell on the boundary has fewer than 4 neighbors, but it still splits into 4 quarters — the quarters aimed off the grid are simply lost. (In the visualization, those are the sparks flying off the rim.) With no emitter running, total mass can only stay flat or shrink, never grow.

The optional center emitter injects fresh grains at one cell after every toppling pass — a faucet dripping onto the pile. With it on, mass can grow without bound and the guarantees below no longer apply.

Why it always settles (without an emitter)

Grains never appear from nowhere and the edges only leak them away, so the grid can only visit finitely many distinct states. Run long enough and, by the pigeonhole principle, some state must repeat — and because the rule is deterministic, history repeats exactly from there forward. Two outcomes are possible:

Steady state — every cell is below 4, nothing topples, the grid stops changing. Or a cycle — a loop of states feeding each other forever, like two piles bouncing the same grains back and forth.

The app fingerprints every generation with a fast hash and watches for a repeat — when the status line says STEADY STATE or CYCLE, that's the moment the fingerprint matched. The green or purple dashed line on the graph marks where the repeat began.

Not the classic sandpile

If you've seen the famous abelian sandpile (Bak–Tang–Wiesenfeld), this is a deliberate variation. The classic model topples one unstable cell at a time, moving exactly 4 grains, and famously reaches the same final state regardless of toppling order. This one topples everything simultaneously and ships ⌊v/4⌋ to each neighbor — so a 16-grain pile moves 16 grains in one tick, and the dynamics ripple in waves you can watch.