PL. 37 · AUTOMATA / AUTOMATON / 2D TURING
Turmite Automaton
Christopher Langton, 1986 · Greg Turk & Jim Propp, 1986 · named by A. K. Dewdney, 1989
OPEN THE LIVE PLATE ▸DEFINITION
(state, color) → (new_color, turn, new_state)
NOTES
A 2D Turing Machine that moves on a grid, changing the color of cells and turning relative to its orientation. The one-state case is Langton's ant of 1986, kept here as the reference rule; Turk and Propp generalised the machine to internal states, and Dewdney named the family as a pun on termite. Depending on the rule table, turmites produce chaotic highways, spiral growth, or structured periodic crystals.
PROVENANCE
- Origin
- C. Langton, "Studying artificial life with cellular automata", Physica D 22, 1986 — the ant; Turk & Propp's two-state machines, 1986; named by A. K. Dewdney, Scientific American, September 1989
- Standing
- Public domain — cellular automaton model
- Constants
- Grid size sets canvas resolution; rule selects state transitions
- Source
- doi:10.1016/0167-2789(86)90237-X
HOUDINI · VEX
The same published mathematics as a Detail Wrangle body. Paste it into a Wrangle with Run Over set to Detail; every constant is the published value plus a tweak channel, so Create Spare Parameters gives a slider that starts where the paper does.
// FORMA — PL. 37 · TURMITE AUTOMATON — Christopher Langton, 1986 · Greg Turk & Jim Propp, 1986 · named by A. K. Dewdney, 1989
// (state, color) → (new_color, turn, new_state)
// Paste into a Detail Wrangle (Run Over: Detail), no inputs needed.
// Written from the published mathematics, not adapted from any code.
// Constants arrive at their published values. Press the node's Create
// Spare Parameters button and every tweak becomes a slider — starting
// at 0, the published figure, and moving in the constant's own units.
// https://forma-gen.com/#plate=turmite
float p_grid = 120 + chf('grid_tweak'); // grid size · live 60 .. 180
float p_rule = 0 + chf('rule_tweak'); // rule set · live 0 .. 3
// The plate's own colour: FORMA's AUTOMATA accent as a cosine ramp,
// brightest near t = 0 and t = 1, near-black around t = 0.5.
vector forma_ramp(float t){
return set(
0.3301 + 0.3588 * cos(6.28318530718 * (t + 0)),
0.2255 + 0.2451 * cos(6.28318530718 * (t + 0.05)),
0.46 + 0.5 * cos(6.28318530718 * (t + 0.1)));
}
// The machine run to its own finish line in one cook: read the colour under
// the head, write, turn, step, change state — the plate's four rule tables
// flattened to arrays indexed state × colour, since VEX has no structs. The
// plate runs 1200 steps a frame until the lattice saturates (38% filled, or
// 420,000 steps) and then restarts; the cook is the construction it holds at
// that moment. One point per coloured cell, on the plate's own alphabet-
// scaled band in the ramp's bright lobe; the head's HILITE cursor is the
// animation's, not the construction's, and is not ported. Deterministic by
// construction — a turmite has no randomness at all.
int n = int(rint(p_grid));
int rule = int(rint(p_rule)) % 4;
// the tables, flattened [state * ncols + colour] -> write / turn / next state
int ncols, nstates;
int TC[], TT[], TS[];
if (rule == 0){ // one state: Langton's ant, the reference case
nstates = 1; ncols = 2;
TC = {1, 0}; TT = {1, -1}; TS = {0, 0};
} else if (rule == 1){ // state remembers the last turn: the spiral
nstates = 2; ncols = 2;
TC = {1, 1, 1, 0}; TT = {1, -1, -1, 1}; TS = {1, 0, 0, 1};
} else if (rule == 2){ // two states over three colours
nstates = 2; ncols = 3;
TC = {1, 2, 0, 2, 0, 1}; TT = {1, -1, 1, -1, 1, -1}; TS = {0, 1, 0, 1, 0, 0};
} else { // about-faces pack a dense body
nstates = 2; ncols = 2;
TC = {1, 0, 1, 1}; TT = {2, 1, -1, 1}; TS = {1, 0, 0, 1};
}
int g[];
resize(g, n * n);
int x = n / 2, y = n / 2, dir = 0, st = 0, filled = 0;
int dx[] = {0, 1, 0, -1}, dy[] = {-1, 0, 1, 0};
int limit = int(n * n * 0.38);
for (int steps = 0; steps < 420000; steps++){
if (filled > limit) break; // the plate's own saturation line
int idx = y * n + x;
int a = (st % nstates) * ncols + (g[idx] % ncols);
int was = g[idx];
g[idx] = TC[a];
if (!was && TC[a]) filled++;
else if (was && !TC[a]) filled--;
dir = (dir + TT[a] + 4) % 4;
st = TS[a];
x = (x + dx[dir] + n) % n;
y = (y + dy[dir] + n) % n;
}
for (int yy = 0; yy < n; yy++){
for (int xx = 0; xx < n; xx++){
int c = g[yy * n + xx];
if (!c) continue;
// canvas y runs down; negated so the construction sits as the plate shows it
int pt = addpoint(0, set(float(xx - n / 2), float(n / 2 - yy), 0.0));
// the band runs past 1.0 deliberately: the ramp is periodic and 1.08
// is as bright as 0.08, where anything near 0.5 is black
setpointattrib(0, "Cd", pt,
forma_ramp(0.82 + float(c - 1) / float(max(1, ncols - 1)) * 0.26));
}
}