Game of Life

Every generation is a single SQL query, running in DuckDB-WASM in your browser.

Booting DuckDB-WASM… gen 0 live 0 ms/step

Tap, click, or drag on the grid to toggle cells while paused.

How it works

There is no simulation loop in JavaScript. The board is a table, and one query turns this generation into the next. Here is that query taken apart, one step at a time, with the SQL that does each job.

  1. 1

    Keep only the cells that are alive

    A grid this size holds six thousand squares, but at any moment most of them are dead, and a dead square is just empty space. So we don't store the grid at all. We keep one row per living cell and nothing else, which means an empty board is an empty table. The only other thing we need is a small lookup table, deltas, listing the eight directions a neighbour can sit in, written out once so we never repeat them.

    CREATE TABLE cells (x INTEGER, y INTEGER);
    
    -- the eight directions a neighbour can sit in
    CREATE TABLE deltas (dx INTEGER, dy INTEGER);
    INSERT INTO deltas VALUES
      (-1,-1), (-1,0), (-1,1),
      ( 0,-1),         ( 0,1),
      ( 1,-1), ( 1,0), ( 1,1);
  2. 2

    Let every living cell vote for its neighbours

    A living cell affects the eight squares around it, so we pair each cell with all eight offsets. That is what a CROSS JOIN does: one cell times eight directions gives eight new coordinates, one per neighbour. Picture each cell dropping a vote onto every square beside it. Five living cells cast forty votes, and plenty of those votes land on the same square.

    SELECT cells.x + deltas.dx AS x,
           cells.y + deltas.dy AS y
    FROM cells CROSS JOIN deltas;
  3. 3

    Count the votes on each square

    Now we group the votes by coordinate. The size of each group is how many living neighbours that square has, so a square with three votes had three living neighbours. While we are here we drop anything that fell off the edge of the world, since a cell born outside the grid would only die anyway. After this step every square that matters carries a single number.

    SELECT x, y, COUNT(*) AS n
    FROM neighbours
    WHERE x BETWEEN 0 AND 99
      AND y BETWEEN 0 AND 59
    GROUP BY x, y;
  4. 4

    Apply Conway's one rule

    The whole game lives in this one WHERE clause. A square comes alive next generation if it has exactly three living neighbours. A square that is already alive also survives on two. Everything else goes dark. The plain-English rule, born on three and survive on two, is almost word for word the condition below. The EXISTS check is just asking whether the square was already alive in the current board.

    SELECT x, y FROM counts
    WHERE n = 3
       OR (n = 2 AND EXISTS (
             SELECT 1 FROM cells
             WHERE cells.x = counts.x
               AND cells.y = counts.y));
  5. 5

    Swap the result in, then draw it

    The query hands back the full set of living cells for the next generation, so we drop it straight into the cells table, replacing what was there. Then JavaScript reads the table back and paints a square for every row. That is one tick. Press play and the same query runs again, and again, as fast as you like. Nothing here remembers the past or plans ahead. Each generation is built only from the one before it.

    CREATE OR REPLACE TABLE cells AS
    SELECT * FROM next_cells;
    
    -- then JavaScript reads it back and draws
    SELECT x, y FROM cells;

All five steps, assembled

The engine runs steps 2 to 4 as a single statement each tick. Steps 2 and 3 become the named blocks neighbours and counts, and step 4 reads from them.

WITH neighbours AS (
  -- step 2: every living cell votes for its 8 neighbours
  SELECT cells.x + deltas.dx AS x,
         cells.y + deltas.dy AS y
  FROM cells CROSS JOIN deltas
),
counts AS (
  -- step 3: count the votes, keeping only in-bounds squares
  SELECT x, y, COUNT(*) AS n
  FROM neighbours
  WHERE x BETWEEN 0 AND 99 AND y BETWEEN 0 AND 59
  GROUP BY x, y
)
-- step 4: born on 3, survive on 2
SELECT x, y FROM counts
WHERE n = 3
   OR (n = 2 AND EXISTS (
         SELECT 1 FROM cells
         WHERE cells.x = counts.x AND cells.y = counts.y));

A universe with one law

Watch the board for a while and you start naming things.

That little arrow sliding diagonally across the grid is a glider. The machine in the corner that spits one out every thirty generations is a gun. Before long you're talking about predators, breeders, spaceships, collisions.

The strange thing is that none of those things exist.

There are no gliders in the code. No spaceships. No guns. The rule never mentions them. Every cell knows only three facts: how many neighbours it has, whether it is alive, and whether it should survive to the next generation.

The glider isn't part of the rule.

It emerges from it.

Things that were never programmed

And gliders are just the beginning.

Given enough space, Conway's Life can build logic gates, memory, clocks, and eventually a complete computer. People have assembled working Turing machines from nothing but these flickering cells. Others have built self-replicating patterns that consume empty space to manufacture copies of themselves nearby.

At some point the distinction between "pattern" and "organism" starts to feel negotiable.

Stephen Hawking and Leonard Mlodinow used Life as an example in The Grand Design. Their point was simple and unsettling: a law small enough to fit on a napkin can generate structures complicated enough to look alive.

Two descriptions of the same world

There are at least two ways to describe what you're looking at.

One is microscopic: millions of individual cells switching on and off according to the rule. Perfectly accurate. Almost useless.

The other is macroscopic: that glider will hit that block in nine generations.

The second description leaves out almost everything. Yet it is often the more useful one.

Hawking called this model-dependent realism. A thing is as real as the model that successfully describes it. The glider is not an illusion hiding behind the cells. It is a higher-level fact about the cells.

Physics gives rise to chemistry. Chemistry gives rise to biology. Biology gives rise to minds.

Reality seems to be built from layers like this all the way up.

Determined, yet unknowable

Life is completely deterministic.

Once the initial pattern is placed, every future generation is fixed. Nothing can happen except what the rule permits. The entire future already exists implicitly in the starting state.

Yet knowing the future is another matter.

For most interesting patterns there is no shortcut. If you want to know what generation 10,000 looks like, you must compute generations 1 through 9,999 first. The system is deterministic, but not necessarily compressible.

I still find that difficult to sit with.

The future can be settled long before it becomes knowable.

The future is written, but unreadable

This is the part that lingers.

If human beings are ultimately physical systems, then in principle we are no different. We are arrangements of matter evolving under fixed laws. Every thought, decision, regret, ambition, and act of love would follow from prior states of the universe.

But the gap between principle and practice is enormous.

Nobody predicts human behaviour from quantum mechanics. The equations are too detailed and the system too large. Instead we use a rougher language. We talk about intentions, beliefs, goals, choices.

Hawking called these effective theories.

Most of us call it free will.

Perhaps free will is not an alternative to physical law. Perhaps it is simply the name we give to a level of description that works.

No one is playing

Notice what is missing from this world.

No hand reaches into the grid. No player nudges the pieces along. No hidden intelligence guides the outcome.

The rule does everything.

Motion. Collision. Replication. Complexity. The appearance of purpose. Even the appearance of life.

All of it follows from a law and an initial condition.

That was the provocation at the heart of The Grand Design. Given the right laws, a universe may not require ongoing supervision. Galaxies, stars, planets, living things, and eventually minds capable of asking why they exist could all emerge as consequences.

No intervention required.

This little simulation is about the smallest version of that idea I know.

One law.

A handful of living cells.

Everything else is consequence.

After Stephen Hawking & Leonard Mlodinow, The Grand Design (2010).