Automata
Build a visible evolving pattern first, then tune it. Treat an Automata scene as four layers:
- A rule chosen for the desired visual behavior.
- The rule's own seed strategy.
- Grid scale, simulation rate, palette, and camera.
- Realtime parameters and restrained interaction.
Start with a working scene
Use gridForCanvas, initialize before mutating state, and prefer reset() over generic randomization. This inline example shows only the minimal lifecycle; for responsive sizing, controls, interaction, and cleanup, start from the bundled Vite app described below:
import {
Engine,
ReactionDiffusion,
gridForCanvas,
} from "@cazala/automata";
const canvas = document.querySelector("canvas");
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error("Missing canvas element");
}
const automaton = new ReactionDiffusion();
automaton.applyPreset("mitosis");
const engine = new Engine({
canvas,
automaton,
grid: {
...gridForCanvas(canvas.clientWidth, canvas.clientHeight, {
cellSize: 1,
maxCells: 1536,
}),
wrap: true,
maxCells: 1536,
},
stepsPerSecond: ReactionDiffusion.recommendedStepsPerSecond,
render: {
colorOn: { r: 0.96, g: 0.78, b: 0.45, a: 1 },
colorOff: { r: 0.035, g: 0.04, b: 0.07, a: 1 },
colorBg: { r: 0.015, g: 0.018, b: 0.03, a: 1 },
},
onError: console.error,
});
await engine.initialize();
engine.coverGrid();
engine.reset({ mode: "random", density: 0.2 });
const stopAutoResize = engine.autoResize();
engine.play();
window.addEventListener("beforeunload", () => {
stopAutoResize();
engine.destroy();
}, { once: true });
Copy the full Vite starter when building a new app. It includes six selectable scenes, responsive sizing, zoom, rule-aware pointer interaction, WebGPU error handling, and cleanup. Read its tested scene source when adapting a recipe.
Choose a rule by visual intent
| Intent |
Start with |
| Worms, mosaics, alien textures |
Neural; use a named preset and its returned seed options |
| Trained growth, persistence, and regeneration |
GrowingNeural; load a versioned trainer artifact |
| Coral, spots, waves, organic textures |
ReactionDiffusion; choose a verified preset |
| Soft continuous organisms |
Lenia; keep its tuned seed and low step rate |
| Competing colored domains |
Pokemon; preserve its Voronoi seed |
| Conway or life-like binary patterns |
Life; convert a preset's counts with countsToMask |
| Wide-neighborhood growth or refractory trails |
LargerThanLife; start from a named preset |
| Fractal row-by-row history |
Elementary with a rule from Elementary.PRESETS |
| Electric glider storms |
BriansBrain |
| Rotating rainbow spirals |
Cyclic |
| A new local rule |
createAutomaton; subclass Automaton for structural state or storages |
Use the smallest rule and grid that express the idea. Do not imitate an effect by bypassing the automaton's seeding or render hints.
Work creatively
- Describe the desired morphology, motion, palette, scale, and interaction in one sentence.
- Select the closest built-in rule before writing custom WGSL.
- Use the rule's
seed() through engine.reset(...).
- Establish grid scale and
recommendedStepsPerSecond.
- Tune one or two realtime parameters while watching several hundred generations.
- Add palette, zoom, and interaction after the dynamics are legible.
- Inspect startup, early evolution, and settled behavior. Fix dead, saturated, flickering, or featureless states before increasing grid size.
Read creative-workflow.md before inventing or substantially tuning a scene. Read recipes.md for compositions based on built-in rules.
Preserve rule semantics
- Call
engine.reset(seedOptions) to use the active automaton's specialized seed.
- Keep
GrowingNeural artifacts intact: their perception order, ReLU, fire rate, and pre/post life mask are model semantics.
- Treat Gray-Scott's idle state as
[1, 0]; filling it with [0, 0] creates inert cells.
- Use preset-specific seed options:
Neural.applyPreset(name) returns them, while ReactionDiffusion.applyPreset(name) only changes parameters.
- Update declared values with
automaton.set(...) or typed setters; they are clamped realtime uniform writes.
- Treat channel count, neural mode/hidden size, Lenia radius, and Larger-than-Life radius as structural changes. Do not animate them per frame.
- Preserve automaton render hints unless intentionally overriding
colorMode.
Preserve WebGPU performance
- Provide a CSS or static fallback. Automata has no CPU runtime.
- Size the grid with
gridForCanvas; cost scales with width × height × channels.
- Increase
cellSize to reduce grid dimensions before weakening the rule.
- Treat
getCells() as a full GPU-to-CPU readback. Never call it in animation, pointer-move, or render loops.
- Keep Lenia's radius modest; its neighborhood work scales approximately with the square of the diameter.
- Keep Larger-than-Life radii modest too; every cell reads
(2R + 1)² - 1 neighbors per step.
- Use
ensureGridCovers() after programmatic zoom or pan, and set a deliberate maxCells ceiling.
- Use the rule's recommended simulation rate as a starting point; simulation steps are decoupled from display FPS.
Load the right detail
- Read api.md for lifecycle, grid, state, view, built-ins, parameters, and interaction.
- Read creative-workflow.md before designing or substantially tuning a visual.
- Read recipes.md when adapting a known pattern.
- Read custom-rules.md before authoring WGSL or subclassing
Automaton.
- Read troubleshooting.md when output is blank, frozen, unstable, slow, or visually weak.
- Read the repository
docs/architecture.md only when changing Automata internals from a full checkout.
Validate the result
- Compile the implementation; do not guess class names, preset names, parameter keys, or channel layouts.
- Run it in a WebGPU-capable browser and surface
EngineOptions.onError.
- Confirm the canvas has non-zero CSS dimensions and the grid covers the view.
- Watch enough generations for the rule's characteristic behavior to emerge.
- Test resize, zoom, pointer behavior, and the no-WebGPU fallback.
- Dispose
autoResize() observers and call engine.destroy() during teardown.
- Visually inspect the output. A creative task must produce coherent evolution, not merely valid code.
1---2name: automata3description: Build and tune real-time cellular automata, generative textures, artificial-life scenes, and custom WGSL rules with @cazala/automata. Use when embedding Automata in web apps; selecting or configuring Neural, GrowingNeural, ReactionDiffusion, Lenia, Pokemon, Life, Elementary, BriansBrain, or Cyclic; designing seeds, palettes, camera controls, and interaction; translating playground settings into code; debugging WebGPU output; optimizing grid performance; or authoring custom Automaton rules.4---56# Automata78Build a visible evolving pattern first, then tune it. Treat an Automata scene as four layers:9101. A rule chosen for the desired visual behavior.112. The rule's own seed strategy.123. Grid scale, simulation rate, palette, and camera.134. Realtime parameters and restrained interaction.1415## Start with a working scene1617Use `gridForCanvas`, initialize before mutating state, and prefer `reset()` over generic randomization. This inline example shows only the minimal lifecycle; for responsive sizing, controls, interaction, and cleanup, start from the bundled Vite app described below:1819```ts20import {21 Engine,22 ReactionDiffusion,23 gridForCanvas,24} from "@cazala/automata";2526const canvas = document.querySelector("canvas");27if (!(canvas instanceof HTMLCanvasElement)) {28 throw new Error("Missing canvas element");29}30const automaton = new ReactionDiffusion();31automaton.applyPreset("mitosis");3233const engine = new Engine({34 canvas,35 automaton,36 grid: {37 ...gridForCanvas(canvas.clientWidth, canvas.clientHeight, {38 cellSize: 1,39 maxCells: 1536,40 }),41 wrap: true,42 maxCells: 1536,43 },44 stepsPerSecond: ReactionDiffusion.recommendedStepsPerSecond,45 render: {46 colorOn: { r: 0.96, g: 0.78, b: 0.45, a: 1 },47 colorOff: { r: 0.035, g: 0.04, b: 0.07, a: 1 },48 colorBg: { r: 0.015, g: 0.018, b: 0.03, a: 1 },49 },50 onError: console.error,51});5253await engine.initialize();54engine.coverGrid();55engine.reset({ mode: "random", density: 0.2 });56const stopAutoResize = engine.autoResize();57engine.play();5859window.addEventListener("beforeunload", () => {60 stopAutoResize();61 engine.destroy();62}, { once: true });63```6465Copy [the full Vite starter](assets/starter/) when building a new app. It includes six selectable scenes, responsive sizing, zoom, rule-aware pointer interaction, WebGPU error handling, and cleanup. Read its [tested scene source](assets/starter/src/scenes.ts) when adapting a recipe.6667## Choose a rule by visual intent6869| Intent | Start with |70| --- | --- |71| Worms, mosaics, alien textures | `Neural`; use a named preset and its returned seed options |72| Trained growth, persistence, and regeneration | `GrowingNeural`; load a versioned trainer artifact |73| Coral, spots, waves, organic textures | `ReactionDiffusion`; choose a verified preset |74| Soft continuous organisms | `Lenia`; keep its tuned seed and low step rate |75| Competing colored domains | `Pokemon`; preserve its Voronoi seed |76| Conway or life-like binary patterns | `Life`; convert a preset's counts with `countsToMask` |77| Wide-neighborhood growth or refractory trails | `LargerThanLife`; start from a named preset |78| Fractal row-by-row history | `Elementary` with a rule from `Elementary.PRESETS` |79| Electric glider storms | `BriansBrain` |80| Rotating rainbow spirals | `Cyclic` |81| A new local rule | `createAutomaton`; subclass `Automaton` for structural state or storages |8283Use the smallest rule and grid that express the idea. Do not imitate an effect by bypassing the automaton's seeding or render hints.8485## Work creatively86871. Describe the desired morphology, motion, palette, scale, and interaction in one sentence.882. Select the closest built-in rule before writing custom WGSL.893. Use the rule's `seed()` through `engine.reset(...)`.904. Establish grid scale and `recommendedStepsPerSecond`.915. Tune one or two realtime parameters while watching several hundred generations.926. Add palette, zoom, and interaction after the dynamics are legible.937. Inspect startup, early evolution, and settled behavior. Fix dead, saturated, flickering, or featureless states before increasing grid size.9495Read [creative-workflow.md](references/creative-workflow.md) before inventing or substantially tuning a scene. Read [recipes.md](references/recipes.md) for compositions based on built-in rules.9697## Preserve rule semantics9899- Call `engine.reset(seedOptions)` to use the active automaton's specialized seed.100- Keep `GrowingNeural` artifacts intact: their perception order, ReLU, fire rate, and pre/post life mask are model semantics.101- Treat Gray-Scott's idle state as `[1, 0]`; filling it with `[0, 0]` creates inert cells.102- Use preset-specific seed options: `Neural.applyPreset(name)` returns them, while `ReactionDiffusion.applyPreset(name)` only changes parameters.103- Update declared values with `automaton.set(...)` or typed setters; they are clamped realtime uniform writes.104- Treat channel count, neural mode/hidden size, Lenia radius, and Larger-than-Life radius as structural changes. Do not animate them per frame.105- Preserve automaton render hints unless intentionally overriding `colorMode`.106107## Preserve WebGPU performance108109- Provide a CSS or static fallback. Automata has no CPU runtime.110- Size the grid with `gridForCanvas`; cost scales with `width × height × channels`.111- Increase `cellSize` to reduce grid dimensions before weakening the rule.112- Treat `getCells()` as a full GPU-to-CPU readback. Never call it in animation, pointer-move, or render loops.113- Keep Lenia's radius modest; its neighborhood work scales approximately with the square of the diameter.114- Keep Larger-than-Life radii modest too; every cell reads `(2R + 1)² - 1` neighbors per step.115- Use `ensureGridCovers()` after programmatic zoom or pan, and set a deliberate `maxCells` ceiling.116- Use the rule's recommended simulation rate as a starting point; simulation steps are decoupled from display FPS.117118## Load the right detail119120- Read [api.md](references/api.md) for lifecycle, grid, state, view, built-ins, parameters, and interaction.121- Read [creative-workflow.md](references/creative-workflow.md) before designing or substantially tuning a visual.122- Read [recipes.md](references/recipes.md) when adapting a known pattern.123- Read [custom-rules.md](references/custom-rules.md) before authoring WGSL or subclassing `Automaton`.124- Read [troubleshooting.md](references/troubleshooting.md) when output is blank, frozen, unstable, slow, or visually weak.125- Read the repository `docs/architecture.md` only when changing Automata internals from a full checkout.126127## Validate the result128129- Compile the implementation; do not guess class names, preset names, parameter keys, or channel layouts.130- Run it in a WebGPU-capable browser and surface `EngineOptions.onError`.131- Confirm the canvas has non-zero CSS dimensions and the grid covers the view.132- Watch enough generations for the rule's characteristic behavior to emerge.133- Test resize, zoom, pointer behavior, and the no-WebGPU fallback.134- Dispose `autoResize()` observers and call `engine.destroy()` during teardown.135- Visually inspect the output. A creative task must produce coherent evolution, not merely valid code.