Skip to content
Русский

The [cellular] table

A cellular preset runs a discrete cellular automaton: a square grid of cells, each generation every cell deciding its next state from its neighbours’. [cellular] picks which automaton, on how large a grid:

system = "cellular"
[cellular]
family = "life_like" # "life_like" (the default), "larger_than_life" or "cyclic"
grid = 256 # cells per side, 16..=1024; the default is 256
wrap = true # a torus (the default); false makes every cell past the border dead

All three keys are read once, at load, and are not bindable. An unknown family, or a grid outside 16..=1024, is a load error. A preset with no [cellular] table runs life_like on a 256-cell torus.

grid is content, not resolution. A pattern is a fixed number of cells — a glider is five — so the grid decides how large every pattern looks: double it and every glider draws at half the size. The grid never follows the window, and it is stretched over the frame as it is, so on a wide window a cell is wider than it is tall.

Every cell is drawn from the seed. The starting field, and every disc a reseed refills, is hashed from the preset’s [generator] seed — never from a clock — so the same preset driven by the same music runs the same history. seed = "random" does not vary it: the automaton always uses the preset’s declared number (0 when it declared "random").

Four parameters read the same on every family:

  • step_rate is generations per second, not per frame, so the automaton runs at the same speed at 30 fps and at 144. Bound to audio it speeds up and slows down with the music — and because an automaton’s history depends on every step before it, two runs at different rates diverge for good.
  • reseed refills one disc of the grid (a fifth of its side in radius, at a position drawn from the seed) with fresh cells, once per rise past 0.5 — held high, it refills once, not every frame. reseed = "beat" puts a disc on every beat; routed through a [latch] it fires on a condition of its own.
  • trail and age_tint paint history. The grid remembers, for every cell, how many generations since it last changed; a cell that has just died glows and fades out over trail generations, sliding age_tint of the way along the palette as it goes. trail = "0" draws only the live cells — a binary checkerboard, which is what a raw automaton looks like and rarely what a preset wants. Both are inert on cyclic, which has no dead cells.

The three families, following ADR-0180 — every parameter in the last two columns is read by one family only and does nothing on the others:

familyThe ruleStructuralModal
life_likeA dead cell with k live neighbours among its eight is born if bit k of birth is set; a live one survives if bit k of survive isbirth, survive—
larger_than_lifeThe same, over a square of side 2 × radius + 1, with birth and survival as ranges of how full that square isradiusbirth_lo, birth_hi, survive_lo, survive_hi
cyclicEach cell holds one of states colours and advances to the next one round the cycle when at least threshold of its eight neighbours already hold itstates, threshold—

life_like: a rule is two bitmasks

A rule in Life’s space is written B…/S…: the neighbour counts that bring a dead cell to life, and the counts that keep a live one alive. birth and survive are those two lists as bitmasks over the counts 0 to 8 — add 2^k for every count k in the list:

RuleB listbirthS listsurvive
Conway’s Life, B3/S2338 (= 2³)2, 312 (= 2² + 2³)
HighLife, B36/S233, 672 (= 8 + 64)2, 312
Seeds, B2/S24none0
Day & Night, B3678/S346783, 6, 7, 84563, 4, 6, 7, 8472

So Conway’s Life is birth = "8", survive = "12" — the defaults. Both are whole numbers from 0 to 511, rounded before the automaton sees them.

larger_than_life: a rule is two ranges over a wider square

radius sets the square each cell reads: side 2 × radius + 1, the cell itself left out, so radius 5 reads 120 neighbours. birth_lo..birth_hi and survive_lo..survive_hi are fractions of that square that must be live, inclusive at both ends — so a rule keeps its meaning when you change the radius. At radius 1 with fractions that land on whole counts this is life_like: Conway is birth_lo = birth_hi = "0.375" (3 of 8) and survive_lo = "0.25", survive_hi = "0.375".

Above radius 1 the rules grow blobs and bugs that travel for a while, where a radius-1 rule settles into still lifes quickly. The defaults — radius 5, births at 0.28..0.385, survival at 0.26..0.47 — are one such rule, and a sensitive one: a single neighbour count off either end of a range can be the difference between a field that keeps moving longer and one that freezes at once.

A larger_than_life world with no reseed settles. On the default rule that takes about a minute: Tide Bugs’ own field — the default 256-cell grid, seed 23 — run at 12 generations a second with its reseed switched off has settled into about thirty small rings on black by the one-minute mark, and its coverage does not change after that. Whether a field lasts longer depends on the grid and the seed as much as on the rule, so no rule here is a promise that a world stays alive. reseed is how a world stays alive — bind it to a beat, an onset or a slow timer, and every disc of fresh soup it drops boils into new bugs before the field settles again.

cyclic: a rule is a cycle

Every cell is one of states colours, and advances to the next one round the cycle when at least threshold of its eight neighbours already hold it. From noise this organizes, within a few hundred generations, into interlocking rotating spirals; the defaults — 3 colours, threshold 3 — get there fastest. There are no dead cells: every cell is lit, at palette position state / states, so the cycle is laid round the palette once and a spiral’s arms are the palette in order. hue rotates it, as on every system.

Holding a rule, and the quality tier

Every structural parameter — birth, survive, radius, states, threshold — is rounded to a whole number, and bound to audio it re-picks the rule on every frame. Bind it through [hold] so it changes on the beat or the bar instead. Stepping states down is safe: a cell holding a colour past the new cycle is read round it and written back inside it on the next generation.

grid and radius are capped by the quality tier, because both change what is drawn: the Floor tier allows a 512-cell grid and radius 6, the Rich tier 1024 and 10. A preset asking within the Floor caps runs identically on both. One asking for more runs at the cap and says so — the standalone prints what was asked and what it runs at, the same way it reports an iteration cap or a tier demotion. Author against the Floor caps.

The range that reads for each parameter, and the families it is inert on, is printed in the cellular table of Parameter roster.

Built from 13c7582 at version 0.158.0. This site tracks main and is not versioned per release.