PulseCore

Chapter 10 · Section 4

Every Flip: The Cell Rule

Every step of the run, before the Pulsecore's novas and after them, begins with the same rule on the field (stepField(), engine.js; Part 2.2). It has three parts and no thresholds to set.

  1. Perpetual reversal. Every pulser flips, 0 → 1 or 1 → 0. Once a cell has pulsed it never stops (Information-Driven Perpetuation).
  2. Bifurcation. A null cell, one that has never pulsed, gathers exposure from its lit neighbours, one eighth of a pulse for each lit neighbour each flip (weighted by direction when the universe spins). When its exposure reaches one whole pulse it bifurcates, ∅ → (0 ⥂ 1), and lights (Law of Binary Emergence). Exposure is never lost.
  3. Fold. A pulser whose eight neighbours are all pulsers in its own phase carries no contrast: it folds back to null (The First Fold). What folds is counted into the void; after the Data Nova a fold can seed a well.
  4. The neighbourhood wraps, because the field is the skin of a torus.
  5. The step is kept for Back: the last fields are stored so the player can step backward, up to 200 steps on a small field and fewer on a large one (about 4 million cells in all; Part 2.13).

The method, in plain steps:

for every cell:
    if it pulses:
        if all eight neighbours pulse in its phase → fold it to null
        else flip it
    else (null):
        exposure += (lit neighbours, spin-weighted) / 8
        if exposure ≥ 1 → it lights and starts pulsing, taking a lit neighbour's colour

The code:

// public/game-v8.4/engine.js:53 stepField()
if (pulser[r][c]) {
    pulsers++;
    // the fold: eight pulser neighbours, all in this cell's phase
    let same = 0;
    for (let k = 0; k < 8; k++) {
        const rr = (r + OFFS[k][0] + rows) % rows, cc = (c + OFFS[k][1] + cols) % cols;
        if (pulser[rr][cc] && lit[rr][cc] === lit[r][c]) same++; else break;
    }
    if (same === 8) { lr[c] = 0; pr[c] = 0; exposure[r][c] = 0; folded.push([r, c]); continue; }
    lr[c] = lit[r][c] ? 0 : 1; pr[c] = 1; flips++;
} else {
    const n = exposureAt(lit, r, c, rows, cols, weights);
    if (n > 0) exposure[r][c] += n / 8;
    if (exposure[r][c] >= 1) {
        lr[c] = 1; pr[c] = 1; exposure[r][c] = 0; born.push([r, c]); flips++;
        …
    } else { lr[c] = 0; pr[c] = 0; }
}