Cellular Automata

Philosophy

Cellular automata embody emergence from simplicity — the discovery that profound complexity can arise from trivially simple rules applied to a grid of cells. Stephen Wolfram’s A New Kind of Science (2002) argued this is a fundamental principle of the universe itself: simple programs, not equations, may underlie physical reality.

John Conway’s Game of Life (1970) demonstrated that four rules about birth, survival, and death could produce self-replicating patterns, gliders, computers, and infinite variety — all from an initial configuration of on/off cells. The philosophical implication: life-like behavior needs no life-like rules.

Key Algorithms

Elementary Cellular Automata (1D, Wolfram)

A row of cells, each 0 or 1. Each cell’s next state depends on its current state and two neighbors (3 cells → 8 possible configurations → 256 possible rules, numbered 0-255).

Famous rules:

Display: each generation as a new row, producing a 2D spacetime diagram.

Parameters: rule number, initial condition, cell size, generations

Conway’s Game of Life (2D)

Grid of cells, alive or dead. Each frame:

  1. Live cell with 2-3 live neighbors survives
  2. Dead cell with exactly 3 live neighbors becomes alive
  3. All other cells die or stay dead

Parameters: grid size, cell size, initial density, speed, wrap-around toggle

Variations

Notable Artists & Works

p5.js Implementation Notes

nannou Implementation Notes

Hexagonal grids — The nannou Nature of Code example (7_hexagon_cells.rs) demonstrates CA on hexagonal grids using draw.polygon().points(hex_vertices):

let n_sides = 6;
let points = (0..n_sides).map(|i| {
    let phase = i as f32 / n_sides as f32;
    let x = radius * (TAU * phase).cos();
    let y = radius * (TAU * phase).sin();
    pt2(x, y)
});
draw.polygon()
    .x_y(cell_x, cell_y)
    .color(fill)
    .stroke(BLACK)
    .points(points);

Hex grid layout: offset every other row by 1.5 * cell_width. Row spacing is sin(60°) * cell_width. This produces visually richer CA than square grids — six neighbors instead of four (or eight with diagonals) creates different emergent dynamics.

Functional Composition Pattern

The thi.ng ecosystem demonstrates cellular automata implemented as composable transducers — pure functions that transform state without mutation:

// CA as a functional pipeline:
// 1. Define rule as pure function: (neighborhood) → next_state
// 2. Apply rule across grid via map/transducer
// 3. Produce new grid (immutable — old grid preserved)

function stepCA(grid, width, rule) {
  return grid.map((cell, i) => {
    const neighbors = getNeighbors(grid, i, width);
    return rule(cell, neighbors);
  });
}

This functional approach:

Color Mapping for Multi-State CA

For continuous automata or multi-state systems (Brian’s Brain, Wireworld), use perceptual color mapping:

Demos in the gallery