Skip to the plate
FORMA PUBLIC DOMAIN GENERATIVE ATLAS / ED. 0.28
Plate 37, Turmite Automaton: a still of the automaton / 2d turing plate as the atlas renders it, in the automata accent.

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));
    }
}