hayao.js

A deterministic, AI-first 2D game engine

A headless-native simulation kernel for JavaScript/TypeScript with a Godot-style scene tree, pluggable renderers (SVG / Canvas / headless), and a built-in verification harness — so a game can be authored, tested, and proven correct entirely in Node, without ever opening a browser.

install

Getting started

npm install hayao

MIT-licensed, TypeScript-first. Everything is one package behind a single barrel — the whole public surface (440 exports) is greppable in one API digest.

the idea

The game is a pure function of its inputs

state₀ ──step(inputs₀)──▶ state₁ ──step(inputs₁)──▶ state₂ ──▶ …

Rendering, audio, and the browser are observer plugins: they watch that function and paint what it produces, but can never change its result. All randomness flows through a seeded world.rng; the fixed-tick clock is injected; iteration order is stable. Hold that invariant and the hard problems collapse:

  • Does my game work?world.step() runs in Node. Assert on state.
  • Is this level winnable?step() is a pure transition, so a solver proves it by search.
  • Did my refactor change behavior? — replay recorded inputs, compare world.hash().
  • Undo, replay, time-travel?world.snapshot() / restore(), or replay the input log. Free.
quickstart

Define a game, step it headlessly

A game is a data definition: dimensions, an input map, and a build() that constructs the initial scene tree. createWorld() turns it into a live deterministic world — used identically by the browser driver, the headless runner, and every test.

import { defineGame, createWorld, Node, Sprite, Text } from 'hayao';

const game = defineGame({
  title: 'my-game',
  seed: 7,
  inputMap: { left: ['ArrowLeft'], right: ['ArrowRight'] },
  build(world) {
    const root = new Node({ name: 'root' });
    // …add Sprite, Text, Timer, Camera2D, behaviors…
    return root;
  },
});

const world = createWorld(game);  // no browser needed
world.step(['right']);            // one fixed tick: pure, deterministic
world.probe();                    // structured game state for assertions
world.hash();                     // canonical state hash — replay-stable

In the browser the same definition runs under runBrowser() with an SVG or Canvas renderer; in CI it runs under runHeadless(). The Sokoban example is the reference for every convention.

prove it

Verification is part of the engine

Every example game in the repo ships a verify suite: solver-proven puzzles, bot-beaten levels, golden replay hashes. The same tools are exported for your games:

import { solve, createWorld, checkDeterministic } from 'hayao';

// Machine-prove a level is winnable (search over the pure transition)
const r = solve(myPuzzle, { level: 0, maxDepth: 80 });
console.assert(r.solvable);

// Run the same input log twice, compare every step's hash
const report = checkDeterministic(() => createWorld(game), inputLog);
console.assert(report.ok && report.divergedAt === -1);

See docs/VERIFICATION.md for the full harness: probes, replay, snapshot stability, and filmstrip rendering for judging looks from a headless SVG.

layers

Kernel and observers

layermodulesrole
core/Rng · Clock · EventBus · World · state hashthe kernel (headless, pure)
scene/Node, Node2D, Sprite, Text, Camera2D, Timer, AnimationPlayerthe state
input/action map · per-step sampling · record / replaydeterministic
physics/ procgen/ logic/ net/ persist/rigid-body + kinematic AABB · seeded generators · FSM / graph search · lockstep + rollback netplay · save/loaddeterministic
verify/probes · replay · assertDeterministic · solverthe AI-first harness
render/display list → SVG | Canvas2D | Headless rendererobserver
ui/ audio/ app/DOM overlays · Web Audio bus · runBrowser / runHeadlessobserver shell

core + scene + input + physics + procgen + logic + net + persist run in Node and are deterministic; render + audio + ui + app are the browser-only observer shell. The engine borrows Godot's authoring model — nodes, signals, scenes, input actions, tweens — but keeps every part text, typed, greppable, and headlessly verifiable.

docs

Documentation & examples

  • Architecture — the authoritative design and the determinism contract.
  • API digest — every export from the package, auto-generated.
  • Conventions — how games are structured; definition of done.
  • Verification — how to prove a game correct.
  • Why a custom engine — and when not to use one.
  • hayao.dev — play all 26 machine-verified example games — one per 2D indie genre, plus physics and netplay showcases.