Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Grids — pathfinding & automata

A first-class 2-D cell grid — the one primitive under tilemaps, spatial pathfinding (space, not graph’s topology), cellular automata and Wave Function Collapse. Cells address like matrix/table ({id}.r{i}c{j}); seed a maze from a compact # . @ * ASCII string; the pathfinders reuse the algo kit’s exact colour grammar (discovered cyan → current magenta → done lime), and generation pre-simulates at build time then replays with run.

Each block is the whole file — copy it into x.manic and run manic x.manic (live) or --record out (video).

grid-astar

A* over a seeded ASCII maze: open cells flood by f-score (frontier cyan → current magenta), a live frontier/visited readout counts up, and the shortest route traces out in gold as {id}.path. neighbors picks 4- or 8-connectivity.

title("A* Pathfinding — Search Over Space");
canvas("16:9");
template("neon");

watermark(mark, (w*0.15, h*0.05), "Made With Manic");

// A cell grid seeded from a compact ASCII maze: `#` wall, `.` open, `@` start,
// `*` goal. A* explores the open cells (frontier cyan → current magenta), then
// the shortest route is traced in gold — the spatial sibling of the algo kit's
// graph search, sharing its exact colour grammar.
grid(g, "@ . . . . . . . ; # # # # # # . # ; . . . . . . . . ; . # # # # # # # ; . . . . . . . . ; # # # # # # # *", (cx, cy+20), 8, 6, 78);
neighbors(g, "4");

gridastar(g, (0,0), (7,5), manhattan);
draw(g.path, 1.4);

grid-life

Conway’s Game of Life: a glider seeded with setcell, then evolve pre-simulates six generations at build time (alive = a filled cell, Conway’s B3/S23) and run replays them — the glider walks diagonally across the grid.

title("Conway's Life — A Glider");
canvas("16:9");
template("neon");

watermark(mark, (w*0.15, h*0.05), "Made With Manic");

// A cellular automaton on the same cell grid. `step` pre-simulates one Conway
// generation at build time (alive = a filled `wall` cell, 8-neighbourhood);
// `run` then replays the stored generations. This glider walks diagonally.
grid(life, (cx, cy+10), 14, 12, 42);
setcell(life, 1, 2, wall);
setcell(life, 2, 3, wall);
setcell(life, 3, 1, wall);
setcell(life, 3, 2, wall);
setcell(life, 3, 3, wall);

evolve(life, "life"); evolve(life, "life"); evolve(life, "life");
evolve(life, "life"); evolve(life, "life"); evolve(life, "life");
run(life, 6, 5.0);

grid-wfc

Wave Function Collapse: collapse pre-simulates a seeded, neighbour-constrained settling row by row, then run replays the grid resolving from empty into a finished maze — deterministic, so the same seed always settles the same way.

title("Wave Function Collapse — A Maze, Settling");
canvas("16:9");
template("neon");

watermark(mark, (w*0.15, h*0.05), "Made With Manic");

// `collapse` pre-simulates a seeded Wave-Function-Collapse-style settling at
// build time — each cell is decided under its neighbours' constraints, one row
// at a time — then `run` replays the grid resolving from empty to a finished
// maze. Seeded, so it is fully deterministic (same seed ⇒ same maze).
grid(mz, (cx, cy+10), 20, 14, 30);
collapse(mz, "maze", 7);
run(mz, 14, 5.0);

grid-life-zoo

Conway’s Life’s whole taxonomy — a still life (Block), an oscillator (Blinker) and a spaceship (Glider) — three grids seeded with setcell, evolved eight generations and run in parallel: the Block holds, the Blinker flips, the Glider walks. The famous pattern zoo, entirely in the grid kit.

// Conway's Life — the Zoo. img_4.png's taxonomy (still lifes / oscillators /
// spaceships) is nothing more than Conway's Life on a grid — which the grid kit
// already does: seed cells, `evolve` a few generations at build time, then `run`
// to replay them. Three grids run in parallel: a Block that never moves, a Blinker
// that oscillates, and a Glider that walks across its grid. No new kit needed.
title("Conway's Life — the Zoo");
canvas("16:9");
template("mono");

let u = (w+h-abs(w-h))/1440;
text(kicker, (cx, h*0.10), "STILL LIFE · OSCILLATOR · SPACESHIP — all just Conway's Life");
size(kicker, 22*u); color(kicker, dim); bold(kicker); wrap(kicker, w*0.9);

// --- Still life: Block (never changes) ---
grid(blk, (w*0.22, cy), 6, 6, 40);
setcell(blk, 2, 2, wall); setcell(blk, 2, 3, wall);
setcell(blk, 3, 2, wall); setcell(blk, 3, 3, wall);
text(blkL, (w*0.22, cy+180*u), "Block — still life"); size(blkL, 20*u); color(blkL, cyan);

// --- Oscillator: Blinker (period 2) ---
grid(bln, (w*0.5, cy), 6, 6, 40);
setcell(bln, 2, 1, wall); setcell(bln, 2, 2, wall); setcell(bln, 2, 3, wall);
text(blnL, (w*0.5, cy+180*u), "Blinker — oscillator (p2)"); size(blnL, 20*u); color(blnL, cyan);

// --- Spaceship: Glider (translates) ---
grid(gld, (w*0.78, cy), 8, 8, 34);
setcell(gld, 1, 2, wall);
setcell(gld, 2, 3, wall);
setcell(gld, 3, 1, wall); setcell(gld, 3, 2, wall); setcell(gld, 3, 3, wall);
text(gldL, (w*0.78, cy+180*u), "Glider — spaceship"); size(gldL, 20*u); color(gldL, cyan);

// Pre-simulate 8 generations of each (build time), same count so they replay in sync.
evolve(blk, "life"); evolve(blk, "life"); evolve(blk, "life"); evolve(blk, "life");
evolve(blk, "life"); evolve(blk, "life"); evolve(blk, "life"); evolve(blk, "life");
evolve(bln, "life"); evolve(bln, "life"); evolve(bln, "life"); evolve(bln, "life");
evolve(bln, "life"); evolve(bln, "life"); evolve(bln, "life"); evolve(bln, "life");
evolve(gld, "life"); evolve(gld, "life"); evolve(gld, "life"); evolve(gld, "life");
evolve(gld, "life"); evolve(gld, "life"); evolve(gld, "life"); evolve(gld, "life");

// Replay all three at once — the whole zoo, self-animating.
par {
  run(blk, 8, 5.0);
  run(bln, 8, 5.0);
  run(gld, 8, 5.0);
}
wait(0.6);