hayao 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -24
- package/bin/create-hayao.mjs +380 -0
- package/bin/hayao-mcp-cli.mjs +11 -0
- package/dist/app/browser.d.ts +65 -4
- package/dist/app/game.d.ts +59 -10
- package/dist/app/tuning.d.ts +68 -0
- package/dist/art/palette.d.ts +41 -0
- package/dist/audio/adaptive.d.ts +58 -0
- package/dist/audio/album.d.ts +16 -0
- package/dist/audio/analysis.d.ts +59 -0
- package/dist/audio/audio.d.ts +39 -1
- package/dist/audio/chord.d.ts +17 -0
- package/dist/audio/genres.d.ts +11 -0
- package/dist/audio/lint.d.ts +29 -0
- package/dist/audio/match.d.ts +38 -0
- package/dist/audio/music.d.ts +88 -0
- package/dist/audio/pcm.d.ts +54 -0
- package/dist/audio/quality.d.ts +28 -0
- package/dist/audio/reverb.d.ts +15 -0
- package/dist/audio/synth.d.ts +63 -0
- package/dist/audio/theory.d.ts +64 -0
- package/dist/audio/zzfx.d.ts +14 -0
- package/dist/content/campaign.d.ts +69 -0
- package/dist/content/generate.d.ts +78 -0
- package/dist/content/level.d.ts +93 -0
- package/dist/content/worldgraph.d.ts +73 -0
- package/dist/core/clock.d.ts +1 -1
- package/dist/core/dmath.d.ts +2 -0
- package/dist/core/projection.d.ts +36 -0
- package/dist/core/rng.d.ts +9 -0
- package/dist/hayao.global.js +200 -0
- package/dist/index.d.ts +39 -1
- package/dist/index.js +6558 -686
- package/dist/index.js.map +4 -4
- package/dist/index.min.js +200 -0
- package/dist/input/actions.d.ts +60 -6
- package/dist/input/gamepad.d.ts +101 -0
- package/dist/input/source.d.ts +133 -1
- package/dist/logic/coroutine.d.ts +68 -0
- package/dist/mcp.js +31225 -0
- package/dist/rasterize-worker-lite.mjs +13 -0
- package/dist/render/canvas.d.ts +6 -5
- package/dist/render/canvas2d-core.d.ts +9 -0
- package/dist/render/commands.d.ts +82 -2
- package/dist/render/paint.d.ts +41 -0
- package/dist/render/renderer.d.ts +47 -0
- package/dist/render/svg.d.ts +5 -1
- package/dist/render/svgString.d.ts +6 -2
- package/dist/render/webgl.d.ts +176 -0
- package/dist/scene/cameraController.d.ts +42 -0
- package/dist/scene/iso.d.ts +73 -0
- package/dist/scene/node.d.ts +98 -6
- package/dist/scene/nodes.d.ts +48 -0
- package/dist/scene/parallax.d.ts +15 -0
- package/dist/scene/particles.d.ts +19 -0
- package/dist/scene/verletChain.d.ts +76 -0
- package/dist/studio/mcpMain.d.ts +1 -0
- package/dist/studio/mcpServer.d.ts +2 -0
- package/dist/studio/record.d.ts +54 -0
- package/dist/studio/run.d.ts +78 -0
- package/dist/studio/session.d.ts +80 -0
- package/dist/studio/timeline.d.ts +35 -0
- package/dist/studio/vitePlugin.d.ts +6 -0
- package/dist/studio-plugin.js +228 -0
- package/dist/ui/overlay.d.ts +6 -0
- package/dist/ui/touch.d.ts +51 -0
- package/dist/verify/audioFilmstrip.d.ts +39 -0
- package/dist/verify/dom.d.ts +26 -0
- package/dist/verify/ethnography.d.ts +67 -0
- package/dist/verify/gates.d.ts +160 -0
- package/dist/verify/layout.d.ts +30 -3
- package/dist/verify/ramp.d.ts +40 -0
- package/dist/world.d.ts +109 -8
- package/dist-studio/assets/index-C7tty_Wo.js +109 -0
- package/dist-studio/assets/index-CM3tjRQo.css +1 -0
- package/dist-studio/index.html +18 -0
- package/docs/API.md +300 -23
- package/docs/CONVENTIONS.md +511 -0
- package/docs/EMBED.md +90 -0
- package/docs/QUICKSTART.md +141 -0
- package/docs/STUDIO.md +97 -0
- package/docs/VERIFICATION.md +256 -0
- package/package.json +40 -6
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/core/dmath.ts", "../src/core/math.ts", "../src/core/rng.ts", "../src/core/clock.ts", "../src/core/events.ts", "../src/core/hash.ts", "../src/scene/node.ts", "../src/scene/nodes.ts", "../src/scene/pool.ts", "../src/scene/tween.ts", "../src/scene/particles.ts", "../src/scene/floatingText.ts", "../src/scene/registry.ts", "../src/input/actions.ts", "../src/input/source.ts", "../src/physics/tilemap.ts", "../src/physics/aabb.ts", "../src/physics/platformer.ts", "../src/physics/spatialHash.ts", "../src/physics/raycast.ts", "../src/physics/rigidBody.ts", "../src/physics/rigidCollide.ts", "../src/physics/rigidJoints.ts", "../src/physics/rigidStep.ts", "../src/physics/rigidQueries.ts", "../src/render/commands.ts", "../src/render/svgString.ts", "../src/render/svg.ts", "../src/render/canvas.ts", "../src/render/headless.ts", "../src/render/nineSlice.ts", "../src/art/palette.ts", "../src/art/shapes.ts", "../src/art/texture.ts", "../src/art/font5.ts", "../src/art/bitmapFont.ts", "../src/art/autotile.ts", "../src/procgen/grid.ts", "../src/procgen/scatter.ts", "../src/procgen/cave.ts", "../src/procgen/terrain.ts", "../src/procgen/rooms.ts", "../src/audio/audio.ts", "../src/ui/overlay.ts", "../src/ui/settings.ts", "../src/ui/shell.ts", "../src/ui/transition.ts", "../src/verify/solver.ts", "../src/verify/determinism.ts", "../src/verify/playthrough.ts", "../src/verify/capture.ts", "../src/verify/driver.ts", "../src/verify/bot.ts", "../src/verify/layout.ts", "../src/verify/feel.ts", "../src/verify/filmstrip.ts", "../src/logic/fsm.ts", "../src/logic/random.ts", "../src/logic/graph.ts", "../src/logic/history.ts", "../src/persist/storage.ts", "../src/persist/codec.ts", "../src/persist/save.ts", "../src/content/dsl.ts", "../src/net/players.ts", "../src/net/protocol.ts", "../src/net/transport.ts", "../src/net/inputBuffer.ts", "../src/net/lockstep.ts", "../src/net/rollback.ts", "../src/net/room.ts", "../src/
|
|
4
|
-
"sourcesContent": ["// Deterministic transcendental math. JavaScript guarantees bit-exact results\n// across engines for +, -, *, /, Math.sqrt (IEEE-754 correctly rounded) \u2014 but\n// NOT for Math.sin/cos/atan2/pow/hypot/exp, which are implementation-defined\n// and may differ between V8, JSC, and SpiderMonkey. A cross-machine lockstep\n// game that touches them can desync even with identical input logs.\n//\n// These replacements are built from exactly-rounded ops only (fdlibm-style\n// polynomial kernels), so every engine computes bit-identical values. Sim code\n// MUST use these instead of the Math.* originals (enforced by\n// `npm run invariants`). Accuracy \u2248 1 ulp on game-scale inputs.\n\n// \u2500\u2500 argument reduction constants (\u03C0/2 split for Cody-Waite reduction) \u2500\u2500\nconst INV_PIO2 = 6.36619772367581382433e-1; // 2/\u03C0\nconst PIO2_HI = 1.57079632673412561417e0; // first 33 bits of \u03C0/2\nconst PIO2_LO = 6.07710050650619224932e-11; // \u03C0/2 \u2212 PIO2_HI\n\n// fdlibm kernel coefficients for sin/cos on |r| \u2264 \u03C0/4.\nconst S1 = -1.66666666666666324348e-1;\nconst S2 = 8.33333333332248946124e-3;\nconst S3 = -1.98412698298579493134e-4;\nconst S4 = 2.75573137070700676789e-6;\nconst S5 = -2.50507602534068634195e-8;\nconst S6 = 1.58969099521155010221e-10;\n\nconst C1 = 4.16666666666666019037e-2;\nconst C2 = -1.38888888888741095749e-3;\nconst C3 = 2.48015872894767294178e-5;\nconst C4 = -2.75573143513906633035e-7;\nconst C5 = 2.08757232129817482790e-9;\nconst C6 = -1.13596475577881948265e-11;\n\nfunction kSin(r: number): number {\n const z = r * r;\n return r + r * z * (S1 + z * (S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)))));\n}\n\nfunction kCos(r: number): number {\n const z = r * r;\n return 1 - 0.5 * z + z * z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));\n}\n\n/** Reduce x to r \u2208 [\u2212\u03C0/4, \u03C0/4] and quadrant n. Accurate for |x| \u2272 1e7 (plenty for game angles). */\nfunction reduce(x: number): { n: number; r: number } {\n const n = Math.round(x * INV_PIO2);\n const r = x - n * PIO2_HI - n * PIO2_LO;\n return { n: ((n % 4) + 4) % 4, r };\n}\n\n/** Deterministic sine (bit-identical on every JS engine). */\nexport function dsin(x: number): number {\n if (!Number.isFinite(x)) return NaN;\n const { n, r } = reduce(x);\n switch (n) {\n case 0:\n return kSin(r);\n case 1:\n return kCos(r);\n case 2:\n return -kSin(r);\n default:\n return -kCos(r);\n }\n}\n\n/** Deterministic cosine (bit-identical on every JS engine). */\nexport function dcos(x: number): number {\n if (!Number.isFinite(x)) return NaN;\n const { n, r } = reduce(x);\n switch (n) {\n case 0:\n return kCos(r);\n case 1:\n return -kSin(r);\n case 2:\n return -kCos(r);\n default:\n return kSin(r);\n }\n}\n\n// \u2500\u2500 atan / atan2 (fdlibm port) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ATAN_HI = [4.63647609000806093515e-1, 7.85398163397448278999e-1, 9.82793723247329054082e-1, 1.570796326794896558e0];\nconst ATAN_LO = [2.26987774529616870924e-17, 3.06161699786838301793e-17, 1.39033110312309984516e-17, 6.12323399573676603587e-17];\nconst AT = [\n 3.33333333333329318027e-1, -1.99999999998764832476e-1, 1.42857142725034663711e-1, -1.1111110405462355788e-1,\n 9.09088713343650656196e-2, -7.69187620504482999495e-2, 6.66107313738753120669e-2, -5.83357013379057348645e-2,\n 4.97687799461593236017e-2, -3.6531572744216915527e-2, 1.62858201153657823623e-2,\n];\n\n/** Deterministic arctangent. */\nexport function datan(x: number): number {\n if (Number.isNaN(x)) return NaN;\n if (!Number.isFinite(x)) return x > 0 ? ATAN_HI[3] : -ATAN_HI[3];\n const sign = x < 0 || Object.is(x, -0) ? -1 : 1;\n let ax = Math.abs(x);\n if (ax >= 1e19) return sign * (ATAN_HI[3] + ATAN_LO[3]);\n\n let id = -1;\n if (ax < 0.4375) {\n if (ax < 1e-9) return x; // tiny: atan(x) \u2248 x\n } else if (ax < 0.6875) {\n id = 0;\n ax = (2 * ax - 1) / (2 + ax);\n } else if (ax < 1.1875) {\n id = 1;\n ax = (ax - 1) / (ax + 1);\n } else if (ax < 2.4375) {\n id = 2;\n ax = (ax - 1.5) / (1 + 1.5 * ax);\n } else {\n id = 3;\n ax = -1 / ax;\n }\n\n const z = ax * ax;\n const w = z * z;\n const s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10])))));\n const s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9]))));\n if (id < 0) return sign * (ax - ax * (s1 + s2));\n const r = ATAN_HI[id] - (ax * (s1 + s2) - ATAN_LO[id] - ax);\n return sign * r;\n}\n\nconst PI = 3.141592653589793;\n\n/** Deterministic atan2(y, x) with standard quadrant conventions. */\nexport function datan2(y: number, x: number): number {\n if (Number.isNaN(x) || Number.isNaN(y)) return NaN;\n if (y === 0 && x === 0) return Object.is(x, -0) ? (Object.is(y, -0) ? -PI : PI) : Object.is(y, -0) ? -0 : 0;\n if (x === 0 || (!Number.isFinite(y) && Number.isFinite(x))) return y > 0 ? PI / 2 : -PI / 2;\n if (!Number.isFinite(x)) {\n if (!Number.isFinite(y)) {\n const q = x > 0 ? PI / 4 : (3 * PI) / 4;\n return y > 0 ? q : -q;\n }\n return x > 0 ? (y < 0 || Object.is(y, -0) ? -0 : 0) : y < 0 || Object.is(y, -0) ? -PI : PI;\n }\n const a = datan(y / x);\n if (x > 0) return a;\n return y < 0 || Object.is(y, -0) ? a - PI : a + PI;\n}\n\n// \u2500\u2500 exp2 (for easing curves and decay) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst LN2 = 6.93147180559945286227e-1;\n\n/** Deterministic 2^x via Taylor series on the reduced argument. */\nexport function dexp2(x: number): number {\n if (Number.isNaN(x)) return NaN;\n if (x >= 1024) return Infinity;\n if (x <= -1075) return 0;\n const k = Math.round(x);\n const y = (x - k) * LN2; // |y| \u2264 ln2/2 \u2248 0.347\n let term = 1;\n let sum = 1;\n for (let i = 1; i <= 13; i++) {\n term = (term * y) / i;\n sum += term;\n }\n return sum * 2 ** k; // 2^integer is exact in every engine\n}\n\n/** Deterministic natural exponential e\u02E3. Routes through dexp2 (e\u02E3 = 2^(x/ln2)). */\nexport function dexp(x: number): number {\n return dexp2(x * INV_LN2);\n}\n\n/** Deterministic hypotenuse: sqrt is IEEE-correctly-rounded, hypot is not. */\nexport function dhypot(x: number, y: number): number {\n return Math.sqrt(x * x + y * y);\n}\n\n// \u2500\u2500 logarithms \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Decompose x = m\u00B72^e with the exponent read straight from the float bits\n// (bit-exact everywhere), then ln(m) on m \u2208 [\u221A\u00BD\u00B72, \u221A2) via the atanh series\n// ln(m) = 2\u00B7atanh((m\u22121)/(m+1)) \u2014 only exactly-rounded ops.\nconst logView = new DataView(new ArrayBuffer(8));\nconst LN2_HI = 6.93147180369123816490e-1;\nconst LN2_LO = 1.90821492927058770002e-10;\n\n/** Deterministic natural logarithm. */\nexport function dlog(x: number): number {\n if (Number.isNaN(x) || x < 0) return NaN;\n if (x === 0) return -Infinity;\n if (!Number.isFinite(x)) return Infinity;\n logView.setFloat64(0, x);\n let e = ((logView.getUint32(0) >>> 20) & 0x7ff) - 1023;\n if (e === -1023) {\n // subnormal: scale up by 2^54 (exact) and correct the exponent\n logView.setFloat64(0, x * 18014398509481984);\n e = ((logView.getUint32(0) >>> 20) & 0x7ff) - 1023 - 54;\n }\n // mantissa m \u2208 [1, 2); shift to [\u221A\u00BD\u00B72, \u221A2) so |s| stays small\n logView.setUint32(0, (logView.getUint32(0) & 0xfffff) | (1023 << 20));\n let m = logView.getFloat64(0);\n if (m > 1.4142135623730951) {\n m *= 0.5;\n e += 1;\n }\n const s = (m - 1) / (m + 1);\n const z = s * s;\n // 2\u00B7atanh(s) = 2s\u00B7(1 + z/3 + z\u00B2/5 + \u2026) \u2014 terms through z\u2079/19 keep the\n // truncation below 1 ulp for |s| \u2264 0.172\n const p =\n 1 +\n z *\n (0.3333333333333333 +\n z *\n (0.2 +\n z *\n (0.14285714285714285 +\n z *\n (0.1111111111111111 +\n z *\n (0.09090909090909091 +\n z * (0.07692307692307693 + z * (0.06666666666666667 + z * (0.058823529411764705 + z * 0.05263157894736842))))))));\n return e * LN2_HI + (2 * s * p + e * LN2_LO);\n}\n\nconst INV_LN10 = 4.34294481903251816668e-1; // 1/ln(10)\nconst INV_LN2 = 1.44269504088896338700e0; // 1/ln(2)\n\n/** Deterministic base-10 logarithm. */\nexport const dlog10 = (x: number): number => dlog(x) * INV_LN10;\n/** Deterministic base-2 logarithm. */\nexport const dlog2 = (x: number): number => dlog(x) * INV_LN2;\n", "// Deterministic 2D math. Plain data + pure functions (no classes with hidden\n// state) so everything serializes and hashes cleanly. Trig/hypot route through\n// dmath so results are bit-identical across JS engines (netplay-safe).\n\nimport { dcos, dhypot, dsin } from './dmath';\n\nexport interface Vec2 {\n x: number;\n y: number;\n}\n\nexport const vec2 = (x = 0, y = 0): Vec2 => ({ x, y });\nexport const vadd = (a: Vec2, b: Vec2): Vec2 => ({ x: a.x + b.x, y: a.y + b.y });\nexport const vsub = (a: Vec2, b: Vec2): Vec2 => ({ x: a.x - b.x, y: a.y - b.y });\nexport const vscale = (a: Vec2, s: number): Vec2 => ({ x: a.x * s, y: a.y * s });\nexport const vdot = (a: Vec2, b: Vec2): number => a.x * b.x + a.y * b.y;\nexport const vlen = (a: Vec2): number => dhypot(a.x, a.y);\nexport const vdist = (a: Vec2, b: Vec2): number => dhypot(a.x - b.x, a.y - b.y);\nexport function vnorm(a: Vec2): Vec2 {\n const l = vlen(a);\n return l === 0 ? { x: 0, y: 0 } : { x: a.x / l, y: a.y / l };\n}\n\nexport const clamp = (v: number, lo: number, hi: number): number => (v < lo ? lo : v > hi ? hi : v);\nexport const lerp = (a: number, b: number, t: number): number => a + (b - a) * t;\nexport const invLerp = (a: number, b: number, v: number): number => (a === b ? 0 : (v - a) / (b - a));\nexport const remap = (v: number, a0: number, a1: number, b0: number, b1: number): number =>\n lerp(b0, b1, invLerp(a0, a1, v));\n\n/** Hermite smoothstep: 0 below `edge0`, 1 above `edge1`, eased in between. */\nexport const smoothstep = (edge0: number, edge1: number, v: number): number => {\n const t = clamp(edge0 === edge1 ? (v < edge0 ? 0 : 1) : invLerp(edge0, edge1, v), 0, 1);\n return t * t * (3 - 2 * t);\n};\n\nexport const TAU = Math.PI * 2;\nexport const deg2rad = (d: number): number => (d * Math.PI) / 180;\nexport const rad2deg = (r: number): number => (r * 180) / Math.PI;\n\n/** Axis-aligned rectangle. */\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport function rectContains(r: Rect, p: Vec2): boolean {\n return p.x >= r.x && p.x <= r.x + r.w && p.y >= r.y && p.y <= r.y + r.h;\n}\n\nexport function rectsOverlap(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\n/** 2D affine transform as a 6-value matrix [a b c d e f] (like SVG/Canvas). */\nexport interface Transform {\n a: number;\n b: number;\n c: number;\n d: number;\n e: number;\n f: number;\n}\n\nexport const IDENTITY: Transform = { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };\n\nexport function composeTransform(m: Transform, n: Transform): Transform {\n return {\n a: m.a * n.a + m.c * n.b,\n b: m.b * n.a + m.d * n.b,\n c: m.a * n.c + m.c * n.d,\n d: m.b * n.c + m.d * n.d,\n e: m.a * n.e + m.c * n.f + m.e,\n f: m.b * n.e + m.d * n.f + m.f,\n };\n}\n\n/** Build a transform from position, rotation (radians), scale. */\nexport function makeTransform(pos: Vec2, rotation: number, scale: Vec2): Transform {\n const cos = dcos(rotation);\n const sin = dsin(rotation);\n return {\n a: cos * scale.x,\n b: sin * scale.x,\n c: -sin * scale.y,\n d: cos * scale.y,\n e: pos.x,\n f: pos.y,\n };\n}\n\nexport function applyTransform(m: Transform, p: Vec2): Vec2 {\n return { x: m.a * p.x + m.c * p.y + m.e, y: m.b * p.x + m.d * p.y + m.f };\n}\n\n/** Invert an affine transform (returns identity if singular). */\nexport function invertTransform(m: Transform): Transform {\n const det = m.a * m.d - m.b * m.c;\n if (det === 0) return { ...IDENTITY };\n const id = 1 / det;\n return {\n a: m.d * id,\n b: -m.b * id,\n c: -m.c * id,\n d: m.a * id,\n e: (m.c * m.f - m.d * m.e) * id,\n f: (m.b * m.e - m.a * m.f) * id,\n };\n}\n", "// Deterministic, seedable, splittable RNG. SplitMix64 for seeding, xoshiro128**\n// for the stream \u2014 fast, good distribution, trivially reproducible.\n// Every random draw in a game MUST flow through here (never Math.random()).\n\nfunction splitmix32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x9e3779b9) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 16), 0x21f0aaad);\n t = Math.imul(t ^ (t >>> 15), 0x735a2d97);\n return (t ^ (t >>> 15)) >>> 0;\n };\n}\n\nexport interface RngState {\n s: [number, number, number, number];\n}\n\nexport class Rng {\n private s0: number;\n private s1: number;\n private s2: number;\n private s3: number;\n\n constructor(seed: number | RngState = 0) {\n if (typeof seed === 'number') {\n const sm = splitmix32(seed === 0 ? 0x1234abcd : seed);\n this.s0 = sm();\n this.s1 = sm();\n this.s2 = sm();\n this.s3 = sm();\n } else {\n [this.s0, this.s1, this.s2, this.s3] = seed.s;\n }\n }\n\n /** Raw 32-bit unsigned integer. */\n private next(): number {\n const result = (Math.imul(this.rotl(Math.imul(this.s1, 5), 7), 9) >>> 0);\n const t = (this.s1 << 9) >>> 0;\n this.s2 ^= this.s0;\n this.s3 ^= this.s1;\n this.s1 ^= this.s2;\n this.s0 ^= this.s3;\n this.s2 = (this.s2 ^ t) >>> 0;\n this.s3 = this.rotl(this.s3, 11);\n return result >>> 0;\n }\n\n private rotl(x: number, k: number): number {\n return (((x << k) | (x >>> (32 - k))) >>> 0);\n }\n\n /** Float in [0, 1). */\n float(): number {\n return this.next() / 4294967296;\n }\n\n /** Float in [lo, hi). */\n range(lo: number, hi: number): number {\n return lo + this.float() * (hi - lo);\n }\n\n /** Integer in [0, n). */\n int(n: number): number {\n return Math.floor(this.float() * n);\n }\n\n /** Integer in [lo, hi] inclusive. */\n intRange(lo: number, hi: number): number {\n return lo + this.int(hi - lo + 1);\n }\n\n /** True with probability p. */\n chance(p: number): boolean {\n return this.float() < p;\n }\n\n /** Uniform element of an array. */\n pick<T>(arr: readonly T[]): T {\n return arr[this.int(arr.length)];\n }\n\n /** In-place Fisher\u2013Yates shuffle (deterministic). */\n shuffle<T>(arr: T[]): T[] {\n for (let i = arr.length - 1; i > 0; i--) {\n const j = this.int(i + 1);\n [arr[i], arr[j]] = [arr[j], arr[i]];\n }\n return arr;\n }\n\n /**\n * Derive an independent child stream. Same parent state + same key always\n * yields the same child \u2014 so subsystems (enemy AI, loot, terrain) get stable,\n * decorrelated randomness without threading one generator through everything.\n */\n split(key = 0): Rng {\n const mix = (this.s0 ^ Math.imul(key + 1, 0x9e3779b9)) >>> 0;\n const child = new Rng(mix ^ this.s3);\n // Advance parent so repeated splits differ.\n this.next();\n return child;\n }\n\n /** Serialize / restore for saves and replay. */\n getState(): RngState {\n return { s: [this.s0, this.s1, this.s2, this.s3] };\n }\n setState(state: RngState): void {\n [this.s0, this.s1, this.s2, this.s3] = state.s;\n }\n}\n\n/** Deterministic 32-bit FNV-1a hash of a string \u2014 handy for stable ids/seeds. */\nexport function hashString(str: string): number {\n let h = 2166136261 >>> 0;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return h >>> 0;\n}\n", "// Fixed-timestep clock. Real elapsed milliseconds go in; whole fixed steps come\n// out. This is what makes the sim frame-rate independent AND exactly reproducible:\n// the same input log always yields the same number of steps.\n\nexport interface ClockConfig {\n /** Simulation rate in Hz (steps per second). Default 60. */\n hz?: number;\n /** Max real ms consumed per advance, to avoid a spiral of death. Default 250. */\n maxFrameMs?: number;\n}\n\nexport class Clock {\n readonly stepMs: number;\n readonly dt: number; // fixed delta in seconds, for game logic\n private maxFrameMs: number;\n private accumulator = 0;\n private _frame = 0;\n private _simTimeMs = 0;\n\n constructor(config: ClockConfig = {}) {\n const hz = config.hz ?? 60;\n this.stepMs = 1000 / hz;\n this.dt = 1 / hz;\n this.maxFrameMs = config.maxFrameMs ?? 250;\n }\n\n /**\n * Feed real elapsed ms; returns how many fixed steps to run now.\n * Caller runs the sim exactly that many times.\n */\n advance(realMs: number): number {\n this.accumulator += Math.min(realMs, this.maxFrameMs);\n let steps = 0;\n while (this.accumulator >= this.stepMs) {\n this.accumulator -= this.stepMs;\n steps++;\n }\n return steps;\n }\n\n /** Called by the World once per executed step to keep counters honest. */\n tick(): void {\n this._frame++;\n this._simTimeMs += this.stepMs;\n }\n\n /** Interpolation alpha in [0,1) for smooth rendering between fixed steps. */\n get alpha(): number {\n return this.accumulator / this.stepMs;\n }\n\n get frame(): number {\n return this._frame;\n }\n get simTimeMs(): number {\n return this._simTimeMs;\n }\n get simTimeSec(): number {\n return this._simTimeMs / 1000;\n }\n\n getState() {\n return { accumulator: this.accumulator, frame: this._frame, simTimeMs: this._simTimeMs };\n }\n setState(s: { accumulator: number; frame: number; simTimeMs: number }): void {\n this.accumulator = s.accumulator;\n this._frame = s.frame;\n this._simTimeMs = s.simTimeMs;\n }\n}\n", "// Synchronous typed signal bus (Godot-style signals). Deterministic: listeners\n// fire in connection order, synchronously, within the current step.\n\nexport type Listener<T> = (payload: T) => void;\n\nexport class Signal<T = void> {\n private listeners: Listener<T>[] = [];\n\n connect(fn: Listener<T>): () => void {\n this.listeners.push(fn);\n return () => this.disconnect(fn);\n }\n\n once(fn: Listener<T>): () => void {\n const off = this.connect((p) => {\n off();\n fn(p);\n });\n return off;\n }\n\n disconnect(fn: Listener<T>): void {\n const i = this.listeners.indexOf(fn);\n if (i >= 0) this.listeners.splice(i, 1);\n }\n\n emit(payload: T): void {\n // Copy so a listener disconnecting mid-emit doesn't skip its neighbor.\n for (const fn of this.listeners.slice()) fn(payload);\n }\n\n get count(): number {\n return this.listeners.length;\n }\n\n clear(): void {\n this.listeners.length = 0;\n }\n}\n\n/**\n * A named event bus for cross-cutting game events, keyed by an event map so\n * payloads are typed. Prefer node-local Signals for local wiring; use the bus\n * for global concerns (score changed, level complete, sound cue).\n */\nexport class EventBus<Events extends Record<string, unknown>> {\n private signals = new Map<keyof Events, Signal<unknown>>();\n\n private signalFor<K extends keyof Events>(key: K): Signal<Events[K]> {\n let s = this.signals.get(key);\n if (!s) {\n s = new Signal<unknown>();\n this.signals.set(key, s);\n }\n return s as unknown as Signal<Events[K]>;\n }\n\n on<K extends keyof Events>(key: K, fn: Listener<Events[K]>): () => void {\n return this.signalFor(key).connect(fn);\n }\n\n once<K extends keyof Events>(key: K, fn: Listener<Events[K]>): () => void {\n return this.signalFor(key).once(fn);\n }\n\n emit<K extends keyof Events>(key: K, payload: Events[K]): void {\n this.signalFor(key).emit(payload);\n }\n\n clear(): void {\n this.signals.clear();\n }\n}\n", "// Deterministic structural hash of any JSON-like value. The spine of replay\n// verification: two runs are identical iff their state hashes match.\n\nfunction canonicalNumber(n: number): string {\n if (Number.isNaN(n)) return 'NaN';\n if (n === Infinity) return 'Inf';\n if (n === -Infinity) return '-Inf';\n if (n === 0) return '0'; // collapse -0 and 0\n return n.toString();\n}\n\n/**\n * Walk a value in a canonical order (object keys sorted) and fold it into a\n * 64-bit-ish FNV-1a hash represented as an 8-char hex string. Stable across runs\n * for structurally identical data.\n */\nexport function hashValue(value: unknown): string {\n let h1 = 2166136261 >>> 0;\n let h2 = 0x811c9dc5 >>> 0;\n const push = (s: string) => {\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n h1 = Math.imul(h1 ^ c, 16777619) >>> 0;\n h2 = Math.imul(h2 ^ ((c << 3) | (c >>> 5)), 2246822519) >>> 0;\n }\n };\n\n const walk = (v: unknown): void => {\n if (v === null) return push('n');\n if (v === undefined) return push('u');\n switch (typeof v) {\n case 'number':\n return push('#' + canonicalNumber(v));\n case 'boolean':\n return push(v ? 't' : 'f');\n case 'string':\n return push('\"' + v);\n case 'object': {\n if (Array.isArray(v)) {\n push('[');\n for (const el of v) walk(el);\n push(']');\n return;\n }\n const obj = v as Record<string, unknown>;\n // Omit undefined-valued keys: JSON has no `undefined`, so `{a: undefined}`\n // and `{}` serialize identically. Counting the key would make hash()\n // disagree with the value after a save/load JSON round-trip (a Sprite's\n // unset paint fields are the canonical case). JSON-stable = the guarantee\n // persistence needs.\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n push('{');\n for (const k of keys) {\n push(k + ':');\n walk(obj[k]);\n }\n push('}');\n return;\n }\n default:\n push('?');\n }\n };\n\n walk(value);\n const hex = (n: number) => n.toString(16).padStart(8, '0');\n return hex(h1) + hex(h2);\n}\n", "// The scene node: a Godot-style tree element with a transform, lifecycle,\n// children, local signals, and attachable behaviors. Updates run in fixed tree\n// order (depth-first, child-index order) which keeps the whole tree deterministic.\n\nimport type { Rng } from '../core/rng';\nimport type { Clock } from '../core/clock';\nimport { Signal } from '../core/events';\nimport {\n IDENTITY,\n composeTransform,\n makeTransform,\n type Transform,\n type Vec2,\n} from '../core/math';\nimport type { DrawCommand } from '../render/commands';\n\n/** What a live node can see of its host world. The World implements this. */\nexport interface WorldContext {\n readonly rng: Rng;\n readonly clock: Clock;\n /** Queue a node to be freed at the end of the current step (safe during iteration). */\n requestFree(node: Node): void;\n /** Seconds elapsed in sim time. */\n readonly time: number;\n}\n\n/** A composable update unit attached to a node (favour over deep inheritance). */\nexport interface Behavior {\n ready?(node: Node): void;\n update?(node: Node, dt: number): void;\n exit?(node: Node): void;\n /** Optional tag for lookup/serialization. */\n readonly kind?: string;\n}\n\nlet __idCounter = 0;\n/** Deterministic id source \u2014 reset by the World on load so ids are reproducible. */\nexport function resetNodeIds(start = 0): void {\n __idCounter = start;\n}\n\nexport interface NodeConfig {\n name?: string;\n pos?: Vec2;\n rotation?: number;\n scale?: Vec2;\n z?: number;\n visible?: boolean;\n}\n\nexport class Node {\n readonly id: string;\n name: string;\n /** Type tag for serialization; subclasses override. */\n readonly type: string = 'Node';\n\n pos: Vec2;\n rotation: number;\n scale: Vec2;\n z: number;\n visible: boolean;\n /**\n * Cosmetic nodes are pure *view* (derived from game state, rebuildable) and are\n * excluded from serialize()/snapshot()/hash(). Mark a container cosmetic when it\n * only renders state that lives elsewhere \u2014 so transient display (move counters,\n * particles, tweened positions) never pollutes the canonical, verifiable state.\n */\n cosmetic = false;\n\n parent: Node | null = null;\n readonly children: Node[] = [];\n world: WorldContext | null = null;\n\n /** Optional inline update without subclassing: node.onUpdate = (n, dt) => {\u2026}. */\n onUpdate?: (node: Node, dt: number) => void;\n\n private behaviors: Behavior[] = [];\n private signals = new Map<string, Signal<unknown>>();\n private _ready = false;\n private _freed = false;\n\n constructor(config: NodeConfig = {}) {\n this.id = `n${__idCounter++}`;\n this.name = config.name ?? this.constructor.name;\n this.pos = config.pos ? { ...config.pos } : { x: 0, y: 0 };\n this.rotation = config.rotation ?? 0;\n this.scale = config.scale ? { ...config.scale } : { x: 1, y: 1 };\n this.z = config.z ?? 0;\n this.visible = config.visible ?? true;\n }\n\n // \u2500\u2500 Tree structure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n addChild<T extends Node>(child: T): T {\n child.parent = this;\n this.children.push(child);\n if (this.world && this._ready) child.enterTree(this.world);\n return child;\n }\n\n removeChild(child: Node): void {\n const i = this.children.indexOf(child);\n if (i >= 0) {\n this.children.splice(i, 1);\n child.parent = null;\n }\n }\n\n /** Deferred free: runs exit hooks and detaches at the end of the step. */\n free(): void {\n this.world?.requestFree(this);\n }\n\n /** Depth-first find by name. */\n find(name: string): Node | null {\n if (this.name === name) return this;\n for (const c of this.children) {\n const r = c.find(name);\n if (r) return r;\n }\n return null;\n }\n\n /** All descendants (and self) of a given type tag. */\n query(type: string, out: Node[] = []): Node[] {\n if (this.type === type) out.push(this);\n for (const c of this.children) c.query(type, out);\n return out;\n }\n\n // \u2500\u2500 Behaviors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n addBehavior(b: Behavior): this {\n this.behaviors.push(b);\n if (this._ready) b.ready?.(this);\n return this;\n }\n\n // \u2500\u2500 Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n signal<T = void>(name: string): Signal<T> {\n let s = this.signals.get(name);\n if (!s) {\n s = new Signal<unknown>();\n this.signals.set(name, s);\n }\n return s as unknown as Signal<T>;\n }\n emit<T>(name: string, payload: T): void {\n this.signals.get(name)?.emit(payload);\n }\n\n // \u2500\u2500 Lifecycle (engine-called) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n enterTree(world: WorldContext): void {\n this.world = world;\n if (!this._ready) {\n this._ready = true;\n this.onReady();\n for (const b of this.behaviors) b.ready?.(this);\n }\n for (const c of this.children) c.enterTree(world);\n }\n\n updateTree(dt: number): void {\n if (this._freed) return;\n for (const b of this.behaviors) b.update?.(this, dt);\n this.onUpdate?.(this, dt);\n this.onProcess(dt);\n // Copy children so structural changes during update are safe.\n for (const c of this.children.slice()) c.updateTree(dt);\n }\n\n exitTree(): void {\n for (const b of this.behaviors) b.exit?.(this);\n this.onExit();\n for (const c of this.children.slice()) c.exitTree();\n this._freed = true;\n }\n\n get isFreed(): boolean {\n return this._freed;\n }\n\n // \u2500\u2500 Transforms \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n localTransform(): Transform {\n return makeTransform(this.pos, this.rotation, this.scale);\n }\n\n worldTransform(): Transform {\n const local = this.localTransform();\n return this.parent ? composeTransform(this.parent.worldTransform(), local) : local;\n }\n\n // \u2500\u2500 Rendering (projection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Walk the subtree, appending draw commands with computed world transforms. */\n collectDraw(out: DrawCommand[], parentWorld: Transform = IDENTITY): void {\n if (!this.visible) return;\n const world = composeTransform(parentWorld, this.localTransform());\n this.draw(out, world);\n for (const c of this.children) c.collectDraw(out, world);\n }\n\n /** Subclasses emit their own commands here. Base draws nothing. */\n protected draw(_out: DrawCommand[], _world: Transform): void {}\n\n // \u2500\u2500 Overridable hooks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n protected onReady(): void {}\n protected onProcess(_dt: number): void {}\n protected onExit(): void {}\n\n // \u2500\u2500 Serialization (data only; behaviors/closures are re-attached by scene code) \u2500\u2500\n serialize(): SerializedNode {\n return {\n type: this.type,\n name: this.name,\n pos: { ...this.pos },\n rotation: this.rotation,\n scale: { ...this.scale },\n z: this.z,\n visible: this.visible,\n props: this.serializeProps(),\n children: this.children.filter((c) => !c.cosmetic).map((c) => c.serialize()),\n };\n }\n /** Subclasses persist their own fields here. */\n protected serializeProps(): Record<string, unknown> {\n return {};\n }\n /** Subclasses restore their own fields here. */\n applyProps(_props: Record<string, unknown>): void {}\n}\n\nexport interface SerializedNode {\n type: string;\n name: string;\n pos: Vec2;\n rotation: number;\n scale: Vec2;\n z: number;\n visible: boolean;\n props: Record<string, unknown>;\n children: SerializedNode[];\n}\n", "// Concrete node types built on Node. Code-as-art: a Sprite is a vector shape or\n// glyph, never a bitmap. Text is a DOM-quality label. Camera2D drives the view.\n// Timer is a deterministic countdown that emits a signal.\n\nimport type { Transform } from '../core/math';\nimport type { DrawCommand, Paint, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig, type WorldContext } from './node';\n\n// \u2500\u2500 Sprite \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport type Shape =\n | { kind: 'rect'; w: number; h: number; r?: number }\n | { kind: 'circle'; radius: number }\n | { kind: 'poly'; points: number[]; closed?: boolean }\n | { kind: 'path'; d: string }\n | { kind: 'glyph'; char: string; size: number };\n\nexport interface SpriteConfig extends NodeConfig, Paint {\n shape: Shape;\n}\n\nexport class Sprite extends Node {\n override readonly type = 'Sprite';\n shape: Shape;\n paint: Paint;\n\n constructor(config: SpriteConfig) {\n super(config);\n this.shape = config.shape;\n this.paint = {\n fill: config.fill,\n stroke: config.stroke,\n strokeWidth: config.strokeWidth,\n opacity: config.opacity,\n round: config.round,\n };\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const p = this.paint;\n const base = { transform: world, z: this.z, ...p };\n switch (this.shape.kind) {\n case 'rect':\n out.push({ kind: 'rect', x: -this.shape.w / 2, y: -this.shape.h / 2, w: this.shape.w, h: this.shape.h, r: this.shape.r, ...base });\n break;\n case 'circle':\n out.push({ kind: 'circle', cx: 0, cy: 0, radius: this.shape.radius, ...base });\n break;\n case 'poly':\n out.push({ kind: 'poly', points: this.shape.points, closed: this.shape.closed ?? true, ...base });\n break;\n case 'path':\n out.push({ kind: 'path', d: this.shape.d, ...base });\n break;\n case 'glyph':\n out.push({ kind: 'text', text: this.shape.char, x: 0, y: 0, size: this.shape.size, align: 'center', ...base });\n break;\n }\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { shape: this.shape, paint: this.paint };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (props.shape) this.shape = props.shape as Shape;\n if (props.paint) this.paint = props.paint as Paint;\n }\n}\n\n// \u2500\u2500 Text \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface TextConfig extends NodeConfig, Paint {\n text: string;\n size?: number;\n font?: string;\n align?: TextAlign;\n weight?: number;\n}\n\nexport class Text extends Node {\n override readonly type = 'Text';\n text: string;\n size: number;\n font?: string;\n align: TextAlign;\n weight?: number;\n paint: Paint;\n\n constructor(config: TextConfig) {\n super(config);\n this.text = config.text;\n this.size = config.size ?? 24;\n this.font = config.font;\n this.align = config.align ?? 'left';\n this.weight = config.weight;\n this.paint = { fill: config.fill ?? '#000', stroke: config.stroke, strokeWidth: config.strokeWidth, opacity: config.opacity };\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n out.push({\n kind: 'text', text: this.text, x: 0, y: 0, size: this.size, font: this.font,\n align: this.align, weight: this.weight, transform: world, z: this.z, ...this.paint,\n });\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { text: this.text, size: this.size, align: this.align, paint: this.paint };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.text === 'string') this.text = props.text;\n if (typeof props.size === 'number') this.size = props.size;\n if (props.align) this.align = props.align as TextAlign;\n if (props.paint) this.paint = props.paint as Paint;\n }\n}\n\n// \u2500\u2500 Camera2D \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface CameraConfig extends NodeConfig {\n zoom?: number;\n /** Make this the active camera on ready. */\n current?: boolean;\n}\n\nexport class Camera2D extends Node {\n override readonly type = 'Camera2D';\n zoom: number;\n current: boolean;\n\n constructor(config: CameraConfig = {}) {\n super(config);\n this.zoom = config.zoom ?? 1;\n this.current = config.current ?? true;\n }\n\n protected override onReady(): void {\n if (this.current) (this.world as WorldContext & { activeCamera?: Camera2D }).activeCamera = this;\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { zoom: this.zoom, current: this.current };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.zoom === 'number') this.zoom = props.zoom;\n if (typeof props.current === 'boolean') this.current = props.current;\n }\n}\n\n// \u2500\u2500 Timer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface TimerConfig extends NodeConfig {\n duration: number; // seconds\n autostart?: boolean;\n oneShot?: boolean;\n}\n\nexport class Timer extends Node {\n override readonly type = 'Timer';\n duration: number;\n oneShot: boolean;\n private remaining: number;\n private running: boolean;\n\n constructor(config: TimerConfig) {\n super(config);\n this.duration = config.duration;\n this.oneShot = config.oneShot ?? true;\n this.remaining = config.duration;\n this.running = config.autostart ?? true;\n }\n\n start(duration?: number): void {\n if (duration !== undefined) this.duration = duration;\n this.remaining = this.duration;\n this.running = true;\n }\n stop(): void {\n this.running = false;\n }\n\n get timeLeft(): number {\n return this.remaining;\n }\n\n protected override onProcess(dt: number): void {\n if (!this.running) return;\n this.remaining -= dt;\n if (this.remaining <= 0) {\n this.emit('timeout', undefined);\n if (this.oneShot) this.running = false;\n else this.remaining += this.duration;\n }\n }\n\n /** Signal emitted when the countdown reaches zero. */\n get timeout() {\n return this.signal('timeout');\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { duration: this.duration, oneShot: this.oneShot, remaining: this.remaining, running: this.running };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.duration === 'number') this.duration = props.duration;\n if (typeof props.oneShot === 'boolean') this.oneShot = props.oneShot;\n if (typeof props.remaining === 'number') this.remaining = props.remaining;\n if (typeof props.running === 'boolean') this.running = props.running;\n }\n}\n", "// Frame-scoped node pool: hide/show instead of create/destroy, for views that\n// redraw a whole entity set every frame (hordes, bullets, tiles, HP bars).\n// Usage per frame: begin() \u2192 get() once per live entity \u2192 end(). Nodes are\n// created on demand, reused in stable order, and surplus nodes are hidden \u2014\n// never removed \u2014 so the scene tree stays allocation-quiet at peak load.\n//\n// Pooled nodes are pure view: parent them to a `cosmetic = true` layer so the\n// pool's grow-only node set never enters world.hash().\n// (Promoted from six near-identical per-game copies \u2014 see docs/LESSONS.md.)\n\nimport type { Node } from './node';\n\nexport class NodePool<T extends Node = Node> {\n private items: T[] = [];\n private used = 0;\n\n constructor(\n private parent: Node,\n private make: () => T,\n ) {}\n\n /** Start a frame: every pooled node is up for reuse. */\n begin(): void {\n this.used = 0;\n }\n\n /** Claim the next node (created and parented on first use), made visible. */\n get(): T {\n if (this.used === this.items.length) this.items.push(this.parent.addChild(this.make()));\n const n = this.items[this.used++];\n n.visible = true;\n return n;\n }\n\n /** End a frame: hide every node not claimed since begin(). */\n end(): void {\n for (let i = this.used; i < this.items.length; i++) this.items[i].visible = false;\n }\n\n /** Nodes claimed this frame (call after the get() loop). */\n get liveCount(): number {\n return this.used;\n }\n}\n", "// Deterministic tweening. Tweens advance by the fixed dt, so animations are\n// exactly reproducible. Tweens animate via setter closures (transient visual\n// polish \u2014 not part of the hashed logic state), Godot AnimationPlayer-style.\n\nimport { clamp, lerp } from '../core/math';\nimport { dcos, dexp, dexp2, dsin } from '../core/dmath';\nimport { Node } from './node';\n\nexport type Easing = (t: number) => number;\n\n// \u2500\u2500 Framerate-independent smoothing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// The naive `x += (target - x) * k` follows a target, but its stiffness scales\n// with frame count: halving dt halves the approach per step. These helpers fold\n// dt into an exponential so the same real-time response falls out of any fixed\n// step. Feed the FIXED clock dt (never a variable rAF delta) or a lockstep sim\n// desyncs. All pure + deterministic (exp routes through dmath), so they are safe\n// to use on hashed values as well as cosmetic ones.\n\n/**\n * Exponentially damp `current` toward `target`, framerate-independent.\n * `lambda` is the decay rate (1/s): larger = snappier. Reaches ~63% of the way\n * to the target after 1/lambda seconds regardless of how dt is subdivided.\n */\nexport const lerpDamp = (current: number, target: number, lambda: number, dt: number): number =>\n lerp(target, current, dexp(-lambda * dt));\n\n/** A critically-damped spring value: rides toward a target with no overshoot. */\nexport interface SpringState {\n value: number;\n vel: number;\n}\n\n/** Make a spring at rest on `value`. */\nexport const spring = (value = 0): SpringState => ({ value, vel: 0 });\n\n/**\n * Advance a critically-damped spring one fixed step toward `target`. `omega` is\n * the angular frequency (rad/s) \u2014 higher snaps faster. Critical damping means it\n * settles as fast as possible without oscillating. Mutates and returns the state.\n * Uses the closed-form solution so it is stable at any dt (no stiffness blow-up).\n */\nexport function springStep(s: SpringState, target: number, omega: number, dt: number): SpringState {\n const decay = dexp(-omega * dt);\n const d = s.value - target; // displacement from rest\n const c = s.vel + omega * d; // integration constant for x(t) = (d + c\u00B7t)\u00B7e^(\u2212\u03C9t)\n s.value = target + (d + c * dt) * decay;\n s.vel = (s.vel - c * omega * dt) * decay;\n return s;\n}\n\n/**\n * One-liner critically-damped follow that owns its own velocity in a closure \u2014\n * for camera/value chase where you don't want to thread a SpringState around.\n * `settle` is the approximate time (s) to arrive. Returns a `(target, dt) \u2192 value`.\n */\nexport function makeReach(start = 0, settle = 0.25): (target: number, dt: number) => number {\n // omega \u2248 4/settle puts ~98% of the move inside `settle` seconds.\n const omega = 4 / Math.max(1e-4, settle);\n const s = spring(start);\n return (target: number, dt: number) => springStep(s, target, omega, dt).value;\n}\n\n// Integer powers are spelled out as multiplication and 2^x routes through\n// dexp2: Math.pow is implementation-defined, and eased values land in hashed\n// node props, so easings must be bit-identical across engines.\nconst sq = (x: number) => x * x;\nconst cube = (x: number) => x * x * x;\nexport const EASINGS: Record<string, Easing> = {\n linear: (t) => t,\n quadIn: (t) => t * t,\n quadOut: (t) => 1 - (1 - t) * (1 - t),\n quadInOut: (t) => (t < 0.5 ? 2 * t * t : 1 - sq(-2 * t + 2) / 2),\n cubicIn: (t) => t * t * t,\n cubicOut: (t) => 1 - cube(1 - t),\n cubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : 1 - cube(-2 * t + 2) / 2),\n sineIn: (t) => 1 - dcos((t * Math.PI) / 2),\n sineOut: (t) => dsin((t * Math.PI) / 2),\n sineInOut: (t) => -(dcos(Math.PI * t) - 1) / 2,\n backOut: (t) => {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * cube(t - 1) + c1 * sq(t - 1);\n },\n elasticOut: (t) => {\n const c4 = (2 * Math.PI) / 3;\n return t === 0 ? 0 : t === 1 ? 1 : dexp2(-10 * t) * dsin((t * 10 - 0.75) * c4) + 1;\n },\n bounceOut: (t) => {\n const n1 = 7.5625;\n const d1 = 2.75;\n if (t < 1 / d1) return n1 * t * t;\n if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;\n if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;\n return n1 * (t -= 2.625 / d1) * t + 0.984375;\n },\n};\n\ninterface Track {\n apply: (v: number) => void;\n from: number;\n to: number;\n duration: number;\n elapsed: number;\n ease: Easing;\n onDone?: () => void;\n delay: number;\n}\n\n/** A node that runs one or more property tweens and reports when they finish. */\nexport class AnimationPlayer extends Node {\n override readonly type = 'AnimationPlayer';\n private tracks: Track[] = [];\n\n /**\n * Animate a value from \u2192 to over `duration` seconds via `apply(value)`.\n * Returns this for chaining.\n */\n to(\n apply: (v: number) => void,\n from: number,\n to: number,\n duration: number,\n ease: keyof typeof EASINGS | Easing = 'cubicOut',\n opts: { delay?: number; onDone?: () => void } = {},\n ): this {\n this.tracks.push({\n apply,\n from,\n to,\n duration: Math.max(1e-6, duration),\n elapsed: 0,\n ease: typeof ease === 'function' ? ease : EASINGS[ease] ?? EASINGS.linear,\n delay: opts.delay ?? 0,\n onDone: opts.onDone,\n });\n return this;\n }\n\n get active(): boolean {\n return this.tracks.length > 0;\n }\n\n /** Signal emitted when all tracks complete. */\n get finished() {\n return this.signal('finished');\n }\n\n protected override onProcess(dt: number): void {\n if (this.tracks.length === 0) return;\n for (let i = this.tracks.length - 1; i >= 0; i--) {\n const tk = this.tracks[i];\n if (tk.delay > 0) {\n tk.delay -= dt;\n continue;\n }\n tk.elapsed += dt;\n const t = clamp(tk.elapsed / tk.duration, 0, 1);\n tk.apply(tk.from + (tk.to - tk.from) * tk.ease(t));\n if (t >= 1) {\n tk.onDone?.();\n this.tracks.splice(i, 1);\n }\n }\n if (this.tracks.length === 0) this.emit('finished', undefined);\n }\n}\n", "// Particles + screen shake: the juice kit. Both are COSMETIC by construction \u2014\n// they carry their own tiny Rng stream (never the world's), are excluded from\n// hashing/serialization, and can be deleted without changing any game outcome.\n// Emission is driven by sim events (jumped, landed, hit\u2026), so replays produce\n// identical visuals, but no canonical state ever depends on them.\n\nimport { dcos, dsin } from '../core/dmath';\nimport { Rng } from '../core/rng';\nimport { smoothstep, TAU, type Transform, type Vec2 } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\n\nexport interface ParticleStyle {\n /** Colors drawn from at random per particle. */\n colors: string[];\n /** Particle radius range (px). */\n sizeMin: number;\n sizeMax: number;\n /** Initial speed range (px/s). */\n speedMin: number;\n speedMax: number;\n /** Emission arc: center angle + spread (radians). Default: full circle. */\n angle?: number;\n spread?: number;\n /** Lifetime range (s). */\n lifeMin: number;\n lifeMax: number;\n /** Gravity applied to particles (px/s\u00B2, +y is down). */\n gravity?: number;\n /** Velocity damping per second (0 = none, 5 = strong). */\n drag?: number;\n /** Shrink to zero over life (default true; also fades opacity). */\n shrink?: boolean;\n}\n\ninterface Particle {\n x: number;\n y: number;\n vx: number;\n vy: number;\n life: number;\n maxLife: number;\n size: number;\n color: string;\n}\n\n/**\n * A pooled particle emitter node. Call `burst(n, at, style)` from game code in\n * response to feel events. Always cosmetic; safe to add anywhere in the tree.\n */\nexport class Particles extends Node {\n override readonly type: string = 'Particles';\n private pool: Particle[] = [];\n private rng: Rng;\n /** Cap on live particles (oldest are recycled first). */\n maxParticles: number;\n\n constructor(config: NodeConfig & { seed?: number; maxParticles?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 7);\n this.maxParticles = config.maxParticles ?? 512;\n }\n\n /** Emit a burst at a position (in this node's local space). */\n burst(count: number, at: Vec2, style: ParticleStyle): void {\n const r = this.rng;\n for (let i = 0; i < count; i++) {\n const angle = style.angle !== undefined ? style.angle + (r.float() - 0.5) * (style.spread ?? 0.6) : r.float() * TAU;\n const speed = style.speedMin + r.float() * (style.speedMax - style.speedMin);\n const p: Particle = {\n x: at.x,\n y: at.y,\n vx: dcos(angle) * speed,\n vy: dsin(angle) * speed,\n life: 0,\n maxLife: style.lifeMin + r.float() * (style.lifeMax - style.lifeMin),\n size: style.sizeMin + r.float() * (style.sizeMax - style.sizeMin),\n color: style.colors[r.int(style.colors.length)],\n };\n if (this.pool.length >= this.maxParticles) this.pool.shift();\n this.pool.push(p);\n }\n // Stash style scalars on the instance for update (single-style emitters are\n // the common case; per-particle style costs memory for no visible gain).\n this.gravity = style.gravity ?? 0;\n this.drag = style.drag ?? 0;\n this.shrink = style.shrink ?? true;\n }\n\n private gravity = 0;\n private drag = 0;\n private shrink = true;\n\n protected override onProcess(dt: number): void {\n const drag = Math.max(0, 1 - this.drag * dt);\n let write = 0;\n for (const p of this.pool) {\n p.life += dt;\n if (p.life >= p.maxLife) continue;\n p.vy += this.gravity * dt;\n p.vx *= drag;\n p.vy *= drag;\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n this.pool[write++] = p;\n }\n this.pool.length = write;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n for (const p of this.pool) {\n const t = 1 - p.life / p.maxLife;\n out.push({\n kind: 'circle',\n cx: p.x,\n cy: p.y,\n radius: this.shrink ? p.size * t : p.size,\n fill: p.color,\n opacity: Math.min(1, t * 2),\n transform: world,\n z: this.z,\n });\n }\n }\n\n get liveCount(): number {\n return this.pool.length;\n }\n}\n\n/** Ready-made styles for the common feel moments. */\nexport const PARTICLE_PRESETS = {\n dust: (colors = ['#c8c2b6', '#a09a8c']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 4, speedMin: 30, speedMax: 90, lifeMin: 0.2, lifeMax: 0.45, gravity: 300, drag: 3, shrink: true }),\n burst: (colors = ['#ffd75e', '#ff9d47', '#fff2c9']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 5, speedMin: 120, speedMax: 320, lifeMin: 0.25, lifeMax: 0.6, drag: 4, shrink: true }),\n hit: (colors = ['#ff5e5e', '#ffd0d0']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 4, speedMin: 160, speedMax: 380, lifeMin: 0.15, lifeMax: 0.35, drag: 6, shrink: true }),\n sparkle: (colors = ['#9ef7ff', '#e8fdff', '#4ed8e8']): ParticleStyle => ({ colors, sizeMin: 1.5, sizeMax: 3.5, speedMin: 20, speedMax: 70, lifeMin: 0.4, lifeMax: 0.9, gravity: -40, drag: 2, shrink: true }),\n} as const;\n\n// \u2500\u2500 Ambient particle field (snow / rain / weather) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A distinct preset family from the burst emitters above: instead of one-shot\n// `burst()` events, an AmbientField seeds a FIXED set of particles across a\n// screen-sized region and drifts them continuously, wrapping at the edges so the\n// field is effectively infinite. Fully cosmetic \u2014 its own Rng, out of the hash.\n// Weather intensity is a smoothstep envelope over SIM time (fixed `dt` from the\n// clock), never wall-clock, so replays and peers see the same storm.\n\nexport interface AmbientStyle {\n /** Colors drawn from at random per particle. */\n colors: string[];\n /** Particle radius range (px). */\n sizeMin: number;\n sizeMax: number;\n /** Steady horizontal wind (px/s). */\n windX?: number;\n /** Fall speed (px/s, +y down). Snow \u2248 40, rain \u2248 600. */\n fallY: number;\n /** Horizontal sway amplitude (px) and frequency (Hz) \u2014 gives snow its wobble. */\n swayAmp?: number;\n swayFreq?: number;\n /** Draw vertical streaks instead of dots (rain). */\n streak?: boolean;\n /** Streak length (px) in streak mode. Default = fallY * 0.03. */\n streakLen?: number;\n}\n\n/** A single weather keyframe: `intensity` (0..1) reached at sim `time` (s). */\nexport interface WeatherKey {\n time: number;\n intensity: number;\n}\n\n/**\n * Smoothstep-interpolated weather intensity at sim time `t` over an ordered list\n * of keyframes. Before the first / after the last key it holds that key's value.\n * Pure \u2014 drive it with `world.time`, never wall-clock.\n */\nexport function weatherEnvelope(t: number, keys: readonly WeatherKey[]): number {\n if (keys.length === 0) return 1;\n if (t <= keys[0].time) return keys[0].intensity;\n for (let i = 1; i < keys.length; i++) {\n if (t <= keys[i].time) {\n const a = keys[i - 1];\n const b = keys[i];\n return a.intensity + (b.intensity - a.intensity) * smoothstep(a.time, b.time, t);\n }\n }\n return keys[keys.length - 1].intensity;\n}\n\ninterface AmbientParticle {\n x: number;\n y: number;\n size: number;\n color: string;\n /** Sway phase offset so particles don't wobble in lockstep. */\n phase: number;\n /** Per-particle fall-speed multiplier (parallax depth). */\n depth: number;\n}\n\n/**\n * A screen-wrapping ambient field for snow, rain, dust, or ash. Seed once with a\n * region size; it fills itself and drifts forever. Set `.envelope` to fade the\n * weather in/out over sim time. Always cosmetic.\n */\nexport class AmbientField extends Node {\n override readonly type: string = 'AmbientField';\n private rng: Rng;\n private field: AmbientParticle[] = [];\n private time = 0;\n private style: AmbientStyle;\n /** Field region (px). Particles wrap within [0,width] \u00D7 [0,height]. */\n width: number;\n height: number;\n /** Optional weather intensity schedule; scales count/opacity. */\n envelope?: WeatherKey[];\n\n constructor(\n config: NodeConfig & {\n seed?: number;\n count?: number;\n width: number;\n height: number;\n style: AmbientStyle;\n envelope?: WeatherKey[];\n },\n ) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 11);\n this.width = config.width;\n this.height = config.height;\n this.style = config.style;\n this.envelope = config.envelope;\n const count = config.count ?? 120;\n const s = this.style;\n for (let i = 0; i < count; i++) {\n this.field.push({\n x: this.rng.float() * this.width,\n y: this.rng.float() * this.height,\n size: s.sizeMin + this.rng.float() * (s.sizeMax - s.sizeMin),\n color: s.colors[this.rng.int(s.colors.length)],\n phase: this.rng.float() * TAU,\n depth: 0.5 + this.rng.float() * 0.5,\n });\n }\n }\n\n private intensity(): number {\n return this.envelope ? weatherEnvelope(this.time, this.envelope) : 1;\n }\n\n protected override onProcess(dt: number): void {\n this.time += dt;\n const s = this.style;\n const wind = s.windX ?? 0;\n const w = this.width;\n const h = this.height;\n for (const p of this.field) {\n p.y += s.fallY * p.depth * dt;\n p.x += wind * dt;\n // Wrap toroidally so the field never empties.\n if (p.y > h) p.y -= h;\n else if (p.y < 0) p.y += h;\n if (p.x > w) p.x -= w;\n else if (p.x < 0) p.x += w;\n }\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const s = this.style;\n const intensity = this.intensity();\n if (intensity <= 0) return;\n // Envelope thins the field: draw only the first `intensity` fraction.\n const shown = Math.round(this.field.length * intensity);\n const swayAmp = s.swayAmp ?? 0;\n const swayFreq = s.swayFreq ?? 0;\n for (let i = 0; i < shown; i++) {\n const p = this.field[i];\n const sway = swayAmp !== 0 ? dsin(this.time * swayFreq * TAU + p.phase) * swayAmp : 0;\n const x = p.x + sway;\n if (s.streak) {\n const len = s.streakLen ?? s.fallY * 0.03;\n out.push({\n kind: 'poly',\n points: [x, p.y, x, p.y + len],\n closed: false,\n stroke: p.color,\n strokeWidth: p.size,\n opacity: intensity,\n transform: world,\n z: this.z,\n });\n } else {\n out.push({\n kind: 'circle',\n cx: x,\n cy: p.y,\n radius: p.size,\n fill: p.color,\n opacity: intensity,\n transform: world,\n z: this.z,\n });\n }\n }\n }\n\n get liveCount(): number {\n return this.field.length;\n }\n}\n\n/** Ready-made ambient weather styles (pair with `AmbientField`). */\nexport const AMBIENT_PRESETS = {\n snow: (colors = ['#ffffff', '#e8f0f8', '#cdd9e6']): AmbientStyle => ({ colors, sizeMin: 1.5, sizeMax: 3.5, windX: 8, fallY: 42, swayAmp: 14, swayFreq: 0.25 }),\n rain: (colors = ['#9fb4c8', '#c3d2e0']): AmbientStyle => ({ colors, sizeMin: 1, sizeMax: 1.8, windX: -40, fallY: 620, streak: true, streakLen: 16 }),\n ash: (colors = ['#6b6b6b', '#8a8580', '#3d3a36']): AmbientStyle => ({ colors, sizeMin: 1, sizeMax: 2.5, windX: 14, fallY: 26, swayAmp: 20, swayFreq: 0.18 }),\n} as const;\n\n/**\n * Screen shake as a cosmetic camera offset with its own Rng and exponential\n * decay. Attach to whatever node the camera follows and read `offset` into the\n * camera's position AFTER canonical follow logic \u2014 or simpler, add the shaker\n * as the camera's parent so the offset composes for free.\n */\nexport class Shaker extends Node {\n override readonly type: string = 'Shaker';\n private rng: Rng;\n private trauma = 0;\n /** Max offset in px at full trauma. */\n amplitude: number;\n /** Trauma decay per second. */\n decay: number;\n\n constructor(config: NodeConfig & { seed?: number; amplitude?: number; decay?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 99);\n this.amplitude = config.amplitude ?? 14;\n this.decay = config.decay ?? 2.6;\n }\n\n /** Add shake (0..1). Stacks, clamped to 1. Quadratic falloff feels right. */\n addTrauma(amount: number): void {\n this.trauma = Math.min(1, this.trauma + amount);\n }\n\n protected override onProcess(dt: number): void {\n this.trauma = Math.max(0, this.trauma - this.decay * dt);\n const s = this.trauma * this.trauma * this.amplitude;\n this.pos.x = (this.rng.float() * 2 - 1) * s;\n this.pos.y = (this.rng.float() * 2 - 1) * s;\n }\n}\n", "// Floating combat text: pooled rise-and-fade numbers/labels \u2014 the damage popups\n// every action/survivors/RPG game leans on. Cosmetic by construction, exactly\n// like Particles/Shaker: its own tiny Rng stream (never the world's, so deleting\n// it changes no game outcome), excluded from hashing, driven by the fixed dt.\n// Emission is triggered by sim events (hit for 12, healed, crit!), so replays\n// reproduce identical popups without any canonical state depending on them.\n\nimport { clamp } from '../core/math';\nimport { Rng } from '../core/rng';\nimport type { Transform, Vec2 } from '../core/math';\nimport type { DrawCommand, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\n\nexport interface FloatStyle {\n /** Text colour. */\n color: string;\n /** Font size in px. */\n size?: number;\n font?: string;\n weight?: number;\n align?: TextAlign;\n /** Upward speed in px/s (screen +y is down, so this is negated internally). */\n rise?: number;\n /** Gravity pulling the rise back down (px/s\u00B2) \u2014 arcs the pop. */\n gravity?: number;\n /** Lifetime in seconds. */\n life?: number;\n /** Random horizontal spread of the launch (px/s). */\n jitter?: number;\n /** Fraction of life spent fading out at the end (0..1, default 0.4). */\n fade?: number;\n}\n\ninterface Popup {\n x: number;\n y: number;\n vx: number;\n vy: number;\n life: number;\n maxLife: number;\n text: string;\n color: string;\n size: number;\n font?: string;\n weight?: number;\n align: TextAlign;\n fade: number;\n}\n\n/**\n * A pooled floating-text emitter. Call `pop(text, at, style)` from game code in\n * response to feel events. Always cosmetic; add it wherever the numbers should\n * live in the tree (usually the world layer, so pops ride the camera).\n */\nexport class FloatingText extends Node {\n override readonly type: string = 'FloatingText';\n private pool: Popup[] = [];\n private rng: Rng;\n /** Cap on live popups (oldest recycled first). */\n maxPopups: number;\n\n constructor(config: NodeConfig & { seed?: number; maxPopups?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 31);\n this.maxPopups = config.maxPopups ?? 128;\n }\n\n /** Spawn one popup at `at` (in this node's local space). */\n pop(text: string, at: Vec2, style: FloatStyle): void {\n const jitter = style.jitter ?? 0;\n const p: Popup = {\n x: at.x + (this.rng.float() - 0.5) * jitter * 0.1,\n y: at.y,\n vx: (this.rng.float() - 0.5) * jitter,\n vy: -(style.rise ?? 60),\n life: 0,\n maxLife: Math.max(0.05, style.life ?? 0.9),\n text,\n color: style.color,\n size: style.size ?? 20,\n font: style.font,\n weight: style.weight,\n align: style.align ?? 'center',\n fade: clamp(style.fade ?? 0.4, 0, 1),\n };\n // Stash the shared gravity for the update step (single-style is the common case).\n this.gravity = style.gravity ?? 0;\n if (this.pool.length >= this.maxPopups) this.pool.shift();\n this.pool.push(p);\n }\n\n private gravity = 0;\n\n protected override onProcess(dt: number): void {\n let write = 0;\n for (const p of this.pool) {\n p.life += dt;\n if (p.life >= p.maxLife) continue;\n p.vy += this.gravity * dt;\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n this.pool[write++] = p;\n }\n this.pool.length = write;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n for (const p of this.pool) {\n const t = p.life / p.maxLife; // 0..1 through life\n const fadeStart = 1 - p.fade;\n const opacity = t < fadeStart ? 1 : clamp(1 - (t - fadeStart) / Math.max(1e-4, p.fade), 0, 1);\n out.push({\n kind: 'text',\n text: p.text,\n x: p.x,\n y: p.y,\n size: p.size,\n font: p.font,\n weight: p.weight,\n align: p.align,\n fill: p.color,\n opacity,\n transform: world,\n z: this.z,\n });\n }\n }\n\n get liveCount(): number {\n return this.pool.length;\n }\n}\n\n/** Ready-made popup looks for the common combat moments. */\nexport const FLOAT_PRESETS = {\n damage: (color = '#e14b4b'): FloatStyle => ({ color, size: 22, weight: 700, rise: 70, gravity: 120, life: 0.8, jitter: 40, fade: 0.4 }),\n crit: (color = '#ffb020'): FloatStyle => ({ color, size: 32, weight: 800, rise: 100, gravity: 160, life: 1.0, jitter: 60, fade: 0.35 }),\n heal: (color = '#4bb06a'): FloatStyle => ({ color, size: 20, weight: 700, rise: 55, gravity: 40, life: 1.0, jitter: 20, fade: 0.5 }),\n label: (color = '#3d3323'): FloatStyle => ({ color, size: 18, weight: 600, rise: 40, gravity: 0, life: 1.2, jitter: 0, fade: 0.5 }),\n} as const;\n", "// Node type registry \u2192 lets a serialized tree (save file / prefab / snapshot)\n// be rebuilt into live nodes. Built-in types register here; games can register\n// custom node types the same way.\n\nimport { Node, type SerializedNode } from './node';\nimport { Sprite, Text, Camera2D, Timer } from './nodes';\nimport { AnimationPlayer } from './tween';\n\nexport type NodeFactory = () => Node;\n\nconst registry = new Map<string, NodeFactory>();\n\nexport function registerNode(type: string, factory: NodeFactory): void {\n registry.set(type, factory);\n}\n\n// Built-ins. Sprite/Text/Timer need required config, so provide safe defaults\n// that applyProps() immediately overwrites during deserialization.\nregisterNode('Node', () => new Node());\nregisterNode('Sprite', () => new Sprite({ shape: { kind: 'rect', w: 1, h: 1 } }));\nregisterNode('Text', () => new Text({ text: '' }));\nregisterNode('Camera2D', () => new Camera2D());\nregisterNode('Timer', () => new Timer({ duration: 1 }));\nregisterNode('AnimationPlayer', () => new AnimationPlayer());\n\n/** Rebuild a live node tree from serialized data. */\nexport function deserializeNode(data: SerializedNode): Node {\n const factory = registry.get(data.type);\n if (!factory) throw new Error(`hayao: unknown node type \"${data.type}\" (register it first)`);\n const node = factory();\n node.name = data.name;\n node.pos = { ...data.pos };\n node.rotation = data.rotation;\n node.scale = { ...data.scale };\n node.z = data.z;\n node.visible = data.visible;\n node.applyProps(data.props);\n for (const child of data.children) node.addChild(deserializeNode(child));\n return node;\n}\n", "// Input as ACTIONS, not keys. Game logic asks \"is 'jump' down?\", never \"is 'KeyZ'\n// down?\". Input is sampled once per fixed step, so a run is a pure function of its\n// input log \u2014 which is what makes replay and scripted playthroughs exact.\n\n/** action name \u2192 physical key codes (KeyboardEvent.code strings). */\nexport type InputMap = Record<string, string[]>;\n\nexport class InputState {\n private down = new Set<string>();\n private prev = new Set<string>();\n /** Analog axes (e.g. from gamepad or pointer), sampled per step. */\n readonly axes = new Map<string, number>();\n\n /** Engine: set which actions are down this step (from live input or replay). */\n beginFrame(actionsDown: Iterable<string>): void {\n this.prev = new Set(this.down);\n this.down = new Set(actionsDown);\n }\n\n isDown(action: string): boolean {\n return this.down.has(action);\n }\n justPressed(action: string): boolean {\n return this.down.has(action) && !this.prev.has(action);\n }\n justReleased(action: string): boolean {\n return !this.down.has(action) && this.prev.has(action);\n }\n axis(name: string): number {\n return this.axes.get(name) ?? 0;\n }\n\n /** The current down-set as a stable sorted array (for recording). */\n snapshot(): string[] {\n return [...this.down].sort();\n }\n\n getState() {\n return { down: [...this.down].sort(), prev: [...this.prev].sort() };\n }\n setState(s: { down: string[]; prev: string[] }): void {\n this.down = new Set(s.down);\n this.prev = new Set(s.prev);\n }\n}\n\n/** Map a set of raw key codes to the set of actions they trigger. */\nexport function keysToActions(map: InputMap, keysDown: Set<string>): string[] {\n const actions: string[] = [];\n for (const action in map) {\n if (map[action].some((k) => keysDown.has(k))) actions.push(action);\n }\n return actions.sort();\n}\n\n/** Records the per-frame action-down sets \u2192 a compact, replayable input log. */\nexport class InputRecorder {\n private frames: string[][] = [];\n\n record(actionsDown: string[]): void {\n this.frames.push(actionsDown.slice().sort());\n }\n\n get length(): number {\n return this.frames.length;\n }\n\n toLog(): InputLog {\n return { frames: this.frames.map((f) => f.slice()) };\n }\n}\n\nexport interface InputLog {\n frames: string[][];\n}\n\n/** Replays a recorded log: returns the action set for frame index i. */\nexport function frameActions(log: InputLog, i: number): string[] {\n return log.frames[i] ?? [];\n}\n\n/** A default set of common bindings games can start from. */\nexport const DEFAULT_INPUT_MAP: InputMap = {\n up: ['ArrowUp', 'KeyW'],\n down: ['ArrowDown', 'KeyS'],\n left: ['ArrowLeft', 'KeyA'],\n right: ['ArrowRight', 'KeyD'],\n confirm: ['Enter', 'Space'],\n cancel: ['Escape', 'Backspace'],\n action: ['KeyZ', 'KeyJ'],\n action2: ['KeyX', 'KeyK'],\n undo: ['KeyU'],\n restart: ['KeyR'],\n};\n", "// Browser input source: tracks physical keys and maps them to actions each step.\n// Kept separate from InputState so the pure sim never imports DOM.\n\nimport { keysToActions, type InputMap } from './actions';\n\nexport class KeyboardSource {\n private keysDown = new Set<string>();\n /** Virtual action taps (from DOM buttons etc.) pending consumption by a step. */\n private pressed = new Set<string>();\n private map: InputMap;\n private target: Document | HTMLElement;\n private onDown: (e: KeyboardEvent) => void;\n private onUp: (e: KeyboardEvent) => void;\n private onBlur: () => void;\n\n constructor(map: InputMap, target: Document | HTMLElement = document) {\n this.map = map;\n this.target = target;\n this.onDown = (e) => {\n this.keysDown.add(e.code);\n // Prevent scroll on arrows/space during play.\n if (e.code.startsWith('Arrow') || e.code === 'Space') e.preventDefault();\n };\n this.onUp = (e) => this.keysDown.delete(e.code);\n this.onBlur = () => this.keysDown.clear();\n target.addEventListener('keydown', this.onDown as EventListener);\n target.addEventListener('keyup', this.onUp as EventListener);\n globalThis.addEventListener?.('blur', this.onBlur);\n }\n\n /** The actions currently held down, as a stable sorted array. */\n currentActions(): string[] {\n const acts = keysToActions(this.map, this.keysDown);\n if (this.pressed.size === 0) return acts;\n const merged = new Set(acts);\n for (const a of this.pressed) merged.add(a);\n return [...merged].sort();\n }\n\n /**\n * Virtually tap an action (DOM button, touch control). The tap is held until\n * at least one fixed step has sampled it \u2014 the driver calls clearPressed()\n * after a successful advance \u2014 so UI clicks enter the SAME deterministic\n * input log as keys, and record/replay covers them.\n */\n press(action: string): void {\n this.pressed.add(action);\n }\n\n /** Consume pending virtual taps (driver-called after \u22651 step ran). */\n clearPressed(): void {\n this.pressed.clear();\n }\n\n setMap(map: InputMap): void {\n this.map = map;\n }\n\n dispose(): void {\n this.target.removeEventListener('keydown', this.onDown as EventListener);\n this.target.removeEventListener('keyup', this.onUp as EventListener);\n globalThis.removeEventListener?.('blur', this.onBlur);\n }\n}\n", "// Tilemaps: grid collision geometry authored as ASCII. Plain data + pure\n// functions (house style) so maps serialize, hash, and diff cleanly.\n\nexport const TILE = {\n EMPTY: 0,\n SOLID: 1,\n /** Passable from below/sides; solid only when landing on its top edge. */\n ONEWAY: 2,\n HAZARD: 3,\n} as const;\nexport type TileId = (typeof TILE)[keyof typeof TILE];\n\nexport interface TilemapData {\n /** Size in tiles. */\n cols: number;\n rows: number;\n /** Tile edge in design-space px. */\n tileSize: number;\n /** Row-major tile ids, length cols*rows. */\n tiles: number[];\n}\n\n/** Default ASCII vocabulary: `#` solid, `-` one-way, `^` hazard, else empty. */\nexport const DEFAULT_TILE_CHARS: Record<string, TileId> = {\n '#': TILE.SOLID,\n '-': TILE.ONEWAY,\n '^': TILE.HAZARD,\n};\n\n/**\n * Build a tilemap from ASCII rows. Unknown characters are EMPTY, so level\n * strings can carry entity markers (`@` spawn, `*` shard\u2026) for game code to\n * read separately via `asciiEntities`.\n */\nexport function tilemapFromAscii(rowsAscii: string[], tileSize = 32, chars: Record<string, TileId> = DEFAULT_TILE_CHARS): TilemapData {\n const rows = rowsAscii.length;\n const cols = Math.max(...rowsAscii.map((r) => r.length));\n const tiles = new Array<number>(cols * rows).fill(TILE.EMPTY);\n rowsAscii.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) tiles[ty * cols + tx] = chars[row[tx]] ?? TILE.EMPTY;\n });\n return { cols, rows, tileSize, tiles };\n}\n\n/** Extract entity markers (any char not in the tile vocabulary, not space/dot). */\nexport function asciiEntities(rowsAscii: string[], tileSize = 32, chars: Record<string, TileId> = DEFAULT_TILE_CHARS): { char: string; tx: number; ty: number; x: number; y: number }[] {\n const out: { char: string; tx: number; ty: number; x: number; y: number }[] = [];\n rowsAscii.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) {\n const c = row[tx];\n if (c === ' ' || c === '.' || chars[c] !== undefined) continue;\n out.push({ char: c, tx, ty, x: (tx + 0.5) * tileSize, y: (ty + 0.5) * tileSize });\n }\n });\n return out;\n}\n\n/** Tile id at tile coords; out-of-bounds reads as SOLID (levels are sealed). */\nexport function tileAt(map: TilemapData, tx: number, ty: number): number {\n if (tx < 0 || ty < 0 || tx >= map.cols || ty >= map.rows) return TILE.SOLID;\n return map.tiles[ty * map.cols + tx];\n}\n\nexport function tileAtPoint(map: TilemapData, x: number, y: number): number {\n return tileAt(map, Math.floor(x / map.tileSize), Math.floor(y / map.tileSize));\n}\n\nexport const mapWidth = (map: TilemapData): number => map.cols * map.tileSize;\nexport const mapHeight = (map: TilemapData): number => map.rows * map.tileSize;\n", "// Kinematic AABB movement against a tilemap plus extra solid rects (moving\n// platforms). Axis-separated, analytically clamped to obstacle edges \u2014 no\n// tunneling, exact and deterministic. Pure functions over plain data.\n\nimport type { Rect } from '../core/math';\nimport { TILE, tileAt, type TilemapData } from './tilemap';\n\nconst EPS = 1e-6;\n\n/** An extra solid the body collides with (moving platform, door, crate\u2026). */\nexport interface SolidRect extends Rect {\n /** Solid only when landing on its top (jump-through platform). */\n oneway?: boolean;\n}\n\nexport interface MoveResult {\n x: number;\n y: number;\n hitX: boolean;\n hitY: boolean;\n onFloor: boolean;\n onCeiling: boolean;\n onWallLeft: boolean;\n onWallRight: boolean;\n /** Final rect overlaps a HAZARD tile (with a small forgiveness inset). */\n hazard: boolean;\n /** Index into `solids` of the rect the body stands on, or -1. */\n floorSolid: number;\n}\n\nconst spanTiles = (lo: number, hi: number, ts: number): [number, number] => [Math.floor(lo / ts), Math.floor((hi - EPS) / ts)];\n\nexport interface MoveOpts {\n solids?: SolidRect[];\n /** Pass true while the player holds \"down\" to drop through one-way platforms. */\n dropThrough?: boolean;\n}\n\n/** Would a rect at (x, y) overlap any solid geometry? (Used for corner-correction probes.) */\nexport function rectBlocked(map: TilemapData, x: number, y: number, w: number, h: number, solids: SolidRect[] = []): boolean {\n const ts = map.tileSize;\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n const [ty0, ty1] = spanTiles(y, y + h, ts);\n for (let ty = ty0; ty <= ty1; ty++)\n for (let tx = tx0; tx <= tx1; tx++) if (tileAt(map, tx, ty) === TILE.SOLID) return true;\n for (const s of solids) {\n if (s.oneway) continue;\n if (x < s.x + s.w - EPS && x + w > s.x + EPS && y < s.y + s.h - EPS && y + h > s.y + EPS) return true;\n }\n return false;\n}\n\n/**\n * Move a rect by (dx, dy) with axis-separated collision: X first, then Y.\n * One-way surfaces block only downward motion that starts at-or-above their top.\n */\nexport function moveRect(map: TilemapData, rect: Rect, dx: number, dy: number, opts: MoveOpts = {}): MoveResult {\n const ts = map.tileSize;\n const solids = opts.solids ?? [];\n let { x, y } = rect;\n const { w, h } = rect;\n let hitX = false;\n let hitY = false;\n let onWallLeft = false;\n let onWallRight = false;\n\n // \u2500\u2500 X axis \u2500\u2500\n if (dx !== 0) {\n const [ty0, ty1] = spanTiles(y, y + h, ts);\n if (dx > 0) {\n let limit = x + dx; // furthest allowed left-edge position\n const [c0, c1] = [Math.floor((x + w) / ts), Math.floor((x + w + dx - EPS) / ts)];\n for (let tx = c0; tx <= c1; tx++)\n for (let ty = ty0; ty <= ty1; ty++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.min(limit, tx * ts - w);\n for (const s of solids)\n if (!s.oneway && s.y < y + h - EPS && s.y + s.h > y + EPS && s.x >= x + w - EPS) limit = Math.min(limit, s.x - w);\n if (limit < x + dx - EPS) {\n hitX = true;\n onWallRight = true;\n }\n x = Math.min(x + dx, limit);\n } else {\n let limit = x + dx;\n const [c0, c1] = [Math.floor((x - EPS) / ts), Math.floor((x + dx) / ts)];\n for (let tx = c0; tx >= c1; tx--)\n for (let ty = ty0; ty <= ty1; ty++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.max(limit, (tx + 1) * ts);\n for (const s of solids)\n if (!s.oneway && s.y < y + h - EPS && s.y + s.h > y + EPS && s.x + s.w <= x + EPS) limit = Math.max(limit, s.x + s.w);\n if (limit > x + dx + EPS) {\n hitX = true;\n onWallLeft = true;\n }\n x = Math.max(x + dx, limit);\n }\n }\n\n // \u2500\u2500 Y axis \u2500\u2500\n const prevBottom = y + h;\n let onFloor = false;\n let onCeiling = false;\n let floorSolid = -1;\n if (dy !== 0) {\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n if (dy > 0) {\n let limit = y + dy; // furthest allowed top position\n const [r0, r1] = [Math.floor(prevBottom / ts), Math.floor((prevBottom + dy - EPS) / ts)];\n for (let ty = r0; ty <= r1; ty++)\n for (let tx = tx0; tx <= tx1; tx++) {\n const t = tileAt(map, tx, ty);\n const blocks = t === TILE.SOLID || (t === TILE.ONEWAY && !opts.dropThrough && prevBottom <= ty * ts + EPS);\n if (blocks) limit = Math.min(limit, ty * ts - h);\n }\n for (let i = 0; i < solids.length; i++) {\n const s = solids[i];\n const inX = s.x < x + w - EPS && s.x + s.w > x + EPS;\n if (!inX || s.y < prevBottom - EPS) continue;\n if (s.oneway && (opts.dropThrough || prevBottom > s.y + EPS)) continue;\n if (s.y - h < limit) {\n limit = s.y - h;\n floorSolid = i;\n }\n }\n if (limit < y + dy - EPS) {\n hitY = true;\n onFloor = true;\n } else floorSolid = -1;\n y = Math.min(y + dy, limit);\n } else {\n let limit = y + dy;\n const [r0, r1] = [Math.floor((y - EPS) / ts), Math.floor((y + dy) / ts)];\n for (let ty = r0; ty >= r1; ty--)\n for (let tx = tx0; tx <= tx1; tx++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.max(limit, (ty + 1) * ts);\n for (const s of solids)\n if (!s.oneway && s.x < x + w - EPS && s.x + s.w > x + EPS && s.y + s.h <= y + EPS) limit = Math.max(limit, s.y + s.h);\n if (limit > y + dy + EPS) {\n hitY = true;\n onCeiling = true;\n }\n y = Math.max(y + dy, limit);\n }\n }\n\n // \u2500\u2500 Ground probe (also true when dy was 0 or clamped exactly) \u2500\u2500\n if (!onFloor) {\n const probe = groundAt(map, x, y, w, h, solids, opts.dropThrough ?? false);\n onFloor = probe.grounded;\n floorSolid = probe.solid;\n }\n\n // \u2500\u2500 Hazard overlap (inset for forgiveness) \u2500\u2500\n const inset = 3;\n let hazard = false;\n {\n const [hx0, hx1] = spanTiles(x + inset, x + w - inset, ts);\n const [hy0, hy1] = spanTiles(y + inset, y + h - inset, ts);\n for (let ty = hy0; ty <= hy1 && !hazard; ty++)\n for (let tx = hx0; tx <= hx1 && !hazard; tx++) if (tileAt(map, tx, ty) === TILE.HAZARD) hazard = true;\n }\n\n return { x, y, hitX, hitY, onFloor, onCeiling, onWallLeft, onWallRight, hazard, floorSolid };\n}\n\n/** Is there support directly under the rect (within 1px)? */\nexport function groundAt(map: TilemapData, x: number, y: number, w: number, h: number, solids: SolidRect[] = [], dropThrough = false): { grounded: boolean; solid: number } {\n const ts = map.tileSize;\n const bottom = y + h;\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n const ty = Math.floor((bottom + 1) / ts);\n for (let tx = tx0; tx <= tx1; tx++) {\n const t = tileAt(map, tx, ty);\n if (t === TILE.SOLID) return { grounded: true, solid: -1 };\n if (t === TILE.ONEWAY && !dropThrough && Math.abs(bottom - ty * ts) <= 1 + EPS) return { grounded: true, solid: -1 };\n }\n for (let i = 0; i < solids.length; i++) {\n const s = solids[i];\n const inX = s.x < x + w - EPS && s.x + s.w > x + EPS;\n if (inX && bottom <= s.y + 1 + EPS && bottom >= s.y - 1 - EPS) return { grounded: true, solid: i };\n }\n return { grounded: false, solid: -1 };\n}\n", "// PlatformerController: a state-of-the-art 2D kinematic character controller.\n// Pure and deterministic \u2014 plain-data state, stepped at the fixed timestep, no\n// engine imports beyond physics/math \u2014 so every game-feel feature below is\n// unit-testable in Node by pumping frames.\n//\n// Implements the modern platforming canon:\n// coyote time \u00B7 jump buffering \u00B7 variable jump height \u00B7 halved-gravity apex\n// jump corner correction \u00B7 dash (8-way) \u00B7 dash corner correction\n// wall slide + wall jump \u00B7 moving-platform carry + lift momentum storage\n// one-way platforms + drop-through\n\nimport { dhypot } from '../core/dmath';\nimport { moveRect, rectBlocked, type SolidRect } from './aabb';\nimport type { TilemapData } from './tilemap';\n\nexport interface PlatformerConfig {\n width: number;\n height: number;\n /** Ground run speed (px/s) and accelerations (px/s\u00B2). */\n runSpeed: number;\n groundAccel: number;\n groundFriction: number;\n airAccel: number;\n /**\n * Horizontal decel with no input while airborne (px/s\u00B2). Keep LOW: inherited\n * momentum (lift jumps, wall kicks) must survive flight to feel right.\n */\n airFriction: number;\n /** Gravity (px/s\u00B2), terminal fall speed, and the apex modifier. */\n gravity: number;\n maxFall: number;\n /** |vy| below this counts as the jump apex\u2026 */\n apexThreshold: number;\n /** \u2026where gravity is multiplied by this while jump is held (the floaty peak). */\n apexGravityMult: number;\n /** Initial jump velocity (px/s, upward) and early-release cut multiplier. */\n jumpVelocity: number;\n jumpCutMult: number;\n /** Grace timers (seconds). */\n coyoteTime: number;\n jumpBuffer: number;\n /** Max px the body is nudged sideways to slip past a ceiling corner when jumping. */\n jumpCornerNudge: number;\n /** Max px the body is nudged vertically to slip past a corner while dashing. */\n dashCornerNudge: number;\n /** Mid-air jumps (0 = none, 1 = double jump\u2026), refilled on landing/wall. */\n airJumps: number;\n /** Air-jump velocity as a fraction of jumpVelocity. */\n airJumpMult: number;\n /** Dash: speed (px/s), duration (s), cooldown (s), charges refilled on landing. */\n dashSpeed: number;\n dashTime: number;\n dashCooldown: number;\n dashCharges: number;\n /** Wall interaction. */\n wallSlideMaxFall: number;\n wallJumpVelX: number;\n wallJumpVelY: number;\n /** Seconds after a wall jump during which input can't cancel the outward velocity. */\n wallJumpLock: number;\n}\n\n/** Tuned for 32px tiles at 60Hz in the 1280\u00D7720 design space. */\nexport const DEFAULT_PLATFORMER: PlatformerConfig = {\n width: 22,\n height: 28,\n runSpeed: 340,\n groundAccel: 3800,\n groundFriction: 4200,\n airAccel: 2600,\n airFriction: 260,\n gravity: 2300,\n maxFall: 660,\n apexThreshold: 60,\n apexGravityMult: 0.5,\n jumpVelocity: 650,\n jumpCutMult: 0.4,\n coyoteTime: 0.1,\n jumpBuffer: 0.12,\n jumpCornerNudge: 10,\n dashCornerNudge: 12,\n airJumps: 0,\n airJumpMult: 0.92,\n dashSpeed: 640,\n dashTime: 0.14,\n dashCooldown: 0.25,\n dashCharges: 1,\n wallSlideMaxFall: 150,\n wallJumpVelX: 360,\n wallJumpVelY: 600,\n wallJumpLock: 0.13,\n};\n\n/** Per-step intent, sampled from actions by the game (never raw keys). */\nexport interface PadInput {\n moveX: number; // -1 | 0 | 1\n moveY: number; // -1 (up) | 0 | 1 (down)\n jumpHeld: boolean;\n jumpPressed: boolean;\n dashPressed: boolean;\n}\n\nexport const PAD_NEUTRAL: PadInput = { moveX: 0, moveY: 0, jumpHeld: false, jumpPressed: false, dashPressed: false };\n\n/** A moving platform: its current rect, plus its velocity this step (px/s). */\nexport interface Platform extends SolidRect {\n vx: number;\n vy: number;\n}\n\n/** Plain serializable controller state \u2014 put it in `world.state` so it hashes. */\nexport interface PlatformerState {\n x: number; // top-left of the collision box\n y: number;\n vx: number;\n vy: number;\n facing: number; // -1 | 1\n onGround: boolean;\n onWall: number; // -1 touching left wall, 1 right, 0 none\n coyote: number;\n buffer: number;\n jumping: boolean; // rising from a jump (variable-height window)\n wallLock: number;\n airJumpsLeft: number;\n dashing: number; // time left in current dash\n dashCd: number;\n dashesLeft: number;\n dashVx: number;\n dashVy: number;\n /** Velocity inherited from the platform we stand on (lift momentum storage). */\n carryVx: number;\n carryVy: number;\n dead: boolean;\n}\n\nexport function createPlatformerState(x: number, y: number): PlatformerState {\n return { x, y, vx: 0, vy: 0, facing: 1, onGround: false, onWall: 0, coyote: 0, buffer: 0, jumping: false, wallLock: 0, airJumpsLeft: 0, dashing: 0, dashCd: 0, dashesLeft: 1, dashVx: 0, dashVy: 0, carryVx: 0, carryVy: 0, dead: false };\n}\n\n/** Feel events emitted by a step \u2014 hooks for SFX / particles / screen shake. */\nexport interface PlatformerEvents {\n jumped: boolean;\n wallJumped: boolean;\n airJumped: boolean;\n dashed: boolean;\n landed: boolean;\n died: boolean;\n}\n\nconst approach = (v: number, target: number, delta: number): number => (v < target ? Math.min(v + delta, target) : Math.max(v - delta, target));\n\n/**\n * Advance the controller one fixed step. Mutates `s`; returns feel events.\n * `platforms` should already be at their post-move positions for this step,\n * with `vx/vy` set to their velocity, so the body is carried exactly.\n */\nexport function stepPlatformer(s: PlatformerState, input: PadInput, dt: number, map: TilemapData, cfg: PlatformerConfig = DEFAULT_PLATFORMER, platforms: Platform[] = []): PlatformerEvents {\n const ev: PlatformerEvents = { jumped: false, wallJumped: false, airJumped: false, dashed: false, landed: false, died: false };\n if (s.dead) return ev;\n const wasGrounded = s.onGround;\n\n // \u2500\u2500 Timers \u2500\u2500\n s.coyote = Math.max(0, s.coyote - dt);\n s.buffer = Math.max(0, s.buffer - dt);\n s.wallLock = Math.max(0, s.wallLock - dt);\n s.dashCd = Math.max(0, s.dashCd - dt);\n if (input.jumpPressed) s.buffer = cfg.jumpBuffer;\n\n // \u2500\u2500 Dash start \u2500\u2500\n if (input.dashPressed && s.dashing <= 0 && s.dashCd <= 0 && s.dashesLeft > 0) {\n let dx = input.moveX;\n let dy = input.moveY;\n if (dx === 0 && dy === 0) dx = s.facing;\n const inv = 1 / dhypot(dx, dy);\n s.dashing = cfg.dashTime;\n s.dashCd = cfg.dashCooldown;\n s.dashesLeft--;\n s.dashVx = dx * inv * cfg.dashSpeed;\n s.dashVy = dy * inv * cfg.dashSpeed;\n s.jumping = false;\n ev.dashed = true;\n }\n\n // \u2500\u2500 Horizontal intent \u2500\u2500\n if (s.dashing > 0) {\n s.vx = s.dashVx;\n s.vy = s.dashVy;\n s.dashing -= dt;\n } else if (s.wallLock <= 0) {\n const target = input.moveX * cfg.runSpeed;\n const accel = s.onGround ? (input.moveX !== 0 ? cfg.groundAccel : cfg.groundFriction) : input.moveX !== 0 ? cfg.airAccel : cfg.airFriction;\n s.vx = approach(s.vx, target, accel * dt);\n if (input.moveX !== 0) s.facing = input.moveX > 0 ? 1 : -1;\n }\n\n // \u2500\u2500 Gravity (skipped while dashing) \u2500\u2500\n if (s.dashing <= 0 && !s.onGround) {\n let g = cfg.gravity;\n if (Math.abs(s.vy) < cfg.apexThreshold && input.jumpHeld && s.jumping) g *= cfg.apexGravityMult; // halved-gravity peak\n s.vy = Math.min(s.vy + g * dt, cfg.maxFall);\n if (s.onWall !== 0 && s.vy > cfg.wallSlideMaxFall && input.moveX === s.onWall) s.vy = cfg.wallSlideMaxFall; // wall slide\n }\n\n // \u2500\u2500 Variable jump height: release cuts upward velocity \u2500\u2500\n if (s.jumping && !input.jumpHeld && s.vy < 0) {\n s.vy *= cfg.jumpCutMult;\n s.jumping = false;\n }\n\n // \u2500\u2500 Jump (buffered + coyote) / wall jump \u2500\u2500\n if (s.buffer > 0 && s.dashing <= 0) {\n if (s.onGround || s.coyote > 0) {\n s.vy = -cfg.jumpVelocity;\n // Lift momentum storage: keep the platform's motion.\n s.vx += s.carryVx;\n if (s.carryVy < 0) s.vy += s.carryVy;\n s.jumping = true;\n s.buffer = 0;\n s.coyote = 0;\n s.onGround = false;\n ev.jumped = true;\n } else if (s.onWall !== 0 && cfg.wallJumpVelY > 0) {\n s.vx = -s.onWall * cfg.wallJumpVelX;\n s.vy = -cfg.wallJumpVelY;\n s.facing = -s.onWall;\n s.jumping = true;\n s.buffer = 0;\n s.wallLock = cfg.wallJumpLock;\n ev.wallJumped = true;\n ev.jumped = true;\n } else if (s.airJumpsLeft > 0) {\n s.vy = -cfg.jumpVelocity * cfg.airJumpMult;\n s.airJumpsLeft--;\n s.jumping = true;\n s.buffer = 0;\n ev.jumped = true;\n ev.airJumped = true;\n }\n }\n\n // \u2500\u2500 Move-and-collide, with platform carry \u2500\u2500\n // Holding down passes through one-ways \u2014 INCLUDING while already falling,\n // or the body re-lands on the platform lip one frame after leaving it.\n const dropThrough = input.moveY > 0 && s.buffer <= 0;\n let dx = s.vx * dt + s.carryVx * dt * (s.onGround ? 1 : 0);\n let dy = s.vy * dt + Math.max(0, s.carryVy) * dt * (s.onGround ? 1 : 0);\n let res = moveRect(map, { x: s.x, y: s.y, w: cfg.width, h: cfg.height }, dx, dy, { solids: platforms, dropThrough });\n\n // \u2500\u2500 Jump corner correction: bonked a ceiling edge while rising \u2192 nudge sideways \u2500\u2500\n if (res.onCeiling && s.vy < 0 && s.dashing <= 0) {\n const slip = cornerSlipX(map, platforms, res.x, res.y, cfg.width, cfg.height, dy, cfg.jumpCornerNudge);\n if (slip !== null) {\n res = moveRect(map, { x: slip, y: res.y, w: cfg.width, h: cfg.height }, 0, dy, { solids: platforms, dropThrough });\n res.x = slip;\n }\n }\n\n // \u2500\u2500 Dash corner correction: clipped a wall edge while dashing \u2192 nudge vertically \u2500\u2500\n if (res.hitX && s.dashing > 0 && Math.abs(s.dashVy) < 1) {\n const slip = cornerSlipY(map, platforms, res.x, res.y, cfg.width, cfg.height, dx, cfg.dashCornerNudge);\n if (slip !== null) {\n res = moveRect(map, { x: res.x, y: slip, w: cfg.width, h: cfg.height }, dx, 0, { solids: platforms, dropThrough });\n res.y = slip;\n }\n }\n\n s.x = res.x;\n s.y = res.y;\n if (res.hitY && s.vy > 0) s.vy = 0;\n if (res.onCeiling) {\n s.vy = Math.max(s.vy, 0);\n s.jumping = false;\n }\n if (res.hitX && s.dashing <= 0) s.vx = 0;\n s.onWall = res.onWallLeft ? -1 : res.onWallRight ? 1 : wallTouch(map, platforms, s.x, s.y, cfg.width, cfg.height);\n s.onGround = res.onFloor;\n\n // \u2500\u2500 Ground bookkeeping: coyote, dash refill, landing, lift momentum \u2500\u2500\n if (s.onGround) {\n s.coyote = cfg.coyoteTime;\n s.dashesLeft = cfg.dashCharges;\n s.airJumpsLeft = cfg.airJumps;\n if (!wasGrounded) ev.landed = true;\n if (res.floorSolid >= 0) {\n const p = platforms[res.floorSolid];\n s.carryVx = p.vx;\n s.carryVy = p.vy;\n // Ride the platform exactly: snap feet to its top.\n s.y = p.y - cfg.height;\n } else {\n s.carryVx = 0;\n s.carryVy = 0;\n }\n if (s.vy > 0) s.vy = 0;\n s.jumping = false;\n } else if (wasGrounded && s.carryVy !== 0) {\n // Walked off a lift: keep stored momentum until landing or jumping.\n }\n\n if (res.hazard) {\n s.dead = true;\n ev.died = true;\n }\n return ev;\n}\n\n// \u2500\u2500 Movement envelope: derive level geometry from the config, never guess \u2500\u2500\n// Conservative closed-form bounds (they ignore the apex-gravity bonus, so the\n// real controller always reaches at least this far). Author levels against\n// these \u2014 \"it looks jumpable\" is how unwinnable geometry ships.\n\n/** Max rise of a full jump (px). */\nexport function jumpHeight(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return (cfg.jumpVelocity * cfg.jumpVelocity) / (2 * cfg.gravity);\n}\n\n/** Full-jump airtime returning to takeoff height (s). */\nexport function jumpAirtime(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return (2 * cfg.jumpVelocity) / cfg.gravity;\n}\n\n/** Max horizontal gap clearable by a running jump (px, flat-to-flat). */\nexport function jumpDistance(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return cfg.runSpeed * jumpAirtime(cfg);\n}\n\n/** Max gap clearable by jump + one apex dash (px, flat-to-flat, horizontal dash). */\nexport function dashJumpDistance(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return jumpDistance(cfg) + (cfg.dashSpeed - cfg.runSpeed) * cfg.dashTime;\n}\n\n/** Try shifting x by up to \u00B1nudge so a rect moving by dy is unblocked. Prefers the smaller shift. */\nfunction cornerSlipX(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number, dy: number, nudge: number): number | null {\n for (let n = 1; n <= nudge; n++) {\n for (const dir of [1, -1]) {\n const nx = x + dir * n;\n if (!rectBlocked(map, nx, y + dy, w, h, solids) && !rectBlocked(map, nx, y, w, h, solids)) return nx;\n }\n }\n return null;\n}\n\n/** Try shifting y by up to \u00B1nudge so a rect moving by dx is unblocked. */\nfunction cornerSlipY(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number, dx: number, nudge: number): number | null {\n for (let n = 1; n <= nudge; n++) {\n for (const dir of [-1, 1]) {\n const ny = y + dir * n;\n if (!rectBlocked(map, x + dx, ny, w, h, solids) && !rectBlocked(map, x, ny, w, h, solids)) return ny;\n }\n }\n return null;\n}\n\n/** Which wall (if any) is the body pressed against? (1px probes) */\nfunction wallTouch(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number): number {\n if (rectBlocked(map, x + 1, y, w, h, solids)) return 1;\n if (rectBlocked(map, x - 1, y, w, h, solids)) return -1;\n return 0;\n}\n", "// Uniform-grid spatial hash for broad-phase queries over many moving entities\n// (hordes, bullets, RTS units). Deterministic: iteration order is insertion\n// order within cells, and query results preserve first-insertion order.\n// Rebuild-per-step is the intended pattern \u2014 clear() + insert all \u2014 which is\n// O(n) and avoids stale incremental state entirely.\n\nimport type { Rect } from '../core/math';\n\nexport class SpatialHash<T> {\n private cells = new Map<number, T[]>();\n private bounds = new Map<T, Rect>();\n private readonly cellSize: number;\n\n constructor(cellSize = 64) {\n this.cellSize = cellSize;\n }\n\n clear(): void {\n this.cells.clear();\n this.bounds.clear();\n }\n\n get size(): number {\n return this.bounds.size;\n }\n\n private key(cx: number, cy: number): number {\n // Interleave-free packing; fine for worlds within \u00B12^15 cells.\n return (cx + 32768) * 65536 + (cy + 32768);\n }\n\n insert(item: T, rect: Rect): void {\n this.bounds.set(item, rect);\n const cs = this.cellSize;\n const x0 = Math.floor(rect.x / cs);\n const x1 = Math.floor((rect.x + rect.w) / cs);\n const y0 = Math.floor(rect.y / cs);\n const y1 = Math.floor((rect.y + rect.h) / cs);\n for (let cy = y0; cy <= y1; cy++)\n for (let cx = x0; cx <= x1; cx++) {\n const k = this.key(cx, cy);\n const cell = this.cells.get(k);\n if (cell) cell.push(item);\n else this.cells.set(k, [item]);\n }\n }\n\n /** All items whose rects overlap the query rect (deduplicated, deterministic order). */\n query(rect: Rect): T[] {\n const cs = this.cellSize;\n const x0 = Math.floor(rect.x / cs);\n const x1 = Math.floor((rect.x + rect.w) / cs);\n const y0 = Math.floor(rect.y / cs);\n const y1 = Math.floor((rect.y + rect.h) / cs);\n const seen = new Set<T>();\n const out: T[] = [];\n for (let cy = y0; cy <= y1; cy++)\n for (let cx = x0; cx <= x1; cx++) {\n const cell = this.cells.get(this.key(cx, cy));\n if (!cell) continue;\n for (const item of cell) {\n if (seen.has(item)) continue;\n seen.add(item);\n const b = this.bounds.get(item)!;\n if (b.x < rect.x + rect.w && b.x + b.w > rect.x && b.y < rect.y + rect.h && b.y + b.h > rect.y) out.push(item);\n }\n }\n return out;\n }\n\n /** All items within `radius` of a point (circle vs rect-center test on bounds). */\n queryCircle(x: number, y: number, radius: number): T[] {\n const near = this.query({ x: x - radius, y: y - radius, w: radius * 2, h: radius * 2 });\n return near.filter((item) => {\n const b = this.bounds.get(item)!;\n const cx = Math.max(b.x, Math.min(x, b.x + b.w));\n const cy = Math.max(b.y, Math.min(y, b.y + b.h));\n return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= radius * radius;\n });\n }\n}\n", "// Grid raycasting (DDA) over a tilemap \u2014 the sight primitive behind stealth\n// vision cones, sentry line-of-sight, roguelike FOV, and 2D lighting.\n\nimport { dcos, dhypot } from '../core/dmath';\nimport { TILE, tileAt, type TilemapData } from './tilemap';\n\nexport interface RayHit {\n /** True if a solid tile stopped the ray before reaching (x1, y1). */\n blocked: boolean;\n /** Where the ray stopped (the hit point, or the target if unblocked). */\n x: number;\n y: number;\n /** Distance travelled. */\n dist: number;\n}\n\n/**\n * March a ray from (x0,y0) toward (x1,y1) through the tile grid (DDA \u2014 exact,\n * no step-size tuning). SOLID tiles block; everything else passes.\n */\nexport function raycastTiles(map: TilemapData, x0: number, y0: number, x1: number, y1: number): RayHit {\n const ts = map.tileSize;\n const dx = x1 - x0;\n const dy = y1 - y0;\n const maxDist = dhypot(dx, dy);\n if (maxDist === 0) return { blocked: false, x: x1, y: y1, dist: 0 };\n const dirX = dx / maxDist;\n const dirY = dy / maxDist;\n\n let tx = Math.floor(x0 / ts);\n let ty = Math.floor(y0 / ts);\n const stepX = dirX > 0 ? 1 : -1;\n const stepY = dirY > 0 ? 1 : -1;\n const tDeltaX = dirX !== 0 ? Math.abs(ts / dirX) : Infinity;\n const tDeltaY = dirY !== 0 ? Math.abs(ts / dirY) : Infinity;\n let tMaxX = dirX !== 0 ? (dirX > 0 ? (tx + 1) * ts - x0 : x0 - tx * ts) / Math.abs(dirX) : Infinity;\n let tMaxY = dirY !== 0 ? (dirY > 0 ? (ty + 1) * ts - y0 : y0 - ty * ts) / Math.abs(dirY) : Infinity;\n\n let t = 0;\n // The starting tile never blocks (the caster stands in it).\n for (let guard = 0; guard < 512; guard++) {\n if (tMaxX < tMaxY) {\n t = tMaxX;\n tMaxX += tDeltaX;\n tx += stepX;\n } else {\n t = tMaxY;\n tMaxY += tDeltaY;\n ty += stepY;\n }\n if (t >= maxDist) return { blocked: false, x: x1, y: y1, dist: maxDist };\n if (tileAt(map, tx, ty) === TILE.SOLID) {\n return { blocked: true, x: x0 + dirX * t, y: y0 + dirY * t, dist: t };\n }\n }\n return { blocked: true, x: x0 + dirX * t, y: y0 + dirY * t, dist: t };\n}\n\n/** Can a see b with no solid tile between? */\nexport function lineOfSight(map: TilemapData, ax: number, ay: number, bx: number, by: number): boolean {\n return !raycastTiles(map, ax, ay, bx, by).blocked;\n}\n\n/**\n * Is the target inside a vision cone AND visible? (facing is a unit vector;\n * fov is the FULL cone angle in radians.)\n */\nexport function inVisionCone(map: TilemapData, ex: number, ey: number, faceX: number, faceY: number, fov: number, range: number, tx: number, ty: number): boolean {\n const dx = tx - ex;\n const dy = ty - ey;\n const d = dhypot(dx, dy);\n if (d > range || d === 0) return false;\n const dot = (dx * faceX + dy * faceY) / d;\n if (dot < dcos(fov / 2)) return false;\n return lineOfSight(map, ex, ey, tx, ty);\n}\n", "// Deterministic 2D rigid-body dynamics \u2014 data model. The whole physics world\n// is PLAIN JSON (no classes, no hidden caches), so it can live in\n// `world.state` and inherit hashing, snapshot/restore, replay verification,\n// and structuredClone-based planning bots for free. Pure functions over data.\n//\n// Units are pixels / seconds / radians. Only mass RATIOS matter to the\n// solver; density defaults keep numbers small. Convention: a body's local\n// origin is its center of mass (use `polygonBox`/`regularPolygon` helpers).\n\nimport { dcos, dsin } from '../core/dmath';\nimport type { Rect } from '../core/math';\n\nexport type RigidShape =\n | { kind: 'circle'; r: number }\n /** Convex polygon, CCW winding, local coords flat [x0,y0,x1,y1,\u2026]. */\n | { kind: 'poly'; points: number[] };\n\nexport type BodyKind = 'dynamic' | 'static' | 'kinematic';\n\nexport interface RigidBody {\n id: number;\n kind: BodyKind;\n shape: RigidShape;\n /** Pose: position of the center of mass + rotation. */\n x: number; y: number; a: number;\n /** Velocity: linear + angular (rad/s). */\n vx: number; vy: number; w: number;\n /** Mass properties (0 inverse = immovable / non-rotating). */\n m: number; invM: number; i: number; invI: number;\n restitution: number;\n friction: number;\n linDamp: number;\n angDamp: number;\n gravityScale: number;\n /** Swept-circle CCD each step (circles only) \u2014 for very fast bodies. */\n bullet: boolean;\n /** Overlap events only, no collision response. */\n sensor: boolean;\n /** Collision filtering: collide iff (a.mask & b.layer) && (b.mask & a.layer). */\n layer: number;\n mask: number;\n canSleep: boolean;\n sleeping: boolean;\n sleepTime: number;\n /** Characteristic radius: converts spin to rim speed for the sleep test. */\n sleepR: number;\n /** Per-step force/torque accumulators (cleared after integration). */\n fx: number; fy: number; torque: number;\n}\n\nexport interface RigidWorldOpts {\n gravityX?: number;\n gravityY?: number;\n /** Solver velocity iterations (default 16 \u2014 stacks need it). */\n iterations?: number;\n /** Broadphase cell size in px (default 96). */\n cellSize?: number;\n}\n\nexport interface RigidWorld {\n gravityX: number;\n gravityY: number;\n iterations: number;\n cellSize: number;\n nextId: number;\n bodies: RigidBody[];\n joints: import('./rigidJoints').Joint[];\n /** Warm-start impulse cache from the previous step, keyed \"a:b:feature\". */\n warm: Record<string, [number, number]>;\n}\n\nexport function createRigidWorld(opts: RigidWorldOpts = {}): RigidWorld {\n return {\n gravityX: opts.gravityX ?? 0,\n gravityY: opts.gravityY ?? 900,\n iterations: opts.iterations ?? 16,\n cellSize: opts.cellSize ?? 96,\n nextId: 1,\n bodies: [],\n joints: [],\n warm: {},\n };\n}\n\nexport interface RigidBodyDef {\n kind?: BodyKind;\n shape: RigidShape;\n x?: number; y?: number; a?: number;\n vx?: number; vy?: number; w?: number;\n density?: number;\n restitution?: number;\n friction?: number;\n linDamp?: number;\n angDamp?: number;\n gravityScale?: number;\n bullet?: boolean;\n sensor?: boolean;\n layer?: number;\n mask?: number;\n canSleep?: boolean;\n /** Lock rotation (players, elevators): infinite inertia. */\n fixedRotation?: boolean;\n}\n\n/** Area + second moment of area (about the local origin) for a shape. */\nfunction massProps(shape: RigidShape): { area: number; unitI: number } {\n if (shape.kind === 'circle') {\n const area = Math.PI * shape.r * shape.r;\n return { area, unitI: (shape.r * shape.r) / 2 }; // I = m r\u00B2/2\n }\n // Convex polygon: standard cross-product accumulation about the origin.\n const p = shape.points;\n const n = p.length / 2;\n let area = 0;\n let inertia = 0;\n for (let k = 0; k < n; k++) {\n const x0 = p[k * 2], y0 = p[k * 2 + 1];\n const j = (k + 1) % n;\n const x1 = p[j * 2], y1 = p[j * 2 + 1];\n const cross = x0 * y1 - x1 * y0;\n area += cross / 2;\n inertia += (cross * (x0 * x0 + x0 * x1 + x1 * x1 + y0 * y0 + y0 * y1 + y1 * y1)) / 12;\n }\n return { area: Math.abs(area), unitI: area !== 0 ? Math.abs(inertia) / Math.abs(area) : 0 };\n}\n\n/** Mass scale keeps typical bodies O(0.1\u201310) so impulses stay well-ranged. */\nconst DENSITY_SCALE = 1e-4;\n\nexport function addBody(rw: RigidWorld, def: RigidBodyDef): number {\n const kind = def.kind ?? 'dynamic';\n const density = def.density ?? 1;\n const { area, unitI } = massProps(def.shape);\n const m = kind === 'dynamic' ? Math.max(area * density * DENSITY_SCALE, 1e-6) : 0;\n const i = kind === 'dynamic' && !def.fixedRotation ? m * unitI : 0;\n const body: RigidBody = {\n id: rw.nextId++,\n kind,\n shape: def.shape,\n x: def.x ?? 0, y: def.y ?? 0, a: def.a ?? 0,\n vx: def.vx ?? 0, vy: def.vy ?? 0, w: def.w ?? 0,\n m, invM: m > 0 ? 1 / m : 0,\n i, invI: i > 0 ? 1 / i : 0,\n restitution: def.restitution ?? 0.1,\n friction: def.friction ?? 0.4,\n linDamp: def.linDamp ?? 0,\n angDamp: def.angDamp ?? 0.6,\n gravityScale: def.gravityScale ?? 1,\n bullet: def.bullet ?? false,\n sensor: def.sensor ?? false,\n layer: def.layer ?? 1,\n mask: def.mask ?? 0xffff,\n canSleep: def.canSleep ?? true,\n sleeping: false,\n sleepTime: 0,\n sleepR: def.shape.kind === 'circle'\n ? def.shape.r\n : Math.sqrt(def.shape.points.reduce((m, _, i, p) => (i % 2 ? m : Math.max(m, p[i] * p[i] + p[i + 1] * p[i + 1])), 0)),\n fx: 0, fy: 0, torque: 0,\n };\n rw.bodies.push(body);\n return body.id;\n}\n\nexport function getBody(rw: RigidWorld, id: number): RigidBody | undefined {\n const bs = rw.bodies;\n for (let k = 0; k < bs.length; k++) if (bs[k].id === id) return bs[k];\n return undefined;\n}\n\nexport function removeBody(rw: RigidWorld, id: number): void {\n const idx = rw.bodies.findIndex((b) => b.id === id);\n if (idx >= 0) rw.bodies.splice(idx, 1);\n rw.joints = rw.joints.filter((j) => j.a !== id && j.b !== id);\n}\n\nexport function wakeBody(b: RigidBody): void {\n b.sleeping = false;\n b.sleepTime = 0;\n}\n\n/** Apply an impulse at a world point (wakes the body). */\nexport function applyImpulse(rw: RigidWorld, id: number, ix: number, iy: number, px?: number, py?: number): void {\n const b = getBody(rw, id);\n if (!b || b.invM === 0) return;\n wakeBody(b);\n b.vx += ix * b.invM;\n b.vy += iy * b.invM;\n if (px !== undefined && py !== undefined) {\n b.w += ((px - b.x) * iy - (py - b.y) * ix) * b.invI;\n }\n}\n\n/** World-space vertices of a poly body (freshly computed \u2014 no caches). */\nexport function worldPoints(b: RigidBody): number[] {\n if (b.shape.kind !== 'poly') return [];\n const c = dcos(b.a), s = dsin(b.a);\n const p = b.shape.points;\n const out = new Array<number>(p.length);\n for (let k = 0; k < p.length; k += 2) {\n out[k] = b.x + p[k] * c - p[k + 1] * s;\n out[k + 1] = b.y + p[k] * s + p[k + 1] * c;\n }\n return out;\n}\n\nexport function bodyAABB(b: RigidBody): Rect {\n if (b.shape.kind === 'circle') {\n const r = b.shape.r;\n return { x: b.x - r, y: b.y - r, w: r * 2, h: r * 2 };\n }\n const wp = worldPoints(b);\n let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;\n for (let k = 0; k < wp.length; k += 2) {\n if (wp[k] < x0) x0 = wp[k];\n if (wp[k] > x1) x1 = wp[k];\n if (wp[k + 1] < y0) y0 = wp[k + 1];\n if (wp[k + 1] > y1) y1 = wp[k + 1];\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n}\n\n/** Centered box as a CCW convex polygon \u2014 the workhorse shape helper. */\nexport function polygonBox(w: number, h: number): RigidShape {\n const hw = w / 2, hh = h / 2;\n return { kind: 'poly', points: [-hw, -hh, hw, -hh, hw, hh, -hw, hh] };\n}\n", "// Narrowphase collision for rigid bodies: circle\u2013circle, circle\u2013poly, and\n// poly\u2013poly (SAT + reference-face clipping, Box2D-lite style). Produces\n// contact manifolds with STABLE feature ids so the solver can warm-start.\n// Pure functions; deterministic tie-breaks everywhere.\n\nimport { dhypot } from '../core/dmath';\nimport type { RigidBody } from './rigidBody';\nimport { worldPoints } from './rigidBody';\n\nexport interface ContactPoint {\n px: number; py: number; // world contact point\n pen: number; // penetration depth (>0 means overlapping)\n feature: number; // stable id for warm starting\n // solver scratch (accumulated impulses live in the warm cache, not here)\n}\n\nexport interface Manifold {\n a: RigidBody;\n b: RigidBody;\n nx: number; ny: number; // contact normal, from A toward B\n points: ContactPoint[]; // 1..2\n}\n\nfunction collideCircles(a: RigidBody, b: RigidBody): Manifold | null {\n if (a.shape.kind !== 'circle' || b.shape.kind !== 'circle') return null;\n const dx = b.x - a.x, dy = b.y - a.y;\n const rsum = a.shape.r + b.shape.r;\n const d2 = dx * dx + dy * dy;\n if (d2 >= rsum * rsum) return null;\n const d = Math.sqrt(d2);\n // Coincident centers: deterministic fallback normal.\n const nx = d > 1e-9 ? dx / d : 1, ny = d > 1e-9 ? dy / d : 0;\n return {\n a, b, nx, ny,\n points: [{ px: a.x + nx * a.shape.r, py: a.y + ny * a.shape.r, pen: rsum - d, feature: 0 }],\n };\n}\n\n/** Circle B against polygon A. Returns manifold with normal A\u2192B. */\nfunction collidePolyCircle(a: RigidBody, b: RigidBody): Manifold | null {\n if (a.shape.kind !== 'poly' || b.shape.kind !== 'circle') return null;\n const wp = worldPoints(a);\n const n = wp.length / 2;\n const r = b.shape.r;\n // Find the face with max separation of the circle center.\n let bestSep = -Infinity, bestI = 0;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ex = wp[j * 2] - wp[k * 2], ey = wp[j * 2 + 1] - wp[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len; // outward for CCW in y-down coords\n const sep = (b.x - wp[k * 2]) * nx + (b.y - wp[k * 2 + 1]) * ny;\n if (sep > bestSep) { bestSep = sep; bestI = k; }\n }\n if (bestSep > r) return null;\n const k = bestI, j = (bestI + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1], bx2 = wp[j * 2], by2 = wp[j * 2 + 1];\n if (bestSep < 1e-9) {\n // Center inside the poly: push out along the deepest face normal.\n const ex = bx2 - ax, ey = by2 - ay;\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n return { a, b, nx, ny, points: [{ px: b.x - nx * r, py: b.y - ny * r, pen: r - bestSep, feature: bestI }] };\n }\n // Closest point on the face segment (vertex regions included).\n const ex = bx2 - ax, ey = by2 - ay;\n const e2 = ex * ex + ey * ey || 1;\n let t = ((b.x - ax) * ex + (b.y - ay) * ey) / e2;\n t = t < 0 ? 0 : t > 1 ? 1 : t;\n const cx = ax + ex * t, cy = ay + ey * t;\n const dx = b.x - cx, dy = b.y - cy;\n const d2 = dx * dx + dy * dy;\n if (d2 >= r * r) return null;\n const d = Math.sqrt(d2) || 1e-9;\n const nx = dx / d, ny = dy / d;\n return { a, b, nx, ny, points: [{ px: cx, py: cy, pen: r - d, feature: bestI }] };\n}\n\n/** Max separation of B's hull from A's faces; returns [separation, faceIndex]. */\nfunction maxSeparation(wpA: number[], wpB: number[]): [number, number] {\n const nA = wpA.length / 2, nB = wpB.length / 2;\n let best = -Infinity, bestI = 0;\n for (let k = 0; k < nA; k++) {\n const j = (k + 1) % nA;\n const ex = wpA[j * 2] - wpA[k * 2], ey = wpA[j * 2 + 1] - wpA[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n // Deepest point of B along this face normal.\n let minDot = Infinity;\n for (let v = 0; v < nB; v++) {\n const d = (wpB[v * 2] - wpA[k * 2]) * nx + (wpB[v * 2 + 1] - wpA[k * 2 + 1]) * ny;\n if (d < minDot) minDot = d;\n }\n if (minDot > best) { best = minDot; bestI = k; }\n }\n return [best, bestI];\n}\n\nfunction collidePolys(a: RigidBody, b: RigidBody): Manifold | null {\n const wpA = worldPoints(a), wpB = worldPoints(b);\n const [sepA, faceA] = maxSeparation(wpA, wpB);\n if (sepA > 0) return null;\n const [sepB, faceB] = maxSeparation(wpB, wpA);\n if (sepB > 0) return null;\n\n // Reference poly: the one with the larger (less negative) separation.\n // Deterministic bias toward A on near-ties.\n let ref: number[], inc: number[], refFace: number, flip: boolean;\n if (sepB > sepA + 1e-4) { ref = wpB; inc = wpA; refFace = faceB; flip = true; }\n else { ref = wpA; inc = wpB; refFace = faceA; flip = false; }\n\n const nRef = ref.length / 2, nInc = inc.length / 2;\n const rj = (refFace + 1) % nRef;\n const rex = ref[rj * 2] - ref[refFace * 2], rey = ref[rj * 2 + 1] - ref[refFace * 2 + 1];\n const rlen = dhypot(rex, rey) || 1;\n const rnx = rey / rlen, rny = -rex / rlen; // reference face normal (outward)\n const rtx = rex / rlen, rty = rey / rlen; // reference face tangent\n\n // Incident face: most anti-parallel to the reference normal.\n let incFace = 0, minDot = Infinity;\n for (let k = 0; k < nInc; k++) {\n const j = (k + 1) % nInc;\n const ex = inc[j * 2] - inc[k * 2], ey = inc[j * 2 + 1] - inc[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const d = (ey / len) * rnx + (-ex / len) * rny;\n if (d < minDot) { minDot = d; incFace = k; }\n }\n const ij = (incFace + 1) % nInc;\n // Two incident vertices; the feature id is (flip, refFace, slot) \u2014 NOT the\n // clip state. Clip-state ids churn every frame while a stack micro-rocks,\n // which mis-applies warm-start impulses and pumps energy into the pile.\n let v1x = inc[incFace * 2], v1y = inc[incFace * 2 + 1];\n let v2x = inc[ij * 2], v2y = inc[ij * 2 + 1];\n\n // Clip against the two side planes of the reference face.\n const refX = ref[refFace * 2], refY = ref[refFace * 2 + 1];\n const refX2 = ref[rj * 2], refY2 = ref[rj * 2 + 1];\n // Side 1: keep t >= 0 along tangent from refV1; Side 2: keep t <= faceLen.\n for (let side = 0; side < 2; side++) {\n const ox = side === 0 ? refX : refX2, oy = side === 0 ? refY : refY2;\n const sx = side === 0 ? rtx : -rtx, sy = side === 0 ? rty : -rty;\n const d1 = (v1x - ox) * sx + (v1y - oy) * sy;\n const d2 = (v2x - ox) * sx + (v2y - oy) * sy;\n if (d1 < 0 && d2 < 0) return null; // fully clipped (shouldn't happen on overlap)\n if (d1 < 0) {\n const t = d1 / (d1 - d2);\n v1x = v1x + (v2x - v1x) * t; v1y = v1y + (v2y - v1y) * t;\n } else if (d2 < 0) {\n const t = d2 / (d2 - d1);\n v2x = v2x + (v1x - v2x) * t; v2y = v2y + (v1y - v2y) * t;\n }\n }\n\n // Keep points behind the reference face; normal must point A\u2192B.\n const nx = flip ? -rnx : rnx, ny = flip ? -rny : rny;\n const points: ContactPoint[] = [];\n const pen1 = -((v1x - refX) * rnx + (v1y - refY) * rny);\n const pen2 = -((v2x - refX) * rnx + (v2y - refY) * rny);\n // Feature id = (flip, refFace, incFace, slot). Stable while the same two\n // faces stay in contact (micro-rocking stacks reuse warm impulses), but\n // fresh whenever a tumbling box rolls onto its next corner (stale impulses\n // at new lever arms would pump energy).\n const fid = ((flip ? 1 : 0) * 64 + refFace) * 64 + incFace;\n if (pen1 > 0) points.push({ px: v1x, py: v1y, pen: pen1, feature: fid * 2 });\n if (pen2 > 0) points.push({ px: v2x, py: v2y, pen: pen2, feature: fid * 2 + 1 });\n if (points.length === 0) return null;\n return { a, b, nx, ny, points };\n}\n\n/** Dispatch on shape kinds. Normal always points from A toward B. */\nexport function collide(a: RigidBody, b: RigidBody): Manifold | null {\n const ka = a.shape.kind, kb = b.shape.kind;\n if (ka === 'circle' && kb === 'circle') return collideCircles(a, b);\n if (ka === 'poly' && kb === 'poly') return collidePolys(a, b);\n if (ka === 'poly' && kb === 'circle') return collidePolyCircle(a, b);\n // circle vs poly: flip so poly is A, then invert the normal back.\n const m = collidePolyCircle(b, a);\n if (!m) return null;\n return { a, b, nx: -m.nx, ny: -m.ny, points: m.points };\n}\n", "// Joints for the rigid-body engine: distance (rod / rope) and revolute\n// (pin, with optional motor and angle limits). Velocity-level constraints\n// with Baumgarte stabilization, solved inside the same iteration loop as\n// contacts. Plain data + pure solve functions.\n\nimport { dcos, dhypot, dsin } from '../core/dmath';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { getBody, wakeBody } from './rigidBody';\n\nexport interface DistanceJoint {\n kind: 'distance';\n id: number;\n a: number; b: number; // body ids\n ax: number; ay: number; // local anchor on A\n bx: number; by: number; // local anchor on B\n length: number;\n /** Rope mode: only constrain when stretched past `length`. */\n rope: boolean;\n}\n\nexport interface RevoluteJoint {\n kind: 'revolute';\n id: number;\n a: number; b: number;\n ax: number; ay: number;\n bx: number; by: number;\n /** Motor: drive relative angular velocity toward `motorSpeed`. */\n motorSpeed: number;\n maxMotorTorque: number; // 0 = motor off\n /** Angle limits on (b.a - a.a - refAngle); NaN-free: enabled flag. */\n limitLower: number;\n limitUpper: number;\n limitEnabled: boolean;\n refAngle: number;\n}\n\nexport type Joint = DistanceJoint | RevoluteJoint;\n\nexport interface DistanceJointDef {\n a: number; b: number;\n ax?: number; ay?: number; bx?: number; by?: number;\n /** Defaults to the current anchor distance. */\n length?: number;\n rope?: boolean;\n}\n\nexport interface RevoluteJointDef {\n a: number; b: number;\n /** World-space pivot; local anchors are derived from current poses. */\n px: number; py: number;\n motorSpeed?: number;\n maxMotorTorque?: number;\n limitLower?: number;\n limitUpper?: number;\n}\n\nfunction toLocal(b: RigidBody, wx: number, wy: number): [number, number] {\n const c = dcos(b.a), s = dsin(b.a);\n const dx = wx - b.x, dy = wy - b.y;\n return [dx * c + dy * s, -dx * s + dy * c];\n}\n\nfunction anchorWorld(b: RigidBody, lx: number, ly: number): [number, number] {\n const c = dcos(b.a), s = dsin(b.a);\n return [b.x + lx * c - ly * s, b.y + lx * s + ly * c];\n}\n\nexport function addDistanceJoint(rw: RigidWorld, def: DistanceJointDef): number {\n const A = getBody(rw, def.a), B = getBody(rw, def.b);\n if (!A || !B) throw new Error(`distance joint: missing body ${def.a}/${def.b}`);\n const ax = def.ax ?? 0, ay = def.ay ?? 0, bx = def.bx ?? 0, by = def.by ?? 0;\n const [wax, way] = anchorWorld(A, ax, ay);\n const [wbx, wby] = anchorWorld(B, bx, by);\n const j: DistanceJoint = {\n kind: 'distance', id: rw.nextId++,\n a: def.a, b: def.b, ax, ay, bx, by,\n length: def.length ?? dhypot(wbx - wax, wby - way),\n rope: def.rope ?? false,\n };\n rw.joints.push(j);\n wakeBody(A); wakeBody(B);\n return j.id;\n}\n\nexport function addRevoluteJoint(rw: RigidWorld, def: RevoluteJointDef): number {\n const A = getBody(rw, def.a), B = getBody(rw, def.b);\n if (!A || !B) throw new Error(`revolute joint: missing body ${def.a}/${def.b}`);\n const [ax, ay] = toLocal(A, def.px, def.py);\n const [bx, by] = toLocal(B, def.px, def.py);\n const j: RevoluteJoint = {\n kind: 'revolute', id: rw.nextId++,\n a: def.a, b: def.b, ax, ay, bx, by,\n motorSpeed: def.motorSpeed ?? 0,\n maxMotorTorque: def.maxMotorTorque ?? 0,\n limitLower: def.limitLower ?? 0,\n limitUpper: def.limitUpper ?? 0,\n limitEnabled: def.limitLower !== undefined || def.limitUpper !== undefined,\n refAngle: B.a - A.a,\n };\n rw.joints.push(j);\n wakeBody(A); wakeBody(B);\n return j.id;\n}\n\nexport function getJoint(rw: RigidWorld, id: number): Joint | undefined {\n for (const j of rw.joints) if (j.id === id) return j;\n return undefined;\n}\n\nexport function removeJoint(rw: RigidWorld, id: number): void {\n rw.joints = rw.joints.filter((j) => j.id !== id);\n}\n\n/** Per-step scratch for accumulated-impulse clamping (one per joint). */\nexport interface JointScratch {\n motorImpulse: number;\n}\n\n/** One velocity iteration for a single joint. `bias` uses dt for Baumgarte. */\nexport function solveJoint(j: Joint, A: RigidBody, B: RigidBody, dt: number, scratch: JointScratch): void {\n const [wax, way] = anchorWorld(A, j.ax, j.ay);\n const [wbx, wby] = anchorWorld(B, j.bx, j.by);\n const rax = wax - A.x, ray = way - A.y;\n const rbx = wbx - B.x, rby = wby - B.y;\n\n if (j.kind === 'distance') {\n let dx = wbx - wax, dy = wby - way;\n const dist = dhypot(dx, dy);\n if (dist < 1e-9) return;\n dx /= dist; dy /= dist;\n const stretch = dist - j.length;\n if (j.rope && stretch <= 0) return; // slack rope\n // Relative velocity along the axis.\n const vax = A.vx - A.w * ray, vay = A.vy + A.w * rax;\n const vbx = B.vx - B.w * rby, vby = B.vy + B.w * rbx;\n const vrel = (vbx - vax) * dx + (vby - vay) * dy;\n const crossA = rax * dy - ray * dx;\n const crossB = rbx * dy - rby * dx;\n const k = A.invM + B.invM + A.invI * crossA * crossA + B.invI * crossB * crossB;\n if (k < 1e-12) return;\n const bias = (0.2 / dt) * stretch;\n let lambda = -(vrel + bias) / k;\n if (j.rope && lambda > 0) lambda = 0; // rope can only pull inward\n const ix = dx * lambda, iy = dy * lambda;\n A.vx -= ix * A.invM; A.vy -= iy * A.invM;\n A.w -= (rax * iy - ray * ix) * A.invI;\n B.vx += ix * B.invM; B.vy += iy * B.invM;\n B.w += (rbx * iy - rby * ix) * B.invI;\n return;\n }\n\n // Revolute: motor + limits first (1D angular), then point-to-point (2D).\n if (j.maxMotorTorque > 0) {\n const kw = A.invI + B.invI;\n if (kw > 1e-12) {\n const cdot = B.w - A.w - j.motorSpeed;\n const imp = -cdot / kw;\n // Accumulated clamp: total motor impulse this STEP \u2264 maxMotorTorque\u00B7dt,\n // regardless of iteration count (Box2D semantics).\n const maxImp = j.maxMotorTorque * dt;\n const acc0 = scratch.motorImpulse;\n scratch.motorImpulse = Math.min(Math.max(acc0 + imp, -maxImp), maxImp);\n const applied = scratch.motorImpulse - acc0;\n A.w -= applied * A.invI;\n B.w += applied * B.invI;\n }\n }\n if (j.limitEnabled) {\n const kw = A.invI + B.invI;\n if (kw > 1e-12) {\n const angle = B.a - A.a - j.refAngle;\n let c = 0;\n if (angle < j.limitLower) c = angle - j.limitLower;\n else if (angle > j.limitUpper) c = angle - j.limitUpper;\n if (c !== 0) {\n const cdot = B.w - A.w;\n const imp = -(cdot + (0.2 / dt) * c) / kw;\n // Only push back toward the range.\n if ((c < 0 && imp > 0) || (c > 0 && imp < 0)) {\n A.w -= imp * A.invI;\n B.w += imp * B.invI;\n }\n }\n }\n }\n // Point-to-point: solve the 2x2 system K * lambda = -(vrel + bias).\n const vax = A.vx - A.w * ray, vay = A.vy + A.w * rax;\n const vbx = B.vx - B.w * rby, vby = B.vy + B.w * rbx;\n const cx = wbx - wax, cy = wby - way;\n const vrx = vbx - vax + (0.2 / dt) * cx;\n const vry = vby - vay + (0.2 / dt) * cy;\n const k11 = A.invM + B.invM + A.invI * ray * ray + B.invI * rby * rby;\n const k12 = -A.invI * rax * ray - B.invI * rbx * rby;\n const k22 = A.invM + B.invM + A.invI * rax * rax + B.invI * rbx * rbx;\n const det = k11 * k22 - k12 * k12;\n if (Math.abs(det) < 1e-12) return;\n const ix = -(k22 * vrx - k12 * vry) / det;\n const iy = -(k11 * vry - k12 * vrx) / det;\n A.vx -= ix * A.invM; A.vy -= iy * A.invM;\n A.w -= (rax * iy - ray * ix) * A.invI;\n B.vx += ix * B.invM; B.vy += iy * B.invM;\n B.w += (rbx * iy - rby * ix) * B.invI;\n}\n", "// The rigid-body step pipeline: integrate forces \u2192 broadphase (spatial hash,\n// ordered pairs) \u2192 narrowphase \u2192 warm-started sequential-impulse solve\n// (joints + contacts) \u2192 integrate positions \u2192 bullet CCD \u2192 sleeping.\n//\n// Penetration recovery uses SPLIT IMPULSE (Chipmunk-style bias velocities): a\n// separate pseudo-velocity field feels the Baumgarte push, integrates into\n// POSITION only, and is discarded \u2014 so stacks recover overlap without gaining\n// kinetic energy, settle truly calm, and can sleep.\n//\n// Deterministic: bodies iterate in array order, pairs in (idA, idB) order,\n// and the warm-start cache is rebuilt every step from plain data.\n\nimport { dhypot } from '../core/dmath';\nimport { SpatialHash } from './spatialHash';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { bodyAABB, getBody, wakeBody, worldPoints } from './rigidBody';\nimport { collide, type Manifold } from './rigidCollide';\nimport { solveJoint } from './rigidJoints';\n\nexport interface ContactEvent {\n a: number; b: number; // body ids (a < b)\n px: number; py: number; // representative contact point\n nx: number; ny: number; // normal a\u2192b\n /** Total normal impulse this step \u2014 scales with hit violence. */\n impulse: number;\n /** Sensor overlap (no collision response was applied). */\n sensor: boolean;\n}\n\nconst SLOP = 0.5; // allowed overlap, px\nconst BIAS = 0.2; // Baumgarte factor (position recovery rate)\nconst REST_THRESHOLD = 40; // px/s \u2014 below this, no bounce\nconst SLEEP_LIN2 = 64; // (8 px/s)\u00B2 \u2014 resting piles hum at 5\u201320 px/s\nconst SLEEP_RIM = 8; // px/s of rim speed (|w|\u00B7sleepR)\nconst TIME_TO_SLEEP = 0.5; // s\nconst WAKE_LIN2 = 100; // partner speed\u00B2 that wakes a sleeper\n\ninterface SolvePoint {\n rax: number; ray: number; rbx: number; rby: number;\n pen: number;\n massN: number; massT: number;\n restBias: number; // restitution target velocity (real)\n posBias: number; // penetration target velocity (pseudo)\n pn: number; pt: number; // accumulated impulses (real)\n pb: number; // accumulated impulse (pseudo)\n key: string;\n}\n\ninterface SolveManifold {\n m: Manifold;\n ia: number; ib: number; // body array indices (for the bias fields)\n points: SolvePoint[];\n friction: number;\n}\n\nfunction canCollide(a: RigidBody, b: RigidBody): boolean {\n if (a.invM === 0 && b.invM === 0 && a.kind !== 'kinematic' && b.kind !== 'kinematic' && !a.sensor && !b.sensor) return false;\n return (a.mask & b.layer) !== 0 && (b.mask & a.layer) !== 0;\n}\n\nexport function rigidStep(rw: RigidWorld, dt: number): ContactEvent[] {\n const bodies = rw.bodies;\n const events: ContactEvent[] = [];\n if (dt <= 0) return events;\n\n // \u2500\u2500 1 \u00B7 integrate forces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) { b.fx = 0; b.fy = 0; b.torque = 0; continue; }\n b.vx += (rw.gravityX * b.gravityScale + b.fx * b.invM) * dt;\n b.vy += (rw.gravityY * b.gravityScale + b.fy * b.invM) * dt;\n b.w += b.torque * b.invI * dt;\n const ld = 1 / (1 + b.linDamp * dt);\n b.vx *= ld; b.vy *= ld;\n b.w *= 1 / (1 + b.angDamp * dt);\n b.fx = 0; b.fy = 0; b.torque = 0;\n }\n\n // \u2500\u2500 2 \u00B7 broadphase: spatial hash, pairs in deterministic order \u2500\u2500\u2500\n const hash = new SpatialHash<RigidBody>(rw.cellSize);\n const indexOf = new Map<RigidBody, number>();\n for (let k = 0; k < bodies.length; k++) {\n hash.insert(bodies[k], bodyAABB(bodies[k]));\n indexOf.set(bodies[k], k);\n }\n const manifolds: SolveManifold[] = [];\n const seen = new Set<number>();\n // Joint-connected bodies never collide with each other (Box2D convention \u2014\n // a pinned wheel must not grind against its own anchor).\n const jointed = new Set<number>();\n for (const j of rw.joints) {\n const lo = Math.min(j.a, j.b), hi = Math.max(j.a, j.b);\n jointed.add(lo * 1048576 + hi);\n }\n for (let k = 0; k < bodies.length; k++) {\n const a = bodies[k];\n const near = hash.query(bodyAABB(a));\n for (const b of near) {\n if (b.id <= a.id) continue;\n const packed = a.id * 1048576 + b.id;\n if (seen.has(packed)) continue;\n seen.add(packed);\n if (jointed.has(packed)) continue;\n if (!canCollide(a, b)) continue;\n // Skip unless at least one side is an AWAKE mover \u2014 this is what lets a\n // settled stack truly freeze (a sleeping box on a static floor gets no\n // solver impulses at all).\n const activeA = !a.sleeping && a.kind !== 'static';\n const activeB = !b.sleeping && b.kind !== 'static';\n if (!activeA && !activeB) continue;\n const m = collide(a, b);\n if (!m) continue;\n // Wake a sleeper hit by something moving.\n const wakeIf = (s: RigidBody, o: RigidBody) => {\n if (s.sleeping && (o.vx * o.vx + o.vy * o.vy > WAKE_LIN2 || o.kind === 'kinematic')) wakeBody(s);\n };\n wakeIf(a, b); wakeIf(b, a);\n if (a.sensor || b.sensor) {\n events.push({ a: a.id, b: b.id, px: m.points[0].px, py: m.points[0].py, nx: m.nx, ny: m.ny, impulse: 0, sensor: true });\n continue;\n }\n // Pre-step: effective masses, restitution capture, warm start.\n const sp: SolvePoint[] = [];\n const tx = -m.ny, ty = m.nx;\n for (const p of m.points) {\n const rax = p.px - a.x, ray = p.py - a.y;\n const rbx = p.px - b.x, rby = p.py - b.y;\n const crossAN = rax * m.ny - ray * m.nx;\n const crossBN = rbx * m.ny - rby * m.nx;\n const kn = a.invM + b.invM + a.invI * crossAN * crossAN + b.invI * crossBN * crossBN;\n const crossAT = rax * ty - ray * tx;\n const crossBT = rbx * ty - rby * tx;\n const kt = a.invM + b.invM + a.invI * crossAT * crossAT + b.invI * crossBT * crossBT;\n // Approach speed for restitution (captured before solving).\n const vrx = b.vx - b.w * rby - a.vx + a.w * ray;\n const vry = b.vy + b.w * rbx - a.vy - a.w * rax;\n const vn = vrx * m.nx + vry * m.ny;\n const e = Math.max(a.restitution, b.restitution);\n const key = `${a.id}:${b.id}:${p.feature}`;\n const warm = rw.warm[key];\n const sp1: SolvePoint = {\n rax, ray, rbx, rby, pen: p.pen,\n massN: kn > 1e-12 ? 1 / kn : 0,\n massT: kt > 1e-12 ? 1 / kt : 0,\n restBias: vn < -REST_THRESHOLD ? -e * vn : 0,\n posBias: (BIAS / dt) * Math.max(0, p.pen - SLOP),\n pn: warm ? warm[0] : 0,\n pt: warm ? warm[1] : 0,\n pb: 0,\n key,\n };\n sp.push(sp1);\n }\n manifolds.push({ m, ia: k, ib: indexOf.get(b)!, points: sp, friction: Math.sqrt(a.friction * b.friction) });\n }\n }\n\n // Warm-start pass \u2014 applied only AFTER every point captured its clean\n // approach velocity. Interleaving capture with application double-counts\n // restitution (the bounce target re-adds speed warm-starting already\n // reversed) and pumps energy into resting piles.\n for (const sm of manifolds) {\n const { a, b, nx, ny } = sm.m;\n const tx = -ny, ty = nx;\n for (const p of sm.points) {\n if (p.pn === 0 && p.pt === 0) continue;\n const ix = nx * p.pn + tx * p.pt;\n const iy = ny * p.pn + ty * p.pt;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n }\n }\n\n // Solve in SUPPORT ORDER \u2014 static pairs first, then bottom-up (larger y\n // first in y-down coords). Sequential impulse converges a resting pile in\n // far fewer iterations when impulses propagate up the support chain.\n // Deterministic: ties break on (a.id, b.id).\n manifolds.sort((p, q) => {\n const ps = p.m.a.invM === 0 || p.m.b.invM === 0 ? 0 : 1;\n const qs = q.m.a.invM === 0 || q.m.b.invM === 0 ? 0 : 1;\n if (ps !== qs) return ps - qs;\n const py = Math.max(p.m.a.y, p.m.b.y), qy = Math.max(q.m.a.y, q.m.b.y);\n if (py !== qy) return qy - py;\n if (p.m.a.id !== q.m.a.id) return p.m.a.id - q.m.a.id;\n return p.m.b.id - q.m.b.id;\n });\n\n // Pseudo-velocity fields for split-impulse position recovery (scratch \u2014\n // never serialized, discarded at the end of the step).\n const bvx = new Float64Array(bodies.length);\n const bvy = new Float64Array(bodies.length);\n const bw = new Float64Array(bodies.length);\n\n // \u2500\u2500 3 \u00B7 velocity iterations: joints then contacts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const jointScratch = rw.joints.map(() => ({ motorImpulse: 0 }));\n for (let iter = 0; iter < rw.iterations; iter++) {\n for (let jk = 0; jk < rw.joints.length; jk++) {\n const j = rw.joints[jk];\n const A = getBody(rw, j.a), B = getBody(rw, j.b);\n if (!A || !B) continue;\n if (A.sleeping && B.sleeping) continue;\n if (A.sleeping) wakeBody(A);\n if (B.sleeping) wakeBody(B);\n solveJoint(j, A, B, dt, jointScratch[jk]);\n }\n for (const sm of manifolds) {\n const { a, b, nx, ny } = sm.m;\n const { ia, ib } = sm;\n const tx = -ny, ty = nx;\n for (const p of sm.points) {\n // Normal impulse (real velocities; restitution target only).\n let vrx = b.vx - b.w * p.rby - a.vx + a.w * p.ray;\n let vry = b.vy + b.w * p.rbx - a.vy - a.w * p.rax;\n const vn = vrx * nx + vry * ny;\n let dPn = p.massN * (p.restBias - vn);\n const pn0 = p.pn;\n p.pn = Math.max(pn0 + dPn, 0);\n dPn = p.pn - pn0;\n let ix = nx * dPn, iy = ny * dPn;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n // Friction impulse (clamped by the friction cone).\n vrx = b.vx - b.w * p.rby - a.vx + a.w * p.ray;\n vry = b.vy + b.w * p.rbx - a.vy - a.w * p.rax;\n const vt = vrx * tx + vry * ty;\n let dPt = p.massT * -vt;\n const maxPt = sm.friction * p.pn;\n const pt0 = p.pt;\n p.pt = Math.min(Math.max(pt0 + dPt, -maxPt), maxPt);\n dPt = p.pt - pt0;\n ix = tx * dPt; iy = ty * dPt;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n // Split-impulse penetration recovery (pseudo velocities \u2192 position\n // only; no kinetic energy enters the sim).\n if (p.posBias > 0) {\n const vbn = (bvx[ib] - bw[ib] * p.rby - bvx[ia] + bw[ia] * p.ray) * nx\n + (bvy[ib] + bw[ib] * p.rbx - bvy[ia] - bw[ia] * p.rax) * ny;\n let dPb = p.massN * (p.posBias - vbn);\n const pb0 = p.pb;\n p.pb = Math.max(pb0 + dPb, 0);\n dPb = p.pb - pb0;\n const bix = nx * dPb, biy = ny * dPb;\n // Linear-only pseudo push: rotating positions without refreshing\n // manifolds amplifies stack rocking, so pseudo torque stays off.\n bvx[ia] -= bix * a.invM; bvy[ia] -= biy * a.invM;\n bvx[ib] += bix * b.invM; bvy[ib] += biy * b.invM;\n }\n }\n }\n }\n\n // \u2500\u2500 4 \u00B7 integrate positions (real + pseudo velocity; pseudo dies) \u2500\n const preX: number[] = [], preY: number[] = [];\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n preX.push(b.x); preY.push(b.y);\n if (b.invM === 0 && b.kind !== 'kinematic') continue;\n if (b.sleeping) continue;\n b.x += (b.vx + bvx[k]) * dt;\n b.y += (b.vy + bvy[k]) * dt;\n b.a += (b.w + bw[k]) * dt;\n }\n\n // \u2500\u2500 5 \u00B7 bullet CCD (swept circle vs everything it can hit) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (!b.bullet || b.shape.kind !== 'circle' || b.sleeping) continue;\n const dx = b.x - preX[k], dy = b.y - preY[k];\n if (dx * dx + dy * dy < 1) continue;\n let bestT = 1;\n for (let q = 0; q < bodies.length; q++) {\n const o = bodies[q];\n if (o === b || o.bullet || o.sensor || !canCollide(b, o)) continue;\n const t = sweepCircle(preX[k], preY[k], dx, dy, b.shape.r, o);\n if (t >= 0 && t < bestT) bestT = t;\n }\n if (bestT < 1) {\n // Stop just PAST the impact time: a sub-slop penetration must exist or\n // the discrete narrowphase (pen > 0) never sees a contact, and the body\n // hangs on the surface accumulating gravity velocity forever.\n const len = dhypot(dx, dy) || 1;\n b.x = preX[k] + dx * bestT + (dx / len) * 0.4;\n b.y = preY[k] + dy * bestT + (dy / len) * 0.4;\n // leave velocity intact \u2014 next step's contact solve applies restitution.\n }\n }\n\n // \u2500\u2500 6 \u00B7 sleeping \u2014 ISLAND-atomic (a pile sleeps as one, or not at all) \u2500\n // Union-find over dynamic\u2013dynamic contacts and joints; static bodies do\n // not conduct (two piles on one floor are separate islands).\n const touching = new Set<number>();\n const parent: number[] = [];\n for (let k = 0; k < bodies.length; k++) parent.push(k);\n const find = (x: number): number => {\n while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n return x;\n };\n const union = (x: number, y: number) => { parent[find(x)] = find(y); };\n for (const sm of manifolds) {\n touching.add(sm.m.a.id); touching.add(sm.m.b.id);\n if (sm.m.a.kind === 'dynamic' && sm.m.b.kind === 'dynamic') union(sm.ia, sm.ib);\n }\n for (const j of rw.joints) {\n touching.add(j.a); touching.add(j.b);\n const A = getBody(rw, j.a), B = getBody(rw, j.b);\n if (A?.kind === 'dynamic' && B?.kind === 'dynamic') union(indexOf.get(A)!, indexOf.get(B)!);\n }\n // Per-body calm clocks (a solver-injected velocity also re-wakes a sleeper).\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic') continue;\n const lin2 = b.vx * b.vx + b.vy * b.vy;\n if (b.sleeping) {\n if (lin2 > WAKE_LIN2) wakeBody(b);\n continue;\n }\n if (!b.canSleep || !touching.has(b.id)) { b.sleepTime = 0; continue; }\n b.sleepTime = lin2 < SLEEP_LIN2 && Math.abs(b.w) * b.sleepR < SLEEP_RIM ? b.sleepTime + dt : 0;\n }\n // An island sleeps when EVERY member has been calm long enough.\n const islandMin = new Map<number, number>();\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) continue;\n const root = find(k);\n const t = !b.canSleep || !touching.has(b.id) ? -1 : b.sleepTime;\n const cur = islandMin.get(root);\n islandMin.set(root, cur === undefined ? t : Math.min(cur, t));\n }\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) continue;\n if ((islandMin.get(find(k)) ?? -1) >= TIME_TO_SLEEP) {\n b.sleeping = true;\n b.vx = 0; b.vy = 0; b.w = 0;\n }\n }\n\n // \u2500\u2500 7 \u00B7 contact events + rebuild the warm cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const warm: Record<string, [number, number]> = {};\n for (const sm of manifolds) {\n let total = 0;\n for (const p of sm.points) {\n total += p.pn;\n if (p.pn !== 0 || p.pt !== 0) warm[p.key] = [p.pn, p.pt];\n }\n const p0 = sm.m.points[0];\n events.push({\n a: sm.m.a.id, b: sm.m.b.id, px: p0.px, py: p0.py,\n nx: sm.m.nx, ny: sm.m.ny, impulse: total, sensor: false,\n });\n }\n rw.warm = warm;\n return events;\n}\n\n/** Earliest t\u2208[0,1] where a circle swept along (dx,dy) first touches body o, or -1. */\nfunction sweepCircle(x0: number, y0: number, dx: number, dy: number, r: number, o: RigidBody): number {\n if (o.shape.kind === 'circle') {\n return sweepVsCircle(x0, y0, dx, dy, o.x, o.y, r + o.shape.r);\n }\n // Poly: Minkowski sum = edges offset outward by r + vertex circles of radius r.\n const wp = worldPoints(o);\n const n = wp.length / 2;\n let best = -1;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1];\n const bx = wp[j * 2], by = wp[j * 2 + 1];\n const ex = bx - ax, ey = by - ay;\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n // Offset edge segment \u2014 only FRONT-side crossings count (motion into the\n // face), and only from a start point that is NOT already touching the\n // face. A touching/overlapping start is the contact solver's regime: TOI\n // would clamp t\u22480 every frame and pin a sliding ball in place.\n const startSep = (x0 - ax) * nx + (y0 - ay) * ny - r;\n if (dx * nx + dy * ny < 0 && startSep > 0.5) {\n const t = sweepVsSegment(x0, y0, dx, dy, ax + nx * r, ay + ny * r, bx + nx * r, by + ny * r);\n if (t >= 0 && (best < 0 || t < best)) best = t;\n }\n // Vertex circle.\n const tv = sweepVsCircle(x0, y0, dx, dy, ax, ay, r);\n if (tv >= 0 && (best < 0 || tv < best)) best = tv;\n }\n return best;\n}\n\nfunction sweepVsCircle(x0: number, y0: number, dx: number, dy: number, cx: number, cy: number, R: number): number {\n const fx = x0 - cx, fy = y0 - cy;\n const a = dx * dx + dy * dy;\n if (a < 1e-12) return -1;\n const b = 2 * (fx * dx + fy * dy);\n // Already touching or overlapping (within a slop ring): the contact solver\n // owns this \u2014 a TOI of ~0 would pin a rolling/sliding ball in place.\n if (fx * fx + fy * fy < (R + 0.5) * (R + 0.5)) return -1;\n const c = fx * fx + fy * fy - R * R;\n const disc = b * b - 4 * a * c;\n if (disc < 0) return -1;\n const t = (-b - Math.sqrt(disc)) / (2 * a);\n return t >= 0 && t <= 1 ? t : -1;\n}\n\nfunction sweepVsSegment(x0: number, y0: number, dx: number, dy: number, ax: number, ay: number, bx: number, by: number): number {\n const ex = bx - ax, ey = by - ay;\n const denom = dx * ey - dy * ex;\n if (Math.abs(denom) < 1e-12) return -1;\n const t = ((ax - x0) * ey - (ay - y0) * ex) / denom;\n const s = ((ax - x0) * dy - (ay - y0) * dx) / denom;\n return t >= 0 && t <= 1 && s >= 0 && s <= 1 ? t : -1;\n}\n", "// Spatial queries against rigid bodies: point tests and raycasts.\n// Pure functions; results are deterministic (bodies scanned in array order).\n\nimport { dhypot } from '../core/dmath';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { worldPoints } from './rigidBody';\n\nexport interface RigidRayHit {\n id: number;\n t: number; // fraction along the ray [0,1]\n x: number; y: number; // hit point\n nx: number; ny: number; // surface normal\n}\n\n/** Is a world point inside this body's shape? */\nexport function bodyContains(b: RigidBody, x: number, y: number): boolean {\n if (b.shape.kind === 'circle') {\n const dx = x - b.x, dy = y - b.y;\n return dx * dx + dy * dy <= b.shape.r * b.shape.r;\n }\n const wp = worldPoints(b);\n const n = wp.length / 2;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ex = wp[j * 2] - wp[k * 2], ey = wp[j * 2 + 1] - wp[k * 2 + 1];\n if ((x - wp[k * 2]) * ey - (y - wp[k * 2 + 1]) * ex > 0) return false;\n }\n return true;\n}\n\n/** First body containing the point (topmost = last added wins ties via scan order). */\nexport function pointQuery(rw: RigidWorld, x: number, y: number, mask = 0xffff): RigidBody | undefined {\n let hit: RigidBody | undefined;\n for (const b of rw.bodies) if ((b.layer & mask) !== 0 && bodyContains(b, x, y)) hit = b;\n return hit;\n}\n\nfunction rayCircle(x0: number, y0: number, dx: number, dy: number, cx: number, cy: number, r: number): number {\n const fx = x0 - cx, fy = y0 - cy;\n const a = dx * dx + dy * dy;\n if (a < 1e-12) return -1;\n const b = 2 * (fx * dx + fy * dy);\n const c = fx * fx + fy * fy - r * r;\n const disc = b * b - 4 * a * c;\n if (disc < 0) return -1;\n const t = (-b - Math.sqrt(disc)) / (2 * a);\n return t >= 0 && t <= 1 ? t : -1;\n}\n\n/** Closest hit along the segment (x0,y0)\u2192(x1,y1), or null. */\nexport function rayCastRigid(rw: RigidWorld, x0: number, y0: number, x1: number, y1: number, mask = 0xffff): RigidRayHit | null {\n const dx = x1 - x0, dy = y1 - y0;\n let best: RigidRayHit | null = null;\n for (const b of rw.bodies) {\n if ((b.layer & mask) === 0) continue;\n if (b.shape.kind === 'circle') {\n const t = rayCircle(x0, y0, dx, dy, b.x, b.y, b.shape.r);\n if (t >= 0 && (!best || t < best.t)) {\n const hx = x0 + dx * t, hy = y0 + dy * t;\n const len = dhypot(hx - b.x, hy - b.y) || 1;\n best = { id: b.id, t, x: hx, y: hy, nx: (hx - b.x) / len, ny: (hy - b.y) / len };\n }\n continue;\n }\n const wp = worldPoints(b);\n const n = wp.length / 2;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1];\n const ex = wp[j * 2] - ax, ey = wp[j * 2 + 1] - ay;\n const denom = dx * ey - dy * ex;\n if (Math.abs(denom) < 1e-12) continue;\n const t = ((ax - x0) * ey - (ay - y0) * ex) / denom;\n const s = ((ax - x0) * dy - (ay - y0) * dx) / denom;\n if (t < 0 || t > 1 || s < 0 || s > 1) continue;\n if (!best || t < best.t) {\n const len = dhypot(ex, ey) || 1;\n best = { id: b.id, t, x: x0 + dx * t, y: y0 + dy * t, nx: ey / len, ny: -ex / len };\n }\n }\n }\n return best;\n}\n", "// The display list: a flat, backend-agnostic vocabulary of draw commands.\n// The scene tree *projects* to DrawCommand[]; a backend (SVG/Canvas/Headless)\n// consumes them. Pure data \u2014 no browser types \u2014 so the projection is testable.\n\nimport type { Transform } from '../core/math';\n\nexport interface Paint {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n /** Round line joins/caps for organic shapes. */\n round?: boolean;\n}\n\nexport type TextAlign = 'left' | 'center' | 'right';\n\ninterface Base extends Paint {\n /** World transform (design-space). */\n transform: Transform;\n /** Painter's-order key; ties broken by tree order. Default 0. */\n z: number;\n}\n\nexport interface RectCommand extends Base {\n kind: 'rect';\n x: number;\n y: number;\n w: number;\n h: number;\n /** Corner radius. */\n r?: number;\n}\n\nexport interface CircleCommand extends Base {\n kind: 'circle';\n cx: number;\n cy: number;\n radius: number;\n}\n\nexport interface PolyCommand extends Base {\n kind: 'poly';\n /** Flat [x0,y0,x1,y1,\u2026] in local space. */\n points: number[];\n closed: boolean;\n}\n\nexport interface PathCommand extends Base {\n kind: 'path';\n /** SVG path data in local space. */\n d: string;\n}\n\nexport interface TextCommand extends Base {\n kind: 'text';\n text: string;\n x: number;\n y: number;\n size: number;\n font?: string;\n align?: TextAlign;\n weight?: number;\n}\n\nexport interface ImageCommand extends Base {\n kind: 'image';\n /** data: URI or path. */\n href: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport type DrawCommand =\n | RectCommand\n | CircleCommand\n | PolyCommand\n | PathCommand\n | TextCommand\n | ImageCommand;\n\n/** Stable painter's sort: by z, then original index (tree order) as tiebreak. */\nexport function sortCommands(cmds: DrawCommand[]): DrawCommand[] {\n return cmds\n .map((c, i) => [c, i] as const)\n .sort((a, b) => a[0].z - b[0].z || a[1] - b[1])\n .map(([c]) => c);\n}\n", "// Pure display-list \u2192 SVG markup. No DOM required, so it runs in Node \u2014 which\n// means the engine can produce a *vector screenshot* of any frame headlessly\n// (an AI-first win: judge layout from a file, no browser, no GPU, no fuzz).\n// The DOM SvgRenderer reuses this; tests assert on it directly.\n\nimport { sortCommands, type DrawCommand, type Paint } from './commands';\nimport type { Transform } from '../core/math';\n\nconst n = (v: number): string => (Number.isInteger(v) ? String(v) : (Math.round(v * 1000) / 1000).toString());\n\nfunction matrix(t: Transform): string {\n return `matrix(${n(t.a)} ${n(t.b)} ${n(t.c)} ${n(t.d)} ${n(t.e)} ${n(t.f)})`;\n}\n\nfunction paintAttrs(p: Paint): string {\n const parts: string[] = [];\n parts.push(`fill=\"${p.fill ?? 'none'}\"`);\n if (p.stroke) {\n parts.push(`stroke=\"${p.stroke}\"`);\n parts.push(`stroke-width=\"${n(p.strokeWidth ?? 1)}\"`);\n if (p.round) parts.push('stroke-linejoin=\"round\" stroke-linecap=\"round\"');\n }\n if (p.opacity !== undefined && p.opacity !== 1) parts.push(`opacity=\"${n(p.opacity)}\"`);\n return parts.join(' ');\n}\n\nfunction escapeText(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nfunction commandToSVG(c: DrawCommand): string {\n const tf = `transform=\"${matrix(c.transform)}\"`;\n const paint = paintAttrs(c);\n switch (c.kind) {\n case 'rect':\n return `<rect x=\"${n(c.x)}\" y=\"${n(c.y)}\" width=\"${n(c.w)}\" height=\"${n(c.h)}\"${c.r ? ` rx=\"${n(c.r)}\"` : ''} ${tf} ${paint}/>`;\n case 'circle':\n return `<circle cx=\"${n(c.cx)}\" cy=\"${n(c.cy)}\" r=\"${n(c.radius)}\" ${tf} ${paint}/>`;\n case 'poly': {\n const pts = [];\n for (let i = 0; i < c.points.length; i += 2) pts.push(`${n(c.points[i])},${n(c.points[i + 1])}`);\n const tag = c.closed ? 'polygon' : 'polyline';\n return `<${tag} points=\"${pts.join(' ')}\" ${tf} ${paint}/>`;\n }\n case 'path':\n return `<path d=\"${c.d}\" ${tf} ${paint}/>`;\n case 'text': {\n const anchor = c.align === 'center' ? 'middle' : c.align === 'right' ? 'end' : 'start';\n const font = c.font ? ` font-family=\"${c.font}\"` : '';\n const weight = c.weight ? ` font-weight=\"${c.weight}\"` : '';\n const fill = c.fill ?? '#000';\n return `<text x=\"${n(c.x)}\" y=\"${n(c.y)}\" font-size=\"${n(c.size)}\" text-anchor=\"${anchor}\" dominant-baseline=\"middle\"${font}${weight} fill=\"${fill}\"${c.opacity !== undefined && c.opacity !== 1 ? ` opacity=\"${n(c.opacity)}\"` : ''} ${tf}>${escapeText(c.text)}</text>`;\n }\n case 'image':\n return `<image href=\"${c.href}\" x=\"${n(c.x)}\" y=\"${n(c.y)}\" width=\"${n(c.w)}\" height=\"${n(c.h)}\" ${tf}${c.opacity !== undefined && c.opacity !== 1 ? ` opacity=\"${n(c.opacity)}\"` : ''}/>`;\n }\n}\n\n/** Inner SVG markup for a display list (no wrapping <svg>). */\nexport function commandsToSVGInner(commands: DrawCommand[]): string {\n return sortCommands(commands).map(commandToSVG).join('');\n}\n\n/** A complete, standalone SVG document string for a frame \u2014 a headless screenshot. */\nexport function renderToSVGString(\n commands: DrawCommand[],\n width: number,\n height: number,\n background = '#ffffff',\n): string {\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${width} ${height}\" width=\"${width}\" height=\"${height}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${width}\" height=\"${height}\" fill=\"${background}\"/>` +\n commandsToSVGInner(commands) +\n `</svg>`\n );\n}\n", "// SVG DOM backend. Resolution-independent (crisp at any DPR \u2014 the OHYG lesson:\n// SVG sidesteps canvas text fuzz entirely) and DOM-inspectable, which makes\n// browser verification trivial: querySelector IS the probe.\n\nimport type { DrawCommand } from './commands';\nimport type { Renderer, RendererConfig } from './renderer';\nimport { commandsToSVGInner } from './svgString';\n\nconst SVGNS = 'http://www.w3.org/2000/svg';\n\nexport class SvgRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private svg: SVGSVGElement;\n private bg: SVGRectElement;\n private layer: SVGGElement;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n\n this.svg = document.createElementNS(SVGNS, 'svg');\n this.svg.setAttribute('viewBox', `0 0 ${this.width} ${this.height}`);\n this.svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\n this.svg.style.width = '100%';\n this.svg.style.height = '100%';\n this.svg.style.display = 'block';\n\n this.bg = document.createElementNS(SVGNS, 'rect');\n this.bg.setAttribute('x', '0');\n this.bg.setAttribute('y', '0');\n this.bg.setAttribute('width', String(this.width));\n this.bg.setAttribute('height', String(this.height));\n this.bg.setAttribute('fill', this.background);\n this.svg.appendChild(this.bg);\n\n this.layer = document.createElementNS(SVGNS, 'g');\n this.svg.appendChild(this.layer);\n }\n\n mount(parent: HTMLElement): void {\n parent.appendChild(this.svg);\n }\n\n draw(commands: DrawCommand[]): void {\n // Simple and correct for v0.1: rebuild the layer markup each frame. SVG is\n // retained-mode so the browser diffs efficiently; heavy scenes use Canvas2D.\n this.layer.innerHTML = commandsToSVGInner(commands);\n }\n\n setBackground(color: string): void {\n this.background = color;\n this.bg.setAttribute('fill', color);\n }\n\n get element(): SVGSVGElement {\n return this.svg;\n }\n\n dispose(): void {\n this.svg.remove();\n }\n}\n", "// Canvas2D backend. For scenes with many primitives/particles where SVG's DOM\n// node count would bite. Same display list, immediate-mode painting, DPR-aware.\n\nimport { sortCommands, type DrawCommand, type Paint } from './commands';\nimport type { Renderer, RendererConfig } from './renderer';\n\nexport class Canvas2DRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private dpr = 1;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n this.canvas = document.createElement('canvas');\n this.canvas.style.width = '100%';\n this.canvas.style.height = '100%';\n // Letterbox, never stretch or crop: the design space must arrive intact\n // (a stretched canvas hides gameplay at the edges on off-ratio windows).\n this.canvas.style.objectFit = 'contain';\n this.canvas.style.display = 'block';\n const ctx = this.canvas.getContext('2d');\n if (!ctx) throw new Error('hayao: 2D canvas context unavailable');\n this.ctx = ctx;\n this.resize();\n }\n\n mount(parent: HTMLElement): void {\n parent.appendChild(this.canvas);\n this.resize();\n }\n\n private resize(): void {\n this.dpr = Math.min(3, globalThis.devicePixelRatio || 1);\n this.canvas.width = Math.round(this.width * this.dpr);\n this.canvas.height = Math.round(this.height * this.dpr);\n }\n\n draw(commands: DrawCommand[]): void {\n const ctx = this.ctx;\n ctx.setTransform(this.dpr, 0, 0, this.dpr, 0, 0);\n ctx.fillStyle = this.background;\n ctx.fillRect(0, 0, this.width, this.height);\n\n for (const c of sortCommands(commands)) {\n ctx.save();\n const t = c.transform;\n ctx.transform(t.a, t.b, t.c, t.d, t.e, t.f);\n ctx.globalAlpha = (c as Paint).opacity ?? 1;\n this.paint(ctx, c);\n ctx.restore();\n }\n }\n\n private stroke(ctx: CanvasRenderingContext2D, c: Paint): void {\n if (c.fill && c.fill !== 'none') {\n ctx.fillStyle = c.fill;\n ctx.fill();\n }\n if (c.stroke) {\n ctx.strokeStyle = c.stroke;\n ctx.lineWidth = c.strokeWidth ?? 1;\n if (c.round) {\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n }\n ctx.stroke();\n }\n }\n\n private paint(ctx: CanvasRenderingContext2D, c: DrawCommand): void {\n switch (c.kind) {\n case 'rect':\n ctx.beginPath();\n if (c.r) this.roundRect(ctx, c.x, c.y, c.w, c.h, c.r);\n else ctx.rect(c.x, c.y, c.w, c.h);\n this.stroke(ctx, c);\n break;\n case 'circle':\n ctx.beginPath();\n ctx.arc(c.cx, c.cy, c.radius, 0, Math.PI * 2);\n this.stroke(ctx, c);\n break;\n case 'poly':\n ctx.beginPath();\n for (let i = 0; i < c.points.length; i += 2) {\n if (i === 0) ctx.moveTo(c.points[i], c.points[i + 1]);\n else ctx.lineTo(c.points[i], c.points[i + 1]);\n }\n if (c.closed) ctx.closePath();\n this.stroke(ctx, c);\n break;\n case 'path':\n {\n const p = new Path2D(c.d);\n if (c.fill && c.fill !== 'none') {\n ctx.fillStyle = c.fill;\n ctx.fill(p);\n }\n if (c.stroke) {\n ctx.strokeStyle = c.stroke;\n ctx.lineWidth = c.strokeWidth ?? 1;\n if (c.round) {\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n }\n ctx.stroke(p);\n }\n }\n break;\n case 'text':\n ctx.fillStyle = c.fill ?? '#000';\n ctx.font = `${c.weight ?? 400} ${c.size}px ${c.font ?? 'sans-serif'}`;\n ctx.textAlign = c.align ?? 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(c.text, c.x, c.y);\n break;\n case 'image':\n break; // images loaded async; omitted in v0.1 canvas backend\n }\n }\n\n private roundRect(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, r: number): void {\n const rr = Math.min(r, w / 2, h / 2);\n ctx.moveTo(x + rr, y);\n ctx.arcTo(x + w, y, x + w, y + h, rr);\n ctx.arcTo(x + w, y + h, x, y + h, rr);\n ctx.arcTo(x, y + h, x, y, rr);\n ctx.arcTo(x, y, x + w, y, rr);\n ctx.closePath();\n }\n\n get element(): HTMLCanvasElement {\n return this.canvas;\n }\n\n dispose(): void {\n this.canvas.remove();\n }\n}\n", "// The headless backend: records the last display list instead of painting it.\n// Tests assert on the commands directly; scripts turn them into a vector\n// screenshot via renderToSVGString. This is why a hayao game is testable with\n// zero browser \u2014 the renderer is just a data sink.\n\nimport type { DrawCommand } from './commands';\nimport type { Renderer, RendererConfig } from './renderer';\nimport { renderToSVGString } from './svgString';\n\nexport class HeadlessRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private last: DrawCommand[] = [];\n frameCount = 0;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n }\n\n draw(commands: DrawCommand[]): void {\n this.last = commands;\n this.frameCount++;\n }\n\n /** The most recently drawn display list. */\n get commands(): DrawCommand[] {\n return this.last;\n }\n\n /** Count commands of a given kind (handy for assertions). */\n count(kind: DrawCommand['kind']): number {\n return this.last.filter((c) => c.kind === kind).length;\n }\n\n /** A vector screenshot of the last frame. */\n toSVGString(): string {\n return renderToSVGString(this.last, this.width, this.height, this.background);\n }\n}\n", "// 9-slice panels: one scalable UI frame from a handful of params. A rectangle is\n// split into a 3\u00D73 grid \u2014 the four corners keep a fixed size while the edges\n// stretch along one axis and the center fills \u2014 so a frame drawn at any size\n// keeps crisp, undistorted corners. Pure: it just emits DrawCommands into a\n// display list, so it renders headlessly and never touches game state. Colour the\n// regions differently (light top/left, dark bottom/right) for an instant bevel.\n\nimport { IDENTITY, type Rect, type Transform } from '../core/math';\nimport type { DrawCommand } from './commands';\n\nexport interface NineSliceStyle {\n /** Corner size in px \u2014 the slice inset that never stretches. */\n border: number;\n /** Center fill (the panel body). */\n fill?: string;\n /** Edge fill (top/bottom/left/right strips). Defaults to `fill`. */\n edge?: string;\n /** Corner fill (the four fixed squares). Defaults to `edge`. */\n corner?: string;\n /** Optional bevel: lighten the top/left, darken the bottom/right. */\n highlight?: string;\n shadow?: string;\n /** Outline stroke drawn around the whole frame. */\n stroke?: string;\n strokeWidth?: number;\n /** Outer corner radius applied to the four corner squares. */\n radius?: number;\n}\n\n/**\n * Emit the draw commands for a 9-slice panel filling `rect`. Regions are pushed\n * back-to-front (center \u2192 edges \u2192 corners) at painter key `z`, transformed by\n * `transform` (screen space by default). Border is clamped so it never exceeds\n * half the smaller side, keeping the grid valid at any size.\n */\nexport function nineSlice(rect: Rect, style: NineSliceStyle, z = 0, transform: Transform = IDENTITY): DrawCommand[] {\n const b = Math.max(0, Math.min(style.border, rect.w / 2, rect.h / 2));\n const fill = style.fill ?? '#fbf6ea';\n const edge = style.edge ?? fill;\n const corner = style.corner ?? edge;\n const out: DrawCommand[] = [];\n const x0 = rect.x;\n const x1 = rect.x + b;\n const x2 = rect.x + rect.w - b;\n const y0 = rect.y;\n const y1 = rect.y + b;\n const y2 = rect.y + rect.h - b;\n const iw = rect.w - 2 * b; // inner (stretched) width\n const ih = rect.h - 2 * b; // inner (stretched) height\n\n const push = (x: number, y: number, w: number, h: number, f: string, r?: number): void => {\n if (w <= 0 || h <= 0) return;\n out.push({ kind: 'rect', x, y, w, h, r, fill: f, transform, z });\n };\n\n // Center + the four stretchable edges.\n push(x1, y1, iw, ih, fill);\n push(x1, y0, iw, b, style.highlight ?? edge); // top\n push(x1, y2, iw, b, style.shadow ?? edge); // bottom\n push(x0, y1, b, ih, style.highlight ?? edge); // left\n push(x2, y1, b, ih, style.shadow ?? edge); // right\n\n // Four fixed corners (drawn last so their radius reads clean over the edges).\n const r = style.radius;\n push(x0, y0, b, b, corner, r);\n push(x2, y0, b, b, corner, r);\n push(x0, y2, b, b, corner, r);\n push(x2, y2, b, b, corner, r);\n\n // Optional outline around the whole frame.\n if (style.stroke) {\n out.push({\n kind: 'rect',\n x: rect.x,\n y: rect.y,\n w: rect.w,\n h: rect.h,\n r: style.radius,\n fill: 'none',\n stroke: style.stroke,\n strokeWidth: style.strokeWidth ?? 2,\n transform,\n z: z + 0.001,\n });\n }\n return out;\n}\n\n/** Ready-made frame looks. */\nexport const PANEL_PRESETS = {\n parchment: (): NineSliceStyle => ({ border: 10, fill: '#fbf6ea', edge: '#efe4c8', corner: '#e2d3a8', highlight: '#fdfaf0', shadow: '#d9c79c', stroke: '#b8a06a', strokeWidth: 2, radius: 4 }),\n slate: (): NineSliceStyle => ({ border: 8, fill: '#2c3040', edge: '#363c4f', corner: '#454c63', highlight: '#4a5268', shadow: '#20242f', stroke: '#151821', strokeWidth: 2, radius: 3 }),\n} as const;\n", "// Curated palettes \u2014 code-as-art means no arbitrary RGB; pick from a named,\n// on-model set. Default is a warm, high-legibility \"Meadow\" palette (a nod to\n// the Ghibli/Miyazaki-ish direction the engine is named for).\n\nimport type { Rng } from '../core/rng';\nimport { dexp2, dlog2 } from '../core/dmath';\n\nexport interface Palette {\n name: string;\n bg: string;\n ink: string;\n inkSoft: string;\n line: string;\n accent: string;\n accent2: string;\n good: string;\n warn: string;\n /** A small ordered ramp for categorical fills. */\n ramp: string[];\n}\n\nexport const MEADOW: Palette = {\n name: 'meadow',\n bg: '#f3ecdb',\n ink: '#3d3323',\n inkSoft: '#6f6047',\n line: '#d9ccae',\n accent: '#a11d3a',\n accent2: '#5a7d4e',\n good: '#4d6b3c',\n warn: '#c8791f',\n ramp: ['#a11d3a', '#c8791f', '#c9a22f', '#5a7d4e', '#3f7d8c', '#6a4c93'],\n};\n\nexport const DUSK: Palette = {\n name: 'dusk',\n bg: '#1c1a24',\n ink: '#efe9f2',\n inkSoft: '#a89fb5',\n line: '#3a3546',\n accent: '#e26d8a',\n accent2: '#6cc4a1',\n good: '#6cc4a1',\n warn: '#e8b64a',\n ramp: ['#e26d8a', '#e8b64a', '#f2e07a', '#6cc4a1', '#5aa9d6', '#b493e6'],\n};\n\nexport const PAPER: Palette = {\n name: 'paper',\n bg: '#faf7f0',\n ink: '#2b2b2b',\n inkSoft: '#666',\n line: '#e2ddd2',\n accent: '#d1495b',\n accent2: '#2e86ab',\n good: '#3c896d',\n warn: '#e0902f',\n ramp: ['#d1495b', '#e0902f', '#edc531', '#3c896d', '#2e86ab', '#8a5a9e'],\n};\n\nexport const PALETTES: Record<string, Palette> = { meadow: MEADOW, dusk: DUSK, paper: PAPER };\n\n/** Blend two hex colors (t in [0,1]). Deterministic, no allocations of note. */\nexport function mix(a: string, b: string, t: number): string {\n const pa = hexToRgb(a);\n const pb = hexToRgb(b);\n const r = Math.round(pa[0] + (pb[0] - pa[0]) * t);\n const g = Math.round(pa[1] + (pb[1] - pa[1]) * t);\n const bl = Math.round(pa[2] + (pb[2] - pa[2]) * t);\n return rgbToHex(r, g, bl);\n}\n\nexport function withAlpha(hex: string, alpha: number): string {\n const [r, g, b] = hexToRgb(hex);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] {\n let h = hex.replace('#', '');\n if (h.length === 3) h = h.split('').map((c) => c + c).join('');\n const n = parseInt(h, 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('');\n}\n\n// \u2500\u2500 HSL / HSV constructors + drift \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Procedural theming and palette drift (space-huggers `setHSLA`+`mutate`,\n// dr1v3n-wild/dodo `.hsl`). Pure arithmetic \u2014 no trig \u2014 so it's netplay-safe.\n// Colors are cosmetic; when drift reads `world.rng` it advances deterministically.\n\nexport interface HSL {\n /** Hue in degrees [0,360). */\n h: number;\n /** Saturation [0,1]. */\n s: number;\n /** Lightness [0,1]. */\n l: number;\n}\n\nconst mod360 = (h: number): number => ((h % 360) + 360) % 360;\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** HSL \u2192 hex. h in degrees (wraps), s/l in [0,1]. */\nexport function hsl(h: number, s: number, l: number): string {\n h = mod360(h) / 360;\n s = clamp01(s);\n l = clamp01(l);\n if (s === 0) {\n const v = l * 255;\n return rgbToHex(v, v, v);\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number): number => {\n t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n return rgbToHex(hue(h + 1 / 3) * 255, hue(h) * 255, hue(h - 1 / 3) * 255);\n}\n\n/** HSV/HSB \u2192 hex. h in degrees (wraps), s/v in [0,1]. */\nexport function hsv(h: number, s: number, v: number): string {\n h = mod360(h) / 60;\n s = clamp01(s);\n v = clamp01(v);\n const c = v * s;\n const x = c * (1 - Math.abs((h % 2) - 1));\n const m = v - c;\n let r = 0;\n let g = 0;\n let b = 0;\n if (h < 1) [r, g, b] = [c, x, 0];\n else if (h < 2) [r, g, b] = [x, c, 0];\n else if (h < 3) [r, g, b] = [0, c, x];\n else if (h < 4) [r, g, b] = [0, x, c];\n else if (h < 5) [r, g, b] = [x, 0, c];\n else [r, g, b] = [c, 0, x];\n return rgbToHex((r + m) * 255, (g + m) * 255, (b + m) * 255);\n}\n\n/** Decompose a hex color into HSL. Inverse of `hsl()`. */\nexport function hexToHsl(hex: string): HSL {\n const [r255, g255, b255] = hexToRgb(hex);\n const r = r255 / 255;\n const g = g255 / 255;\n const b = b255 / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d === 0) return { h: 0, s: 0, l };\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0);\n else if (max === g) h = (b - r) / d + 2;\n else h = (r - g) / d + 4;\n return { h: h * 60, s, l };\n}\n\nexport interface DriftAmounts {\n /** Max hue drift \u00B1 degrees. */\n hue?: number;\n /** Max saturation drift \u00B1 (absolute, [0,1]). */\n sat?: number;\n /** Max lightness drift \u00B1 (absolute, [0,1]). */\n light?: number;\n}\n\n/**\n * Drift a color in HSL space by random amounts from `world.rng` (space-huggers'\n * `mutate`). Deterministic given rng state; hue wraps, s/l clamp. Cosmetic, but\n * because it consumes rng draws, call it in a stable order.\n */\nexport function mutateColor(rng: Rng, hex: string, amounts: DriftAmounts = {}): string {\n const c = hexToHsl(hex);\n const dh = amounts.hue ?? 0;\n const ds = amounts.sat ?? 0;\n const dl = amounts.light ?? 0;\n return hsl(\n c.h + rng.range(-dh, dh),\n c.s + rng.range(-ds, ds),\n c.l + rng.range(-dl, dl),\n );\n}\n\n// \u2500\u2500 gamma-correct (linear-space) interpolation + gradients \u2500\u2500\u2500\u2500\u2500\u2500\n// super-castle blends in linear light, not sRGB \u2014 perceptually correct, no muddy\n// mid-tones. sRGB\u2194linear uses the exact IEC transfer curve; the 2.4 exponent\n// routes through dmath (dexp2/dlog2) so it's bit-identical across engines and\n// never trips the \"no Math.pow\" invariant.\n\nfunction dpow(base: number, exp: number): number {\n if (base <= 0) return 0;\n return dexp2(exp * dlog2(base));\n}\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : dpow((c + 0.055) / 1.055, 2.4));\nconst linearToSrgb = (c: number): number => (c <= 0.0031308 ? c * 12.92 : 1.055 * dpow(c, 1 / 2.4) - 0.055);\n\n/** Blend two hex colors in linear light (gamma-correct). t in [0,1]. */\nexport function mixLinear(a: string, b: string, t: number): string {\n const pa = hexToRgb(a);\n const pb = hexToRgb(b);\n const chan = (i: number): number => {\n const la = srgbToLinear(pa[i] / 255);\n const lb = srgbToLinear(pb[i] / 255);\n return linearToSrgb(la + (lb - la) * t) * 255;\n };\n return rgbToHex(chan(0), chan(1), chan(2));\n}\n\n/**\n * Sample a multi-stop gradient at t in [0,1], blending in linear light. Stops\n * are evenly spaced hex colors (\u2265 1). Great for procedural sky/heat/health ramps.\n */\nexport function sampleGradient(stops: readonly string[], t: number): string {\n if (stops.length === 0) return '#000000';\n if (stops.length === 1) return stops[0];\n const clamped = clamp01(t);\n const scaled = clamped * (stops.length - 1);\n const i = Math.min(stops.length - 2, Math.floor(scaled));\n return mixLinear(stops[i], stops[i + 1], scaled - i);\n}\n\n/** Materialize an n-color ramp from gradient stops (linear-light interpolation). */\nexport function gradient(stops: readonly string[], n: number): string[] {\n if (n <= 0) return [];\n if (n === 1) return [sampleGradient(stops, 0)];\n return Array.from({ length: n }, (_, i) => sampleGradient(stops, i / (n - 1)));\n}\n", "// Procedural vector shape builders \u2014 the \"code-as-art\" toolkit. All pure and\n// deterministic (any randomness must be passed an Rng), producing point arrays\n// or SVG path strings usable directly in a Sprite.\n\nimport { dcos, dsin } from '../core/dmath';\nimport type { Rng } from '../core/rng';\nimport { TAU, type Vec2 } from '../core/math';\n\n/** Regular polygon points (flat [x,y,\u2026]) centered at origin. */\nexport function regularPolygon(sides: number, radius: number, rotation = 0): number[] {\n const pts: number[] = [];\n for (let i = 0; i < sides; i++) {\n const a = rotation + (i / sides) * TAU;\n pts.push(dcos(a) * radius, dsin(a) * radius);\n }\n return pts;\n}\n\n/** Star with alternating outer/inner radii. */\nexport function star(points: number, outer: number, inner: number, rotation = -Math.PI / 2): number[] {\n const pts: number[] = [];\n for (let i = 0; i < points * 2; i++) {\n const r = i % 2 === 0 ? outer : inner;\n const a = rotation + (i / (points * 2)) * TAU;\n pts.push(dcos(a) * r, dsin(a) * r);\n }\n return pts;\n}\n\n/** An organic blob outline as an SVG path (deterministic given the Rng). */\nexport function blobPath(rng: Rng, radius: number, wobble = 0.25, lobes = 7): string {\n const pts: Vec2[] = [];\n for (let i = 0; i < lobes; i++) {\n const a = (i / lobes) * TAU;\n const r = radius * (1 - wobble + rng.float() * wobble * 2);\n pts.push({ x: dcos(a) * r, y: dsin(a) * r });\n }\n return smoothClosedPath(pts);\n}\n\n/** Convert a point list into a smooth closed path (Catmull-Rom \u2192 cubic B\u00E9zier). */\nexport function smoothClosedPath(points: Vec2[], tension = 1): string {\n const nPts = points.length;\n if (nPts < 3) return '';\n const p = (i: number) => points[((i % nPts) + nPts) % nPts];\n const r = (v: number) => Math.round(v * 100) / 100;\n let d = `M ${r(p(0).x)} ${r(p(0).y)}`;\n for (let i = 0; i < nPts; i++) {\n const p0 = p(i - 1);\n const p1 = p(i);\n const p2 = p(i + 1);\n const p3 = p(i + 2);\n const c1x = p1.x + ((p2.x - p0.x) / 6) * tension;\n const c1y = p1.y + ((p2.y - p0.y) / 6) * tension;\n const c2x = p2.x - ((p3.x - p1.x) / 6) * tension;\n const c2y = p2.y - ((p3.y - p1.y) / 6) * tension;\n d += ` C ${r(c1x)} ${r(c1y)}, ${r(c2x)} ${r(c2y)}, ${r(p2.x)} ${r(p2.y)}`;\n }\n return d + ' Z';\n}\n\n/** Smooth open path through points (for trails, curves). */\nexport function smoothOpenPath(points: Vec2[], tension = 1): string {\n const nPts = points.length;\n if (nPts < 2) return '';\n const r = (v: number) => Math.round(v * 100) / 100;\n let d = `M ${r(points[0].x)} ${r(points[0].y)}`;\n for (let i = 0; i < nPts - 1; i++) {\n const p0 = points[Math.max(0, i - 1)];\n const p1 = points[i];\n const p2 = points[i + 1];\n const p3 = points[Math.min(nPts - 1, i + 2)];\n const c1x = p1.x + ((p2.x - p0.x) / 6) * tension;\n const c1y = p1.y + ((p2.y - p0.y) / 6) * tension;\n const c2x = p2.x - ((p3.x - p1.x) / 6) * tension;\n const c2y = p2.y - ((p3.y - p1.y) / 6) * tension;\n d += ` C ${r(c1x)} ${r(c1y)}, ${r(c2x)} ${r(c2y)}, ${r(p2.x)} ${r(p2.y)}`;\n }\n return d;\n}\n", "// Procedural sprite / texture generation \u2014 build whole tilesets and sprites\n// from code with ~0 asset bytes (the defining js13k art trick). A `PixelBuffer`\n// is a tiny indexed bitmap; decoders reconstruct one from a compact encoding\n// (packed 2-bit, RLE run pairs, or a 1-bit BigInt/hex bitmap), and the emitter\n// projects it to run-merged `rect` draw commands the renderer already speaks.\n//\n// COSMETIC / DETERMINISM: the pixels here are pure *view* derived from constant\n// data (or from `world.rng`, never `Math.random`). The output rects carry no\n// canonical state, so `TextureSprite` sets `cosmetic = true` \u2014 it never enters\n// `world.hash()`/snapshot. Decoding is a pure function of its inputs.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { DrawCommand, RectCommand } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\n\n/** A palette entry; `null` (or a missing index) renders transparent. */\nexport type Swatch = string | null;\n\n/** A small indexed bitmap: `data[y * width + x]` is a palette index. */\nexport class PixelBuffer {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n\n constructor(width: number, height: number, data?: Uint8Array) {\n this.width = width;\n this.height = height;\n this.data = data ?? new Uint8Array(width * height);\n }\n\n get(x: number, y: number): number {\n if (x < 0 || y < 0 || x >= this.width || y >= this.height) return 0;\n return this.data[y * this.width + x];\n }\n set(x: number, y: number, index: number): void {\n if (x < 0 || y < 0 || x >= this.width || y >= this.height) return;\n this.data[y * this.width + x] = index;\n }\n\n /** Build from a rows-of-strings grid, mapping each character to an index. */\n static fromRows(rows: readonly string[], charToIndex: Record<string, number>): PixelBuffer {\n const height = rows.length;\n const width = rows.reduce((w, r) => Math.max(w, r.length), 0);\n const buf = new PixelBuffer(width, height);\n for (let y = 0; y < height; y++) {\n const row = rows[y];\n for (let x = 0; x < row.length; x++) buf.data[y * width + x] = charToIndex[row[x]] ?? 0;\n }\n return buf;\n }\n\n /** A copy with every index passed through `lut` (2-bit \u2192 palette remap). */\n remap(lut: readonly number[]): PixelBuffer {\n const out = new Uint8Array(this.data.length);\n for (let i = 0; i < this.data.length; i++) out[i] = lut[this.data[i]] ?? 0;\n return new PixelBuffer(this.width, this.height, out);\n }\n}\n\n/** Normalize a packed bitmap source (hex string, `0b\u2026`/`0x\u2026`, or bigint) to a BigInt. */\nfunction toBig(source: bigint | string): bigint {\n if (typeof source === 'bigint') return source;\n const s = source.trim();\n if (s.startsWith('0x') || s.startsWith('0b') || s.startsWith('0o')) return BigInt(s);\n return BigInt('0x' + s);\n}\n\n/**\n * Decode a 1-bit-per-pixel bitmap packed MSB-first into a BigInt/hex string\n * (the super-castle-style trick). Pixel `i` reads bit `(w*h-1-i)`, so a hex\n * literal reads left-to-right, top-to-bottom. Produces indices 0 or 1.\n */\nexport function decodeBits(source: bigint | string, width: number, height: number): PixelBuffer {\n const bits = toBig(source);\n const total = width * height;\n const buf = new PixelBuffer(width, height);\n for (let i = 0; i < total; i++) {\n buf.data[i] = Number((bits >> BigInt(total - 1 - i)) & 1n);\n }\n return buf;\n}\n\n/**\n * Decode a 2-bit-per-pixel bitmap (indices 0\u20133) packed MSB-first, matching the\n * dying-dreams \"2-bit source \u2192 palette LUT\" pipeline. Pass the result through\n * `PixelBuffer.remap(lut)` to lift the 2-bit indices into a wider palette.\n */\nexport function decode2bit(source: bigint | string, width: number, height: number): PixelBuffer {\n const bits = toBig(source);\n const total = width * height;\n const buf = new PixelBuffer(width, height);\n for (let i = 0; i < total; i++) {\n const shift = BigInt((total - 1 - i) * 2);\n buf.data[i] = Number((bits >> shift) & 3n);\n }\n return buf;\n}\n\n/**\n * Decode a run-length-encoded index stream (witchcat-style). `runs` is a flat\n * list of `[count, index, count, index, \u2026]` filled row-major. A short encoding\n * for sprites dominated by flat colour.\n */\nexport function decodeRLE(runs: readonly number[], width: number, height: number): PixelBuffer {\n const buf = new PixelBuffer(width, height);\n let p = 0;\n for (let i = 0; i + 1 < runs.length; i += 2) {\n const count = runs[i];\n const index = runs[i + 1];\n for (let k = 0; k < count && p < buf.data.length; k++) buf.data[p++] = index;\n }\n return buf;\n}\n\n/** Encode a PixelBuffer back to RLE run pairs \u2014 the inverse of `decodeRLE`. */\nexport function encodeRLE(buf: PixelBuffer): number[] {\n const runs: number[] = [];\n const d = buf.data;\n for (let i = 0; i < d.length; ) {\n const v = d[i];\n let count = 1;\n while (i + count < d.length && d[i + count] === v) count++;\n runs.push(count, v);\n i += count;\n }\n return runs;\n}\n\nexport interface PixelDrawOptions {\n /** Size of one pixel cell in design units. Default 1. */\n cell?: number;\n /** Top-left origin in local space. Default 0,0. */\n x?: number;\n y?: number;\n /** Painter z. Default 0. */\n z?: number;\n /** World transform for the emitted commands. Default identity. */\n transform?: Transform;\n}\n\n/**\n * Project a PixelBuffer to `rect` draw commands, run-merging horizontal spans\n * of the same colour so a 16\u00D716 sprite is a handful of rects, not 256. Palette\n * entries that are `null`/undefined render transparent (skipped). Pure \u2014 the\n * commands carry no state and belong under a `cosmetic` node.\n */\nexport function pixelsToCommands(\n buf: PixelBuffer,\n palette: readonly Swatch[],\n options: PixelDrawOptions = {},\n): RectCommand[] {\n const cell = options.cell ?? 1;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const out: RectCommand[] = [];\n for (let y = 0; y < buf.height; y++) {\n let x = 0;\n while (x < buf.width) {\n const idx = buf.get(x, y);\n const fill = palette[idx];\n if (fill == null) {\n x++;\n continue;\n }\n let run = 1;\n while (x + run < buf.width && buf.get(x + run, y) === idx) run++;\n out.push({\n kind: 'rect',\n x: ox + x * cell,\n y: oy + y * cell,\n w: run * cell,\n h: cell,\n transform,\n z,\n fill,\n });\n x += run;\n }\n }\n return out;\n}\n\nexport interface TextureSpriteConfig extends NodeConfig {\n buffer: PixelBuffer;\n palette: readonly Swatch[];\n /** Pixel cell size in design units. Default 1. */\n cell?: number;\n /** Draw centered on the node origin instead of top-left. Default true. */\n center?: boolean;\n}\n\n/**\n * A scene node that renders a decoded PixelBuffer. It is pure view over\n * constant art data, so it is `cosmetic = true` by default \u2014 excluded from\n * `serialize()`/`hash()`/snapshot. Position/scale it like any other node.\n */\nexport class TextureSprite extends Node {\n override readonly type = 'TextureSprite';\n buffer: PixelBuffer;\n palette: readonly Swatch[];\n cell: number;\n center: boolean;\n\n constructor(config: TextureSpriteConfig) {\n super(config);\n this.buffer = config.buffer;\n this.palette = config.palette;\n this.cell = config.cell ?? 1;\n this.center = config.center ?? true;\n this.cosmetic = true;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const cell = this.cell;\n const x = this.center ? -(this.buffer.width * cell) / 2 : 0;\n const y = this.center ? -(this.buffer.height * cell) / 2 : 0;\n for (const cmd of pixelsToCommands(this.buffer, this.palette, { cell, x, y, z: this.z, transform: world })) {\n out.push(cmd);\n }\n }\n}\n", "// A built-in 5-pixel-tall proportional bitmap font (\"code-as-art\" \u2014 no font\n// asset). Each glyph is rows of `#` (lit) / `.` (off), top to bottom; the glyph\n// width is its row length, so letters are proportional (I is 1 wide, M is 5).\n// Uppercase-only: layout folds lowercase to uppercase. Pure constant data.\n\n/** A font: named glyph bitmaps plus vertical/spacing metrics. */\nexport interface BitmapFont {\n readonly height: number;\n /** Blank columns between glyphs. */\n readonly tracking: number;\n /** Width of a space character (advance only, no pixels). */\n readonly spaceWidth: number;\n readonly glyphs: Readonly<Record<string, readonly string[]>>;\n}\n\nconst G: Record<string, string[]> = {\n A: ['.#.', '#.#', '###', '#.#', '#.#'],\n B: ['##.', '#.#', '##.', '#.#', '##.'],\n C: ['.##', '#..', '#..', '#..', '.##'],\n D: ['##.', '#.#', '#.#', '#.#', '##.'],\n E: ['###', '#..', '##.', '#..', '###'],\n F: ['###', '#..', '##.', '#..', '#..'],\n G: ['.##', '#..', '#.#', '#.#', '.##'],\n H: ['#.#', '#.#', '###', '#.#', '#.#'],\n I: ['#', '#', '#', '#', '#'],\n J: ['..#', '..#', '..#', '#.#', '.#.'],\n K: ['#.#', '##.', '#..', '##.', '#.#'],\n L: ['#..', '#..', '#..', '#..', '###'],\n M: ['#...#', '##.##', '#.#.#', '#...#', '#...#'],\n N: ['#...#', '##..#', '#.#.#', '#..##', '#...#'],\n O: ['.#.', '#.#', '#.#', '#.#', '.#.'],\n P: ['##.', '#.#', '##.', '#..', '#..'],\n Q: ['.#.', '#.#', '#.#', '#.#', '.##'],\n R: ['##.', '#.#', '##.', '#.#', '#.#'],\n S: ['.##', '#..', '.#.', '..#', '##.'],\n T: ['###', '.#.', '.#.', '.#.', '.#.'],\n U: ['#.#', '#.#', '#.#', '#.#', '###'],\n V: ['#.#', '#.#', '#.#', '#.#', '.#.'],\n W: ['#...#', '#...#', '#.#.#', '##.##', '#...#'],\n X: ['#.#', '#.#', '.#.', '#.#', '#.#'],\n Y: ['#.#', '#.#', '.#.', '.#.', '.#.'],\n Z: ['###', '..#', '.#.', '#..', '###'],\n '0': ['.#.', '#.#', '#.#', '#.#', '.#.'],\n '1': ['.#.', '##.', '.#.', '.#.', '###'],\n '2': ['##.', '..#', '.#.', '#..', '###'],\n '3': ['##.', '..#', '.#.', '..#', '##.'],\n '4': ['#.#', '#.#', '###', '..#', '..#'],\n '5': ['###', '#..', '##.', '..#', '##.'],\n '6': ['.##', '#..', '##.', '#.#', '.#.'],\n '7': ['###', '..#', '.#.', '.#.', '.#.'],\n '8': ['.#.', '#.#', '.#.', '#.#', '.#.'],\n '9': ['.#.', '#.#', '.##', '..#', '##.'],\n '.': ['.', '.', '.', '.', '#'],\n ',': ['..', '..', '..', '.#', '#.'],\n '!': ['#', '#', '#', '.', '#'],\n '?': ['##.', '..#', '.#.', '...', '.#.'],\n ':': ['.', '#', '.', '#', '.'],\n ';': ['..', '.#', '..', '.#', '#.'],\n '-': ['...', '...', '###', '...', '...'],\n '+': ['...', '.#.', '###', '.#.', '...'],\n '=': ['...', '###', '...', '###', '...'],\n '/': ['..#', '..#', '.#.', '#..', '#..'],\n \"'\": ['#', '#', '.', '.', '.'],\n '\"': ['#.#', '#.#', '...', '...', '...'],\n '(': ['.#', '#.', '#.', '#.', '.#'],\n ')': ['#.', '.#', '.#', '.#', '#.'],\n '<': ['..#', '.#.', '#..', '.#.', '..#'],\n '>': ['#..', '.#.', '..#', '.#.', '#..'],\n '%': ['#.#', '..#', '.#.', '#..', '#.#'],\n '*': ['...', '#.#', '.#.', '#.#', '...'],\n '#': ['#.#', '###', '#.#', '###', '#.#'],\n};\n\n/** The default built-in font: 5px tall, proportional, uppercase + digits + punctuation. */\nexport const FONT_5: BitmapFont = {\n height: 5,\n tracking: 1,\n spaceWidth: 3,\n glyphs: G,\n};\n", "// Bitmap/pixel text: glyph atlas \u2192 proportional layout \u2192 run-merged draw\n// commands. Covers what the js13k HUD/dialogue games hand-build: per-char\n// widths, word wrap, typewriter reveal (clock-driven, never wall-clock), and\n// inline colour markup via a `{tag}\u2026{/}` stack (clawstrike/coup-ahoo style).\n//\n// COSMETIC / DETERMINISM: text is pure view. Layout is a pure function of\n// (font, string, width). Typewriter reveal is a pure function of sim time from\n// `world.time`/`clock` \u2014 no `performance.now`. `BitmapText` is `cosmetic`.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { DrawCommand, RectCommand, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\nimport { FONT_5, type BitmapFont } from './font5';\n\n/** One source character with an optional colour and its index in the source string. */\nexport interface RichChar {\n ch: string;\n color?: string;\n i: number;\n}\n\n/**\n * Parse inline colour markup into per-character colours. `{name}` pushes a\n * colour, `{/}` pops it (a stack, so nesting works); `{{` is a literal `{`.\n * A tag resolves through `colorMap`, or is used literally if it starts with `#`\n * or is not in the map. Text outside any tag has no colour (caller default).\n */\nexport function parseRich(markup: string, colorMap: Record<string, string> = {}): RichChar[] {\n const out: RichChar[] = [];\n const stack: string[] = [];\n let i = 0;\n let srcIndex = 0;\n while (i < markup.length) {\n const c = markup[i];\n if (c === '{' && markup[i + 1] === '{') {\n out.push({ ch: '{', color: stack[stack.length - 1], i: srcIndex++ });\n i += 2;\n continue;\n }\n if (c === '{') {\n const end = markup.indexOf('}', i);\n if (end === -1) {\n out.push({ ch: c, color: stack[stack.length - 1], i: srcIndex++ });\n i++;\n continue;\n }\n const tag = markup.slice(i + 1, end);\n if (tag === '/') stack.pop();\n else stack.push(tag[0] === '#' ? tag : (colorMap[tag] ?? tag));\n i = end + 1;\n continue;\n }\n out.push({ ch: c, color: stack[stack.length - 1], i: srcIndex++ });\n i++;\n }\n return out;\n}\n\n/** Fold a character to one the font can draw (uppercase; unknown \u2192 space or `?`). */\nfunction resolveChar(font: BitmapFont, ch: string): string {\n if (ch === ' ' || ch === '\\n') return ch;\n const up = ch.toUpperCase();\n if (font.glyphs[up]) return up;\n if (font.glyphs[ch]) return ch;\n return font.glyphs['?'] ? '?' : ' ';\n}\n\n/** Width of a single glyph (advance excludes tracking). */\nfunction glyphWidth(font: BitmapFont, ch: string): number {\n if (ch === ' ') return font.spaceWidth;\n const rows = font.glyphs[ch];\n return rows ? rows[0].length : font.spaceWidth;\n}\n\n/** Width in font-pixels of a run of already-resolved chars on one line. */\nexport function measureLine(font: BitmapFont, chars: readonly RichChar[]): number {\n let w = 0;\n for (let k = 0; k < chars.length; k++) {\n w += glyphWidth(font, chars[k].ch);\n if (k < chars.length - 1) w += font.tracking;\n }\n return w;\n}\n\n/** Width in font-pixels of a plain string (no wrapping). */\nexport function measureText(font: BitmapFont, text: string): number {\n return measureLine(font, [...text].map((ch, i) => ({ ch: resolveChar(font, ch), i })));\n}\n\nexport interface PlacedGlyph {\n ch: string;\n color?: string;\n /** Source-string index (for typewriter reveal). */\n i: number;\n /** Top-left in font-pixel units. */\n x: number;\n y: number;\n w: number;\n}\n\nexport interface TextLayout {\n glyphs: PlacedGlyph[];\n /** Bounding size in font-pixel units. */\n width: number;\n height: number;\n lines: number;\n}\n\nexport interface TextLayoutOptions {\n /** Wrap width in font-pixels. Omit for no wrapping. */\n maxWidth?: number;\n /** Extra blank rows between lines. Default 1. */\n lineSpacing?: number;\n /** Horizontal alignment within `maxWidth` (or the widest line). Default 'left'. */\n align?: TextAlign;\n}\n\n/**\n * Lay out text into placed glyphs (font-pixel coords), word-wrapping on spaces\n * and breaking on `\\n`. Accepts a plain string or a `RichChar[]` from\n * `parseRich`. Pure and deterministic.\n */\nexport function layoutText(\n font: BitmapFont,\n input: string | readonly RichChar[],\n options: TextLayoutOptions = {},\n): TextLayout {\n const lineSpacing = options.lineSpacing ?? 1;\n const source: RichChar[] =\n typeof input === 'string' ? [...input].map((ch, i) => ({ ch, i })) : input.map((r) => ({ ...r }));\n\n // Split into hard lines on '\\n', then greedily wrap each on spaces.\n const hardLines: RichChar[][] = [[]];\n for (const rc of source) {\n if (rc.ch === '\\n') hardLines.push([]);\n else hardLines[hardLines.length - 1].push({ ...rc, ch: resolveChar(font, rc.ch) });\n }\n\n const rows: RichChar[][] = [];\n for (const line of hardLines) {\n if (options.maxWidth === undefined) {\n rows.push(line);\n continue;\n }\n let current: RichChar[] = [];\n let word: RichChar[] = [];\n const flushWord = () => {\n if (word.length === 0) return;\n const sep = current.length ? font.spaceWidth + font.tracking : 0;\n if (current.length && measureLine(font, current) + sep + measureLine(font, word) > options.maxWidth!) {\n rows.push(current);\n current = [];\n }\n if (current.length) current.push({ ch: ' ', i: -1 });\n current.push(...word);\n word = [];\n };\n for (const rc of line) {\n if (rc.ch === ' ') flushWord();\n else word.push(rc);\n }\n flushWord();\n rows.push(current);\n }\n\n const glyphs: PlacedGlyph[] = [];\n let maxW = 0;\n for (const row of rows) maxW = Math.max(maxW, measureLine(font, row));\n const boundW = options.maxWidth ?? maxW;\n\n let y = 0;\n for (const row of rows) {\n const rowW = measureLine(font, row);\n let x = options.align === 'center' ? Math.floor((boundW - rowW) / 2) : options.align === 'right' ? boundW - rowW : 0;\n for (const rc of row) {\n const w = glyphWidth(font, rc.ch);\n if (rc.ch !== ' ') glyphs.push({ ch: rc.ch, color: rc.color, i: rc.i, x, y, w });\n x += w + font.tracking;\n }\n y += font.height + lineSpacing;\n }\n\n return { glyphs, width: boundW, height: rows.length * (font.height + lineSpacing) - lineSpacing, lines: rows.length };\n}\n\n/** Typewriter: how many source characters are revealed after `elapsed` seconds. */\nexport function typewriterCount(total: number, elapsedSec: number, charsPerSec: number): number {\n if (charsPerSec <= 0) return total;\n const n = Math.floor(elapsedSec * charsPerSec);\n return n < 0 ? 0 : n > total ? total : n;\n}\n\nexport interface TextDrawOptions {\n /** Font-pixel cell size in design units. Default 2. */\n cell?: number;\n /** Top-left origin in local space. Default 0,0. */\n x?: number;\n y?: number;\n z?: number;\n /** Default fill for glyphs without an inline colour. Default '#000'. */\n color?: string;\n transform?: Transform;\n /** Draw only glyphs whose source index is `< reveal` (typewriter). */\n reveal?: number;\n}\n\n/**\n * Project a laid-out text to run-merged `rect` commands \u2014 one rect per\n * horizontal span of lit pixels. Pure; the commands belong under a `cosmetic`\n * node.\n */\nexport function textToCommands(\n font: BitmapFont,\n layout: TextLayout,\n options: TextDrawOptions = {},\n): RectCommand[] {\n const cell = options.cell ?? 2;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const defColor = options.color ?? '#000';\n const reveal = options.reveal;\n const out: RectCommand[] = [];\n for (const g of layout.glyphs) {\n if (reveal !== undefined && g.i >= reveal) continue;\n const rows = font.glyphs[g.ch];\n if (!rows) continue;\n const fill = g.color ?? defColor;\n for (let ry = 0; ry < rows.length; ry++) {\n const row = rows[ry];\n let cx = 0;\n while (cx < row.length) {\n if (row[cx] !== '#') {\n cx++;\n continue;\n }\n let run = 1;\n while (cx + run < row.length && row[cx + run] === '#') run++;\n out.push({\n kind: 'rect',\n x: ox + (g.x + cx) * cell,\n y: oy + (g.y + ry) * cell,\n w: run * cell,\n h: cell,\n transform,\n z,\n fill,\n });\n cx += run;\n }\n }\n }\n return out;\n}\n\nexport interface BitmapTextConfig extends NodeConfig {\n text: string;\n font?: BitmapFont;\n cell?: number;\n color?: string;\n /** Resolve `{tag}` markup names to colours. */\n colorMap?: Record<string, string>;\n /** Wrap width in font-pixels. */\n maxWidth?: number;\n lineSpacing?: number;\n align?: TextAlign;\n /** Typewriter speed in chars/sec (clock-driven). Omit to show all at once. */\n charsPerSec?: number;\n /** Center the block on the node origin instead of top-left. Default false. */\n center?: boolean;\n}\n\n/**\n * A scene node that renders bitmap text with optional inline colour and a\n * clock-driven typewriter reveal. Pure view \u2192 `cosmetic = true` (never hashed).\n */\nexport class BitmapText extends Node {\n override readonly type = 'BitmapText';\n text: string;\n font: BitmapFont;\n cell: number;\n color: string;\n colorMap: Record<string, string>;\n maxWidth?: number;\n lineSpacing: number;\n align: TextAlign;\n charsPerSec?: number;\n center: boolean;\n private startTime = 0;\n\n constructor(config: BitmapTextConfig) {\n super(config);\n this.text = config.text;\n this.font = config.font ?? FONT_5;\n this.cell = config.cell ?? 2;\n this.color = config.color ?? '#000';\n this.colorMap = config.colorMap ?? {};\n this.maxWidth = config.maxWidth;\n this.lineSpacing = config.lineSpacing ?? 1;\n this.align = config.align ?? 'left';\n this.charsPerSec = config.charsPerSec;\n this.center = config.center ?? false;\n this.cosmetic = true;\n }\n\n protected override onReady(): void {\n this.startTime = this.world?.time ?? 0;\n }\n\n /** Restart the typewriter from the current sim time. */\n restartReveal(): void {\n this.startTime = this.world?.time ?? 0;\n }\n\n private buildLayout(): TextLayout {\n const chars = parseRich(this.text, this.colorMap);\n return layoutText(this.font, chars, { maxWidth: this.maxWidth, lineSpacing: this.lineSpacing, align: this.align });\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const layout = this.buildLayout();\n let reveal: number | undefined;\n if (this.charsPerSec !== undefined) {\n const elapsed = (this.world?.time ?? 0) - this.startTime;\n reveal = typewriterCount(this.text.length, elapsed, this.charsPerSec);\n }\n const x = this.center ? -(layout.width * this.cell) / 2 : 0;\n const y = this.center ? -(layout.height * this.cell) / 2 : 0;\n for (const cmd of textToCommands(this.font, layout, {\n cell: this.cell,\n x,\n y,\n z: this.z,\n color: this.color,\n transform: world,\n reveal,\n })) {\n out.push(cmd);\n }\n }\n}\n", "// Autotiling: turn a boolean/logical grid into seamless tile art. Two solvers,\n// both fully pure and deterministic (no RNG):\n// \u2022 4-/8-neighbour bitmask \u2192 a base `frame` + `rotation` (Wang tiles), the\n// dying-dreams/witchcat wall-and-edge trick.\n// \u2022 marching squares over the grid corners \u2192 a 0\u201315 case per dual cell, plus\n// iso-contour segments for smooth outlines.\n//\n// The classification is pure logic and MAY inform gameplay, but the *emitted*\n// draw commands are art \u2192 the caller places them under a `cosmetic` node so\n// they stay out of `world.hash()`. BoolGrid is row-major: `grid[y][x]`.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { PolyCommand, RectCommand } from '../render/commands';\n\nexport type BoolGrid = readonly (readonly boolean[])[];\n\n/** Build a grid from rows of text; a cell is solid when its char is in `solid`. */\nexport function gridFromRows(rows: readonly string[], solid = '#'): boolean[][] {\n return rows.map((r) => [...r].map((c) => solid.includes(c)));\n}\n\nfunction at(grid: BoolGrid, x: number, y: number): boolean {\n return y >= 0 && y < grid.length && x >= 0 && x < grid[y].length && grid[y][x];\n}\n\n// \u2500\u2500 4-neighbour Wang bitmask \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Bit order N=1, E=2, S=4, W=8 (set when that side connects to another solid).\n\nexport const Edge = { N: 1, E: 2, S: 4, W: 8 } as const;\nexport type Edge = (typeof Edge)[keyof typeof Edge];\n\n/** 4-bit edge mask of solid neighbours around a cell. */\nexport function mask4(grid: BoolGrid, x: number, y: number): number {\n return (\n (at(grid, x, y - 1) ? Edge.N : 0) |\n (at(grid, x + 1, y) ? Edge.E : 0) |\n (at(grid, x, y + 1) ? Edge.S : 0) |\n (at(grid, x - 1, y) ? Edge.W : 0)\n );\n}\n\n/** 8-bit neighbour mask, bit order N,NE,E,SE,S,SW,W,NW (1,2,4,\u2026,128). */\nexport function mask8(grid: BoolGrid, x: number, y: number): number {\n let m = 0;\n const dirs: ReadonlyArray<readonly [number, number]> = [\n [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1],\n ];\n for (let i = 0; i < 8; i++) if (at(grid, x + dirs[i][0], y + dirs[i][1])) m |= 1 << i;\n return m;\n}\n\n/** Base tile shapes an edge mask resolves to (rotate `frame` by `rotation`\u00D790\u00B0 CW). */\nexport const WangFrame = { Isolated: 0, Cap: 1, Straight: 2, Bend: 3, Tee: 4, Cross: 5 } as const;\nexport type WangFrame = (typeof WangFrame)[keyof typeof WangFrame];\n\nexport interface WangTile {\n mask: number;\n frame: WangFrame;\n /** Quarter turns clockwise applied to the base frame (0\u20133). */\n rotation: number;\n}\n\nfunction rotateCW(m: number): number {\n let r = 0;\n if (m & Edge.N) r |= Edge.E;\n if (m & Edge.E) r |= Edge.S;\n if (m & Edge.S) r |= Edge.W;\n if (m & Edge.W) r |= Edge.N;\n return r;\n}\n\n// Precomputed 16-entry mask \u2192 {frame, rotation} table. Built by rotating one\n// canonical mask per frame through four quarter turns (pure, module-load once).\nconst WANG4: WangTile[] = (() => {\n const bases: ReadonlyArray<readonly [WangFrame, number]> = [\n [WangFrame.Isolated, 0b0000],\n [WangFrame.Cap, Edge.N],\n [WangFrame.Straight, Edge.N | Edge.S],\n [WangFrame.Bend, Edge.N | Edge.E],\n [WangFrame.Tee, Edge.N | Edge.E | Edge.S],\n [WangFrame.Cross, 0b1111],\n ];\n const table: WangTile[] = new Array(16);\n for (const [frame, mask0] of bases) {\n let m = mask0;\n for (let rotation = 0; rotation < 4; rotation++) {\n if (table[m] === undefined) table[m] = { mask: m, frame, rotation };\n m = rotateCW(m);\n }\n }\n return table;\n})();\n\n/** Resolve an edge mask (0\u201315) to its base frame + rotation. */\nexport function wangTile(mask: number): WangTile {\n return WANG4[mask & 15];\n}\n\n/** Classify every solid cell into a {frame, rotation}; empty cells are `null`. */\nexport function autotile4(grid: BoolGrid): (WangTile | null)[][] {\n return grid.map((row, y) => row.map((solid, x) => (solid ? wangTile(mask4(grid, x, y)) : null)));\n}\n\n// \u2500\u2500 Marching squares (corner-sampled dual grid) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Case bit order over a cell's corners: TL=1, TR=2, BR=4, BL=8.\n\n/** Per-dual-cell case index (0\u201315) over the grid corners; size (h-1)\u00D7(w-1). */\nexport function marchingSquaresCases(grid: BoolGrid): number[][] {\n const h = grid.length;\n const w = h ? grid[0].length : 0;\n const out: number[][] = [];\n for (let y = 0; y < h - 1; y++) {\n const row: number[] = [];\n for (let x = 0; x < w - 1; x++) {\n row.push(\n (at(grid, x, y) ? 1 : 0) |\n (at(grid, x + 1, y) ? 2 : 0) |\n (at(grid, x + 1, y + 1) ? 4 : 0) |\n (at(grid, x, y + 1) ? 8 : 0),\n );\n }\n out.push(row);\n }\n return out;\n}\n\n// Edge midpoints per case, referenced as pairs. T=top, R=right, B=bottom, L=left.\ntype MSEdge = 'T' | 'R' | 'B' | 'L';\nconst MS_SEGMENTS: ReadonlyArray<ReadonlyArray<readonly [MSEdge, MSEdge]>> = [\n [], // 0\n [['L', 'T']], // 1 TL\n [['T', 'R']], // 2 TR\n [['L', 'R']], // 3 TL,TR\n [['R', 'B']], // 4 BR\n [['L', 'T'], ['R', 'B']], // 5 saddle\n [['T', 'B']], // 6 TR,BR\n [['L', 'B']], // 7 TL,TR,BR\n [['B', 'L']], // 8 BL\n [['T', 'B']], // 9 TL,BL\n [['T', 'R'], ['B', 'L']], // 10 saddle\n [['R', 'B']], // 11 TL,TR,BL\n [['L', 'R']], // 12 BR,BL\n [['T', 'R']], // 13 TL,BR,BL\n [['L', 'T']], // 14 TR,BR,BL\n [], // 15\n];\n\nexport interface ContourSegment {\n a: { x: number; y: number };\n b: { x: number; y: number };\n}\n\nexport interface ContourOptions {\n /** Cell size in design units. Default 1. */\n cell?: number;\n x?: number;\n y?: number;\n}\n\n/** Iso-contour line segments tracing the solid/empty boundary (design units). */\nexport function marchingSquaresContours(grid: BoolGrid, options: ContourOptions = {}): ContourSegment[] {\n const cell = options.cell ?? 1;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const cases = marchingSquaresCases(grid);\n const segs: ContourSegment[] = [];\n const mid = (edge: MSEdge, cx: number, cy: number) => {\n switch (edge) {\n case 'T': return { x: cx + cell / 2, y: cy };\n case 'R': return { x: cx + cell, y: cy + cell / 2 };\n case 'B': return { x: cx + cell / 2, y: cy + cell };\n case 'L': return { x: cx, y: cy + cell / 2 };\n }\n };\n for (let y = 0; y < cases.length; y++) {\n for (let x = 0; x < cases[y].length; x++) {\n const cx = ox + x * cell;\n const cy = oy + y * cell;\n for (const [e1, e2] of MS_SEGMENTS[cases[y][x]]) segs.push({ a: mid(e1, cx, cy), b: mid(e2, cx, cy) });\n }\n }\n return segs;\n}\n\n// \u2500\u2500 Emitters (cosmetic draw data) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AutotileDrawOptions {\n /** Tile size in design units. Default 8. */\n tile?: number;\n x?: number;\n y?: number;\n z?: number;\n transform?: Transform;\n /** Fill colour of solid tiles. */\n fill?: string;\n /** Stroke colour drawn only on sides exposed to empty (the seam). */\n edge?: string;\n edgeWidth?: number;\n}\n\n/**\n * Draw a boolean grid as seamless tiles: a fill per solid cell plus an edge\n * stroke only on sides facing empty (derived from `mask4`). Pure draw data for\n * a `cosmetic` node.\n */\nexport function autotileToCommands(grid: BoolGrid, options: AutotileDrawOptions = {}): (RectCommand | PolyCommand)[] {\n const tile = options.tile ?? 8;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const fill = options.fill ?? '#888';\n const edge = options.edge;\n const edgeWidth = options.edgeWidth ?? Math.max(1, tile / 8);\n const out: (RectCommand | PolyCommand)[] = [];\n for (let y = 0; y < grid.length; y++) {\n for (let x = 0; x < grid[y].length; x++) {\n if (!grid[y][x]) continue;\n const px = ox + x * tile;\n const py = oy + y * tile;\n out.push({ kind: 'rect', x: px, y: py, w: tile, h: tile, transform, z, fill });\n if (!edge) continue;\n const m = mask4(grid, x, y);\n const line = (points: number[]) =>\n out.push({ kind: 'poly', points, closed: false, transform, z: z + 1, stroke: edge, strokeWidth: edgeWidth });\n if (!(m & Edge.N)) line([px, py, px + tile, py]);\n if (!(m & Edge.E)) line([px + tile, py, px + tile, py + tile]);\n if (!(m & Edge.S)) line([px, py + tile, px + tile, py + tile]);\n if (!(m & Edge.W)) line([px, py, px, py + tile]);\n }\n }\n return out;\n}\n\n/** Draw the marching-squares iso-contour as open polylines (cosmetic draw data). */\nexport function contourToCommands(grid: BoolGrid, options: AutotileDrawOptions = {}): PolyCommand[] {\n const tile = options.tile ?? 8;\n const transform = options.transform ?? IDENTITY;\n const z = options.z ?? 0;\n const stroke = options.edge ?? options.fill ?? '#333';\n const strokeWidth = options.edgeWidth ?? Math.max(1, tile / 8);\n const segs = marchingSquaresContours(grid, { cell: tile, x: options.x ?? 0, y: options.y ?? 0 });\n return segs.map((s) => ({\n kind: 'poly',\n points: [s.a.x, s.a.y, s.b.x, s.b.y],\n closed: false,\n transform,\n z,\n stroke,\n strokeWidth,\n round: true,\n }));\n}\n", "// Shared boolean grid for procgen output. Plain data + pure functions (house\n// style) so generated levels serialize, hash, and diff cleanly. Convention:\n// `1` = solid/wall, `0` = open/floor \u2014 matching TILE.SOLID / TILE.EMPTY so a\n// grid drops straight into the collision tilemap.\n\nimport { TILE, type TilemapData } from '../physics/tilemap';\n\nexport interface Grid {\n cols: number;\n rows: number;\n /** Row-major cells, length cols*rows. 1 = solid, 0 = open. */\n cells: number[];\n}\n\n/** Allocate a grid filled with a single value (default open). */\nexport function makeGrid(cols: number, rows: number, fill = 0): Grid {\n return { cols, rows, cells: new Array<number>(cols * rows).fill(fill) };\n}\n\n/** Read a cell; out-of-bounds reads as solid (1) so borders seal naturally. */\nexport function gridAt(g: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= g.cols || y >= g.rows) return 1;\n return g.cells[y * g.cols + x];\n}\n\n/** Write a cell (no-op out of bounds). */\nexport function gridSet(g: Grid, x: number, y: number, v: number): void {\n if (x < 0 || y < 0 || x >= g.cols || y >= g.rows) return;\n g.cells[y * g.cols + x] = v;\n}\n\n/** Count solid cells in the 8-neighbourhood (Moore) around (x,y). */\nexport function solidNeighbours(g: Grid, x: number, y: number): number {\n let n = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n if (dx === 0 && dy === 0) continue;\n if (gridAt(g, x + dx, y + dy) === 1) n++;\n }\n }\n return n;\n}\n\n/**\n * Project a grid to collision geometry: 1 \u2192 SOLID, everything else \u2192 EMPTY.\n * The result is a logical, hash-relevant `TilemapData` \u2014 feed it straight to\n * the physics tilemap functions.\n */\nexport function gridToTilemap(g: Grid, tileSize = 32): TilemapData {\n const tiles = g.cells.map((c) => (c === 1 ? TILE.SOLID : TILE.EMPTY));\n return { cols: g.cols, rows: g.rows, tileSize, tiles };\n}\n", "// Coordinate-hash scatter + value noise \u2014 the corpus's actual \"procgen texture\"\n// need (witchcat / cat-survivors do `((x-812347*y)*928371)%17===0`), done right.\n//\n// Every function here is STATELESS and deterministic: the value at a cell is a\n// pure hash of (x, y, seed), so no PRNG stream is threaded and the same world\n// coordinate always decorates the same way \u2014 across frames, reloads, and peers.\n// Output is COSMETIC by intent (decoration placement, dithering, texture): keep\n// it out of `world.hash()`. For logical structure use the carving generators\n// (cave/terrain/rooms), which run off `world.rng`.\n\n/** 32-bit integer hash of a 2D cell + seed. Well-mixed; avalanche on any bit. */\nexport function cellHash(x: number, y: number, seed = 0): number {\n let h = (seed ^ 0x9e3779b9) >>> 0;\n h = Math.imul(h ^ (x | 0), 0x85ebca6b) >>> 0;\n h = Math.imul(h ^ (y | 0), 0xc2b2ae35) >>> 0;\n h ^= h >>> 13;\n h = Math.imul(h, 0x27d4eb2f) >>> 0;\n h ^= h >>> 15;\n return h >>> 0;\n}\n\n/** Deterministic float in [0,1) for a cell \u2014 hash normalized. */\nexport function cellFloat(x: number, y: number, seed = 0): number {\n return cellHash(x, y, seed) / 4294967296;\n}\n\n/** Deterministic integer in [0,n) for a cell (e.g. pick a decoration variant). */\nexport function cellInt(x: number, y: number, n: number, seed = 0): number {\n return Math.floor(cellFloat(x, y, seed) * n);\n}\n\n/** True with ~`probability` at this cell \u2014 the stateless scatter test. */\nexport function scatter(x: number, y: number, probability: number, seed = 0): boolean {\n return cellFloat(x, y, seed) < probability;\n}\n\n/**\n * Enumerate the chosen cells in a rectangle, row-major (ordered). Handy for\n * placing decoration nodes over a visible region without a PRNG. Cosmetic.\n */\nexport function scatterCells(\n x0: number,\n y0: number,\n cols: number,\n rows: number,\n probability: number,\n seed = 0,\n): { x: number; y: number }[] {\n const out: { x: number; y: number }[] = [];\n for (let y = y0; y < y0 + rows; y++) {\n for (let x = x0; x < x0 + cols; x++) {\n if (scatter(x, y, probability, seed)) out.push({ x, y });\n }\n }\n return out;\n}\n\nconst smooth = (t: number): number => t * t * (3 - 2 * t);\n\n/**\n * Value noise in [0,1] at a fractional coordinate \u2014 smooth bilinear blend of the\n * four surrounding integer-cell hashes. This is the deliberately-small\n * alternative to a simplex lib (see JS13K-MINING anti-recommendations): enough\n * for cosmetic terrain tint, cloud cover, wobble; not a gameplay dependency.\n */\nexport function valueNoise(x: number, y: number, seed = 0): number {\n const x0 = Math.floor(x);\n const y0 = Math.floor(y);\n const fx = smooth(x - x0);\n const fy = smooth(y - y0);\n const c00 = cellFloat(x0, y0, seed);\n const c10 = cellFloat(x0 + 1, y0, seed);\n const c01 = cellFloat(x0, y0 + 1, seed);\n const c11 = cellFloat(x0 + 1, y0 + 1, seed);\n const top = c00 + (c10 - c00) * fx;\n const bot = c01 + (c11 - c01) * fx;\n return top + (bot - top) * fy;\n}\n\nexport interface FractalOptions {\n octaves?: number;\n /** Frequency multiplier per octave (default 2). */\n lacunarity?: number;\n /** Amplitude multiplier per octave (default 0.5). */\n gain?: number;\n}\n\n/** Fractal (fBm) value noise \u2014 layered octaves, normalized to [0,1]. Cosmetic. */\nexport function fractalNoise(x: number, y: number, seed = 0, opts: FractalOptions = {}): number {\n const octaves = opts.octaves ?? 4;\n const lacunarity = opts.lacunarity ?? 2;\n const gain = opts.gain ?? 0.5;\n let amp = 1;\n let freq = 1;\n let sum = 0;\n let norm = 0;\n for (let o = 0; o < octaves; o++) {\n sum += amp * valueNoise(x * freq, y * freq, seed + o);\n norm += amp;\n amp *= gain;\n freq *= lacunarity;\n }\n return norm === 0 ? 0 : sum / norm;\n}\n", "// Cave / cavern carving via cellular automata \u2014 space-huggers-style organic\n// caverns. This is LOGICAL structure (it becomes collision geometry), so it is\n// fully deterministic and hash-relevant: all randomness draws from the passed\n// `world.rng`, and every loop iterates row-major (ordered). The knight-dreams\n// anti-pattern (raw `Math.random`) is exactly what this avoids \u2014 pass a seeded\n// `Rng` and the same seed always carves the same cave.\n\nimport type { Rng } from '../core/rng';\nimport { makeGrid, gridSet, solidNeighbours, type Grid } from './grid';\n\nexport interface CaveOptions {\n cols: number;\n rows: number;\n /** Initial solid-fill probability (0..1). ~0.45 gives balanced caverns. */\n fill?: number;\n /** Smoothing passes (more = rounder, larger chambers). Default 4. */\n steps?: number;\n /** A cell becomes solid if it has \u2265 this many solid neighbours. Default 5. */\n birth?: number;\n /** A solid cell survives if it has \u2265 this many solid neighbours. Default 4. */\n survive?: number;\n /** Force the outer ring solid so the cave is sealed. Default true. */\n border?: boolean;\n}\n\n/**\n * Generate a cave grid (1 = rock, 0 = open) with cellular automata. Deterministic\n * given `rng`'s state + options. Feed the result to `gridToTilemap` for physics.\n */\nexport function generateCave(rng: Rng, opts: CaveOptions): Grid {\n const { cols, rows } = opts;\n const fill = opts.fill ?? 0.45;\n const steps = opts.steps ?? 4;\n const birth = opts.birth ?? 5;\n const survive = opts.survive ?? 4;\n const border = opts.border ?? true;\n\n let g = makeGrid(cols, rows, 0);\n // Random seed fill \u2014 ordered draws from world.rng so replays match.\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n const edge = border && (x === 0 || y === 0 || x === cols - 1 || y === rows - 1);\n gridSet(g, x, y, edge || rng.chance(fill) ? 1 : 0);\n }\n }\n\n // Smoothing passes into a fresh grid (double-buffer; no in-place bias).\n for (let s = 0; s < steps; s++) {\n const next = makeGrid(cols, rows, 0);\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (border && (x === 0 || y === 0 || x === cols - 1 || y === rows - 1)) {\n gridSet(next, x, y, 1);\n continue;\n }\n const n = solidNeighbours(g, x, y);\n const wasSolid = g.cells[y * cols + x] === 1;\n gridSet(next, x, y, (wasSolid ? n >= survive : n >= birth) ? 1 : 0);\n }\n }\n g = next;\n }\n return g;\n}\n", "// Endless terrain surface \u2014 knight-dreams' infinite auto-runner terrain, done\n// deterministically. The ground height at a column is a PURE function of the\n// column index + seed (layered value noise), so it needs no PRNG stream and no\n// stored state: any column can be sampled in any order and an infinite world\n// stays perfectly reproducible across peers and reloads.\n//\n// This is LOGICAL structure (the surface is collision), so it belongs in the\n// hash \u2014 and because it is a stateless pure function of (col, seed), it is\n// deterministic by construction. Seed is explicit (derive it from `world.rng`\n// once at setup, e.g. `rng.int(1e9)`), never `Math.random`.\n\nimport { clamp } from '../core/math';\nimport { fractalNoise, type FractalOptions } from './scatter';\n\nexport interface TerrainOptions {\n /** Baseline ground row (tiles from the top). */\n base: number;\n /** Peak deviation above/below the baseline (tiles). */\n amplitude: number;\n /** Horizontal frequency \u2014 smaller = longer, smoother hills. Default 0.08. */\n scale?: number;\n /** Clamp ground into [minRow, maxRow] so it stays on-screen. */\n minRow?: number;\n maxRow?: number;\n seed?: number;\n fractal?: FractalOptions;\n}\n\n/**\n * Ground row (integer tile Y) for a column. Lower row = higher ground. Sampling\n * the same (col, opts) always returns the same height \u2014 the endless-terrain\n * contract.\n */\nexport function terrainHeight(col: number, opts: TerrainOptions): number {\n const scale = opts.scale ?? 0.08;\n const seed = opts.seed ?? 0;\n // valueNoise is [0,1]; center to [-1,1] so the surface undulates about `base`.\n const n = fractalNoise(col * scale, 0, seed, opts.fractal) * 2 - 1;\n let row = Math.round(opts.base + n * opts.amplitude);\n if (opts.minRow !== undefined || opts.maxRow !== undefined) {\n row = clamp(row, opts.minRow ?? -Infinity, opts.maxRow ?? Infinity);\n }\n return row;\n}\n\n/** Ground rows for a contiguous chunk `[startCol, startCol+count)` (ordered). */\nexport function terrainSlice(startCol: number, count: number, opts: TerrainOptions): number[] {\n const out = new Array<number>(count);\n for (let i = 0; i < count; i++) out[i] = terrainHeight(startCol + i, opts);\n return out;\n}\n\n/** True when a tile is solid ground (at or below the surface row) at (col,row). */\nexport function isGround(col: number, row: number, opts: TerrainOptions): boolean {\n return row >= terrainHeight(col, opts);\n}\n", "// Room / segment layout \u2014 space-huggers-style multi-floor bases. Places\n// non-overlapping rectangular rooms into a solid grid and links them with\n// L-shaped corridors, carving floor (0) out of rock (1). LOGICAL structure, so\n// it is hash-relevant: all randomness is drawn from the passed `world.rng` and\n// rooms connect in placement order (ordered iteration) \u2014 same seed, same base.\n\nimport type { Rng } from '../core/rng';\nimport { makeGrid, gridSet, type Grid } from './grid';\n\nexport interface Room {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface DungeonOptions {\n cols: number;\n rows: number;\n /** How many placement attempts to make (actual rooms \u2264 this). Default 12. */\n attempts?: number;\n /** Room side length range (tiles), inclusive. */\n minSize?: number;\n maxSize?: number;\n /** Keep a 1-tile solid margin around the grid. Default true. */\n border?: boolean;\n}\n\nexport interface Dungeon {\n rooms: Room[];\n grid: Grid;\n}\n\n/** Center tile of a room (floored). */\nexport function roomCenter(r: Room): { x: number; y: number } {\n return { x: Math.floor(r.x + r.w / 2), y: Math.floor(r.y + r.h / 2) };\n}\n\nfunction overlaps(a: Room, b: Room): boolean {\n // 1-tile gap between rooms so walls never merge.\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\n}\n\nfunction carveRoom(g: Grid, r: Room): void {\n for (let y = r.y; y < r.y + r.h; y++) {\n for (let x = r.x; x < r.x + r.w; x++) gridSet(g, x, y, 0);\n }\n}\n\nfunction carveHCorridor(g: Grid, x0: number, x1: number, y: number): void {\n for (let x = Math.min(x0, x1); x <= Math.max(x0, x1); x++) gridSet(g, x, y, 0);\n}\nfunction carveVCorridor(g: Grid, y0: number, y1: number, x: number): void {\n for (let y = Math.min(y0, y1); y <= Math.max(y0, y1); y++) gridSet(g, x, y, 0);\n}\n\n/**\n * Generate a room-and-corridor layout in a grid (1 = wall, 0 = floor).\n * Deterministic given `rng` state + options; consecutive rooms are joined so the\n * whole floor is connected. Feed `.grid` to `gridToTilemap` for physics.\n */\nexport function generateDungeon(rng: Rng, opts: DungeonOptions): Dungeon {\n const { cols, rows } = opts;\n const attempts = opts.attempts ?? 12;\n const minSize = opts.minSize ?? 4;\n const maxSize = opts.maxSize ?? 8;\n const margin = (opts.border ?? true) ? 1 : 0;\n\n const g = makeGrid(cols, rows, 1); // start solid, carve into it\n const rooms: Room[] = [];\n\n for (let i = 0; i < attempts; i++) {\n const w = rng.intRange(minSize, maxSize);\n const h = rng.intRange(minSize, maxSize);\n const x = rng.intRange(margin, cols - w - margin - 1);\n const y = rng.intRange(margin, rows - h - margin - 1);\n if (x < margin || y < margin) continue;\n const room: Room = { x, y, w, h };\n if (rooms.some((r) => overlaps(room, r))) continue;\n\n carveRoom(g, room);\n if (rooms.length > 0) {\n // Connect to the previous room with an L corridor; coin-flip the elbow.\n const prev = roomCenter(rooms[rooms.length - 1]);\n const cur = roomCenter(room);\n if (rng.chance(0.5)) {\n carveHCorridor(g, prev.x, cur.x, prev.y);\n carveVCorridor(g, prev.y, cur.y, cur.x);\n } else {\n carveVCorridor(g, prev.y, cur.y, prev.x);\n carveHCorridor(g, prev.x, cur.x, cur.y);\n }\n }\n rooms.push(room);\n }\n\n return { rooms, grid: g };\n}\n", "// Procedural audio bus. Code-as-sound: zzfx-style tone synthesis + an ambient\n// pad, no audio files. A no-op when there's no AudioContext (Node/headless), so\n// automated runs are silent by construction (a narrow-js invariant).\n\nexport interface Volumes {\n master: number;\n music: number;\n sfx: number;\n muted: boolean;\n}\n\nconst DEFAULT_VOLUMES: Volumes = { master: 0.7, music: 0.6, sfx: 0.8, muted: false };\n\n/** A single zzfx-ish tone spec. */\nexport interface Tone {\n freq: number;\n duration: number;\n type?: OscillatorType;\n gain?: number;\n delay?: number;\n /** Stereo position -1 (left) \u2026 1 (right) \u2014 the spatial-audio hook. */\n pan?: number;\n}\n\nexport class AudioBus {\n private ctx: AudioContext | null = null;\n private master: GainNode | null = null;\n private musicGain: GainNode | null = null;\n private sfxGain: GainNode | null = null;\n private vol: Volumes = { ...DEFAULT_VOLUMES };\n private padOn = false;\n\n get available(): boolean {\n return typeof globalThis.AudioContext !== 'undefined' || 'webkitAudioContext' in globalThis;\n }\n get started(): boolean {\n return !!this.ctx;\n }\n\n /** Must be called from a user gesture (browser autoplay policy). */\n start(): void {\n if (this.ctx) {\n void this.ctx.resume();\n return;\n }\n if (!this.available) return;\n const Ctx =\n globalThis.AudioContext ||\n (globalThis as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;\n this.ctx = new Ctx();\n this.master = this.ctx.createGain();\n this.musicGain = this.ctx.createGain();\n this.sfxGain = this.ctx.createGain();\n this.musicGain.connect(this.master);\n this.sfxGain.connect(this.master);\n this.master.connect(this.ctx.destination);\n this.applyVolumes();\n }\n\n setVolumes(v: Partial<Volumes>): void {\n this.vol = { ...this.vol, ...v };\n this.applyVolumes();\n }\n getVolumes(): Volumes {\n return { ...this.vol };\n }\n\n private applyVolumes(): void {\n if (!this.ctx || !this.master || !this.musicGain || !this.sfxGain) return;\n const t = this.ctx.currentTime;\n this.master.gain.setTargetAtTime(this.vol.muted ? 0 : this.vol.master, t, 0.04);\n this.musicGain.gain.setTargetAtTime(this.vol.music * 0.5, t, 0.04);\n this.sfxGain.gain.setTargetAtTime(this.vol.sfx, t, 0.04);\n }\n\n /** Play a single tone (no-op if audio unstarted). */\n tone(spec: Tone): void {\n if (!this.ctx || !this.sfxGain) return;\n const { freq, duration, type = 'sine', gain = 0.2, delay = 0, pan } = spec;\n const t = this.ctx.currentTime + delay;\n const osc = this.ctx.createOscillator();\n osc.type = type;\n osc.frequency.value = freq;\n const g = this.ctx.createGain();\n g.gain.setValueAtTime(0, t);\n g.gain.linearRampToValueAtTime(gain, t + 0.008);\n g.gain.exponentialRampToValueAtTime(0.0001, t + duration);\n osc.connect(g);\n if (pan !== undefined && typeof this.ctx.createStereoPanner === 'function') {\n const p = this.ctx.createStereoPanner();\n p.pan.value = Math.max(-1, Math.min(1, pan));\n g.connect(p);\n p.connect(this.sfxGain);\n } else {\n g.connect(this.sfxGain);\n }\n osc.start(t);\n osc.stop(t + duration + 0.05);\n }\n\n /**\n * A positional cue: gain falls with distance, pan follows the horizontal\n * offset. dx/dist in design-space px; hearing range sets the falloff.\n */\n spatial(freq: number, dx: number, dist: number, hearing = 600, duration = 0.18, type: OscillatorType = 'sawtooth'): void {\n if (dist > hearing) return;\n const near = 1 - dist / hearing;\n this.tone({ freq, duration, type, gain: 0.04 + near * near * 0.3, pan: Math.max(-1, Math.min(1, dx / (hearing * 0.6))) });\n }\n\n /** Play a sequence of tones as an arpeggio/chord. */\n play(tones: Tone[]): void {\n for (const t of tones) this.tone(t);\n }\n\n /** Convenience SFX. */\n blip(freq = 520): void {\n this.tone({ freq, duration: 0.06, type: 'sine', gain: 0.18 });\n }\n chime(): void {\n [523.25, 659.25, 783.99].forEach((f, i) => this.tone({ freq: f, duration: 0.9 - i * 0.15, type: 'sine', gain: 0.15, delay: i * 0.04 }));\n }\n success(): void {\n [392, 493.88, 587.33, 783.99].forEach((f, i) => this.tone({ freq: f, duration: 0.4, type: 'triangle', gain: 0.15, delay: i * 0.08 }));\n }\n thud(): void {\n this.tone({ freq: 130, duration: 0.14, type: 'sine', gain: 0.22 });\n }\n\n /** Start a soft evolving ambient pad on the music bus. */\n startAmbient(root = 110, voices = [1, 1.5, 2, 2.5]): void {\n if (!this.ctx || !this.musicGain || this.padOn) return;\n this.padOn = true;\n const filter = this.ctx.createBiquadFilter();\n filter.type = 'lowpass';\n filter.frequency.value = 900;\n filter.connect(this.musicGain);\n const bus = this.ctx.createGain();\n bus.gain.value = 0;\n bus.connect(filter);\n for (const mult of voices) {\n const osc = this.ctx.createOscillator();\n osc.type = 'triangle';\n osc.frequency.value = root * mult;\n const g = this.ctx.createGain();\n g.gain.value = 0.1 / voices.length;\n osc.connect(g);\n g.connect(bus);\n osc.start();\n }\n bus.gain.setTargetAtTime(0.9, this.ctx.currentTime, 3);\n }\n}\n\n/** Shared default bus. */\nexport const audio = new AudioBus();\n", "// DOM overlay screens \u2014 titles, menus, game-over, HUD. Crisp DOM type instead of\n// canvas text (narrow-js lesson: humans compare canvas text to DOM and canvas\n// loses). Keyboard-navigable by construction. Browser-only; no-op guards for SSR.\n\nexport interface MenuAction {\n label: string;\n onSelect: () => void;\n primary?: boolean;\n}\n\nexport interface ScreenSpec {\n title?: string;\n /** Subtitle / body text (plain text or HTML string). */\n body?: string;\n /** Menu actions, navigable with up/down + Enter. */\n actions?: MenuAction[];\n /** Dim the game behind the screen. */\n dim?: boolean;\n /** Extra class for theming. */\n className?: string;\n}\n\nexport interface ScreenHandle {\n close(): void;\n readonly element: HTMLElement;\n}\n\nlet active: ScreenHandle | null = null;\n\nconst STYLE_ID = 'hayao-overlay-style';\nconst CSS = `\n.hy-scrim{position:absolute;inset:0;display:grid;place-items:center;z-index:50;font-family:var(--hy-serif,Georgia,serif)}\n.hy-scrim.dim{background:rgba(30,24,14,.5);backdrop-filter:blur(2px)}\n.hy-card{background:var(--hy-paper,#fbf6ea);color:var(--hy-ink,#3d3323);border:1px solid var(--hy-line,#d9ccae);border-radius:14px;box-shadow:0 14px 44px rgba(40,30,15,.3);padding:26px 30px;max-width:440px;text-align:center}\n.hy-card h1{margin:0 0 6px;font-size:30px}\n.hy-card .hy-body{color:var(--hy-ink-soft,#6f6047);font-size:15px;line-height:1.5;margin-bottom:18px}\n.hy-menu{display:flex;flex-direction:column;gap:8px;align-items:stretch}\n.hy-item{font:inherit;font-size:16px;padding:9px 16px;border-radius:9px;border:1px solid var(--hy-line,#d9ccae);background:transparent;color:inherit;cursor:pointer;transition:transform .1s,background .1s}\n.hy-item:hover,.hy-item.sel{background:var(--hy-accent,#a11d3a);color:#fdf3ee;border-color:transparent;transform:translateY(-1px)}\n.hy-item.primary{background:var(--hy-accent,#a11d3a);color:#fdf3ee;border-color:transparent}\n`;\n\nfunction ensureStyle(): void {\n if (typeof document === 'undefined' || document.getElementById(STYLE_ID)) return;\n const s = document.createElement('style');\n s.id = STYLE_ID;\n s.textContent = CSS;\n document.head.appendChild(s);\n}\n\nlet host: HTMLElement | null = null;\n/** Set the element overlays mount into (defaults to document.body). */\nexport function setOverlayHost(el: HTMLElement): void {\n host = el;\n}\n\n/** Show a screen (replaces any current one). Returns a handle. */\nexport function showScreen(spec: ScreenSpec): ScreenHandle {\n if (typeof document === 'undefined') {\n return { close() {}, element: null as unknown as HTMLElement };\n }\n ensureStyle();\n hideScreen();\n\n const scrim = document.createElement('div');\n scrim.className = `hy-scrim${spec.dim === false ? '' : ' dim'}${spec.className ? ' ' + spec.className : ''}`;\n const card = document.createElement('div');\n card.className = 'hy-card';\n\n if (spec.title) {\n const h = document.createElement('h1');\n h.textContent = spec.title;\n card.appendChild(h);\n }\n if (spec.body) {\n const b = document.createElement('div');\n b.className = 'hy-body';\n b.innerHTML = spec.body;\n card.appendChild(b);\n }\n\n const actions = spec.actions ?? [];\n let sel = Math.max(0, actions.findIndex((a) => a.primary));\n if (sel < 0) sel = 0;\n const items: HTMLButtonElement[] = [];\n if (actions.length) {\n const menu = document.createElement('div');\n menu.className = 'hy-menu';\n actions.forEach((a, i) => {\n const btn = document.createElement('button');\n btn.className = `hy-item${a.primary ? ' primary' : ''}`;\n btn.textContent = a.label;\n btn.addEventListener('click', () => a.onSelect());\n btn.addEventListener('mouseenter', () => setSel(i));\n menu.appendChild(btn);\n items.push(btn);\n });\n card.appendChild(menu);\n }\n\n function setSel(i: number): void {\n sel = (i + items.length) % items.length;\n items.forEach((el, k) => el.classList.toggle('sel', k === sel));\n }\n if (items.length) setSel(sel);\n\n const onKey = (e: KeyboardEvent) => {\n if (!items.length) return;\n if (e.code === 'ArrowDown') { setSel(sel + 1); e.preventDefault(); }\n else if (e.code === 'ArrowUp') { setSel(sel - 1); e.preventDefault(); }\n else if (e.code === 'Enter' || e.code === 'Space') { actions[sel]?.onSelect(); e.preventDefault(); }\n };\n document.addEventListener('keydown', onKey);\n\n scrim.appendChild(card);\n (host ?? document.body).appendChild(scrim);\n\n const handle: ScreenHandle = {\n element: scrim,\n close() {\n document.removeEventListener('keydown', onKey);\n scrim.remove();\n if (active === handle) active = null;\n },\n };\n active = handle;\n return handle;\n}\n\nexport function hideScreen(): void {\n active?.close();\n}\n", "// Player settings, persisted to localStorage and pushed into the audio bus.\n// Framework-agnostic (plain object + subscribe), so any game/UI can bind to it.\n\nimport { audio } from '../audio/audio';\n\nexport interface Settings {\n master: number;\n music: number;\n sfx: number;\n muted: boolean;\n colorblind: boolean;\n reducedMotion: boolean;\n}\n\nconst KEY = 'hayao.settings.v1';\nconst DEFAULTS: Settings = { master: 0.7, music: 0.6, sfx: 0.8, muted: false, colorblind: false, reducedMotion: false };\n\ntype Sub = (s: Settings) => void;\n\nclass SettingsStore {\n private state: Settings;\n private subs = new Set<Sub>();\n\n constructor() {\n this.state = this.load();\n this.pushToAudio();\n }\n\n get(): Settings {\n return { ...this.state };\n }\n\n set(patch: Partial<Settings>): void {\n this.state = { ...this.state, ...patch };\n this.save();\n this.pushToAudio();\n for (const fn of this.subs) fn(this.get());\n }\n\n subscribe(fn: Sub): () => void {\n this.subs.add(fn);\n return () => this.subs.delete(fn);\n }\n\n private pushToAudio(): void {\n audio.setVolumes({ master: this.state.master, music: this.state.music, sfx: this.state.sfx, muted: this.state.muted });\n }\n\n private load(): Settings {\n try {\n const raw = typeof localStorage !== 'undefined' && localStorage.getItem(KEY);\n if (raw) return { ...DEFAULTS, ...JSON.parse(raw) };\n } catch {\n /* ignore */\n }\n return { ...DEFAULTS };\n }\n private save(): void {\n try {\n localStorage.setItem(KEY, JSON.stringify(this.state));\n } catch {\n /* ignore */\n }\n }\n}\n\nexport const settings = new SettingsStore();\n\n// \u2500\u2500 Fullscreen helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport function toggleFullscreen(): void {\n if (typeof document === 'undefined') return;\n const doc = document as Document & { webkitFullscreenElement?: Element; webkitExitFullscreen?: () => void };\n const el = document.documentElement as HTMLElement & { webkitRequestFullscreen?: () => void };\n if (document.fullscreenElement || doc.webkitFullscreenElement) {\n (document.exitFullscreen ?? doc.webkitExitFullscreen)?.call(document);\n } else {\n (el.requestFullscreen ?? el.webkitRequestFullscreen)?.call(el);\n }\n}\n", "// The game shell: a pause menu (Esc) with volume, mute, fullscreen, restart, and\n// back-to-hub \u2014 every game gets it for free (narrow-js lesson: the shell owns Esc,\n// kills debug-key landmines, and standardizes chrome). Browser-only.\n\nimport { audio } from '../audio/audio';\nimport { settings, toggleFullscreen } from './settings';\nimport { showScreen, hideScreen } from './overlay';\n\nexport interface ShellOptions {\n onRestart?: () => void;\n onQuit?: () => void;\n /** Called with true when paused, false when resumed. */\n onPause?: (paused: boolean) => void;\n title?: string;\n}\n\nexport class Shell {\n private paused = false;\n private opts: ShellOptions;\n private keyHandler: (e: KeyboardEvent) => void;\n\n constructor(opts: ShellOptions = {}) {\n this.opts = opts;\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.code === 'Escape') {\n e.preventDefault();\n this.toggle();\n }\n };\n if (typeof document !== 'undefined') document.addEventListener('keydown', this.keyHandler);\n }\n\n get isPaused(): boolean {\n return this.paused;\n }\n\n toggle(): void {\n this.paused ? this.resume() : this.pause();\n }\n\n pause(): void {\n if (this.paused) return;\n this.paused = true;\n audio.blip(440);\n this.opts.onPause?.(true);\n this.render();\n }\n\n resume(): void {\n if (!this.paused) return;\n this.paused = false;\n hideScreen();\n this.opts.onPause?.(false);\n }\n\n private render(): void {\n const s = settings.get();\n const vol = (label: string, v: number) => `${label}: ${Math.round(v * 100)}`;\n showScreen({\n title: this.opts.title ?? 'Paused',\n body:\n `<div style=\"font-size:13px;text-align:left;line-height:1.9\">` +\n `${vol('Master', s.master)} \u00B7 ${vol('Music', s.music)} \u00B7 ${vol('Sfx', s.sfx)}` +\n `<br/><span style=\"opacity:.7\">Use the menu, or keys: M mute \u00B7 F fullscreen</span></div>`,\n actions: [\n { label: 'Resume', primary: true, onSelect: () => this.resume() },\n { label: s.muted ? 'Unmute (M)' : 'Mute (M)', onSelect: () => { settings.set({ muted: !settings.get().muted }); this.render(); } },\n { label: 'Music \u2212/+', onSelect: () => { const m = Math.min(1, settings.get().music + 0.1) % 1.05; settings.set({ music: m > 1 ? 0 : m }); this.render(); } },\n { label: 'Fullscreen (F)', onSelect: () => toggleFullscreen() },\n ...(this.opts.onRestart ? [{ label: 'Restart', onSelect: () => { this.resume(); this.opts.onRestart!(); } }] : []),\n ...(this.opts.onQuit ? [{ label: 'Quit', onSelect: () => { this.resume(); this.opts.onQuit!(); } }] : []),\n ],\n });\n }\n\n dispose(): void {\n if (typeof document !== 'undefined') document.removeEventListener('keydown', this.keyHandler);\n hideScreen();\n }\n}\n", "// Screen transitions + a cinematic sequencer \u2014 the layer between showScreen()\n// (a static DOM dialog) and a scripted, animated scene change.\n//\n// Transition is a COSMETIC scene node that paints a full-screen wipe (fade /\n// iris / dither) in SCREEN space, so it sits on top of the camera untouched. It\n// runs on the fixed clock dt \u2014 not rAF delta \u2014 so a lockstep replay wipes\n// identically, and because it draws through the display list it renders headless\n// (a filmstrip can prove it). The classic move is cover \u2192 onMidpoint (swap the\n// level) \u2192 reveal, all gated off `busy`.\n//\n// CinematicPlayer walks a list of pure-data steps: each step runs an `enter`\n// hook (aim the camera, set text, mutate state) then holds until its duration\n// elapses AND its `until` gate passes \u2014 which is how you fade-gate advancement\n// (step waits on `!transition.busy`). Also cosmetic and dt-driven.\n\nimport { clamp, lerp, type Rect, type Transform, IDENTITY } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\n\nexport type WipeKind = 'fade' | 'circle' | 'dither';\n\n// Ordered 4\u00D74 Bayer matrix (thresholds 0..15) for the dither dissolve.\nconst BAYER4 = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];\nconst smoothstep = (t: number): number => t * t * (3 - 2 * t);\n\ninterface Ramp {\n from: number | undefined; // resolved to current coverage when the ramp starts\n to: number;\n dur: number;\n elapsed: number;\n onEnd?: () => void;\n}\n\nexport interface WipeOptions {\n /** Seconds to cover the screen (default 0.4). */\n cover?: number;\n /** Seconds to hold fully covered before revealing (default 0). */\n hold?: number;\n /** Seconds to reveal the scene again (default = cover). */\n reveal?: number;\n /** Fired at full cover \u2014 swap the level/scene here. */\n onMidpoint?: () => void;\n /** Fired once the reveal finishes. */\n onDone?: () => void;\n}\n\nexport interface TransitionConfig extends NodeConfig {\n kind?: WipeKind;\n /** Overlay colour. */\n color?: string;\n /** Screen size in px (pass world.width / world.height). */\n width?: number;\n height?: number;\n /** Dither cell size in px (default 28). */\n cell?: number;\n}\n\n/**\n * A full-screen wipe overlay. Add it to the tree (cosmetic), then drive it with\n * `cover()` / `reveal()` / `wipe()`. `coverage` runs 0 (clear) \u2192 1 (opaque).\n */\nexport class ScreenTransition extends Node {\n override readonly type: string = 'ScreenTransition';\n kind: WipeKind;\n color: string;\n screenW: number;\n screenH: number;\n cell: number;\n /** 0 = fully clear, 1 = fully covering. */\n coverage = 0;\n private queue: Ramp[] = [];\n\n constructor(config: TransitionConfig = {}) {\n super(config);\n this.cosmetic = true;\n this.kind = config.kind ?? 'fade';\n this.color = config.color ?? '#1a1410';\n this.screenW = config.width ?? 1280;\n this.screenH = config.height ?? 720;\n this.cell = config.cell ?? 28;\n }\n\n /** True while a wipe is animating. */\n get busy(): boolean {\n return this.queue.length > 0;\n }\n\n private enqueue(to: number, dur: number, onEnd?: () => void): void {\n this.queue.push({ from: undefined, to, dur: Math.max(1e-4, dur), elapsed: 0, onEnd });\n }\n\n /** Animate the overlay to fully covering over `dur` seconds. */\n cover(dur = 0.4, onEnd?: () => void): this {\n this.enqueue(1, dur, onEnd);\n return this;\n }\n\n /** Animate the overlay back to fully clear over `dur` seconds. */\n reveal(dur = 0.4, onEnd?: () => void): this {\n this.enqueue(0, dur, onEnd);\n return this;\n }\n\n /** Hold the current coverage for `dur` seconds (chains after cover/reveal). */\n hold(dur: number, onEnd?: () => void): this {\n // Target the pending end-state so a mid-queue hold keeps that coverage.\n const target = this.queue.length ? this.queue[this.queue.length - 1].to : this.coverage;\n this.enqueue(target, dur, onEnd);\n return this;\n }\n\n /** The classic cover \u2192 onMidpoint \u2192 reveal sequence. Returns this for chaining. */\n wipe(opts: WipeOptions = {}): this {\n const cover = opts.cover ?? 0.4;\n this.cover(cover, () => {\n this.emit('covered', undefined);\n opts.onMidpoint?.();\n });\n if (opts.hold) this.hold(opts.hold);\n this.reveal(opts.reveal ?? cover, () => {\n this.emit('done', undefined);\n opts.onDone?.();\n });\n return this;\n }\n\n /** Signal emitted at full cover (the midpoint). */\n get covered() {\n return this.signal('covered');\n }\n /** Signal emitted when a wipe fully finishes revealing. */\n get done() {\n return this.signal('done');\n }\n\n protected override onProcess(dt: number): void {\n const step = this.queue[0];\n if (!step) return;\n if (step.from === undefined) step.from = this.coverage;\n step.elapsed += dt;\n const t = clamp(step.elapsed / step.dur, 0, 1);\n this.coverage = lerp(step.from, step.to, smoothstep(t));\n if (t >= 1) {\n this.coverage = step.to;\n const end = step.onEnd;\n this.queue.shift();\n end?.();\n }\n }\n\n protected override draw(out: DrawCommand[], _world: Transform): void {\n const c = this.coverage;\n if (c <= 0) return;\n // Screen space: ignore the camera transform so the wipe stays fixed.\n const z = this.z;\n if (this.kind === 'fade') {\n out.push({ kind: 'rect', x: 0, y: 0, w: this.screenW, h: this.screenH, fill: this.color, opacity: c, transform: IDENTITY, z });\n return;\n }\n if (this.kind === 'circle') {\n // Iris: a filled disc grown from the centre to the far corner.\n const cx = this.screenW / 2;\n const cy = this.screenH / 2;\n const diag = Math.sqrt(cx * cx + cy * cy);\n out.push({ kind: 'circle', cx, cy, radius: c * diag, fill: this.color, transform: IDENTITY, z });\n return;\n }\n // Dither: an ordered dissolve \u2014 one opaque cell per Bayer threshold below c.\n const cols = Math.ceil(this.screenW / this.cell);\n const rows = Math.ceil(this.screenH / this.cell);\n for (let cy = 0; cy < rows; cy++) {\n for (let cx = 0; cx < cols; cx++) {\n const threshold = (BAYER4[(cx & 3) + ((cy & 3) << 2)] + 0.5) / 16;\n if (threshold < c) {\n out.push({ kind: 'rect', x: cx * this.cell, y: cy * this.cell, w: this.cell, h: this.cell, fill: this.color, transform: IDENTITY, z });\n }\n }\n }\n }\n}\n\n// \u2500\u2500 Cinematic sequencer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CinematicStep {\n /** Optional label (handy for debugging/skip logic). */\n name?: string;\n /** Runs once when the step begins \u2014 aim the camera, set text, mutate state. */\n enter?: () => void;\n /** Minimum seconds to hold on this step before advancing (default 0). */\n duration?: number;\n /** Gate: advance only once this returns true (e.g. `() => !transition.busy`). */\n until?: () => boolean;\n}\n\n/**\n * Runs a list of pure-data cinematic steps on the fixed clock. Each step's\n * `enter` fires once, then the player waits for both its `duration` and its\n * `until` gate before moving on \u2014 the fade-gate pattern for scripted intros.\n * Cosmetic: it only orchestrates view/state changes, holds no hashed state.\n */\nexport class CinematicPlayer extends Node {\n override readonly type: string = 'CinematicPlayer';\n private steps: CinematicStep[] = [];\n private index = -1;\n private elapsed = 0;\n private running = false;\n private onFinish?: () => void;\n\n constructor(config: NodeConfig = {}) {\n super(config);\n this.cosmetic = true;\n }\n\n /** Load and start a sequence. `onDone` fires after the last step advances. */\n play(steps: CinematicStep[], onDone?: () => void): this {\n this.steps = steps;\n this.onFinish = onDone;\n this.index = -1;\n this.elapsed = 0;\n this.running = steps.length > 0;\n this.advance();\n return this;\n }\n\n /** True while a sequence is playing. */\n get active(): boolean {\n return this.running;\n }\n /** Index of the step currently on screen (\u22121 before play / after finish). */\n get step(): number {\n return this.index;\n }\n\n /** Signal emitted when the whole sequence finishes. */\n get finished() {\n return this.signal('finished');\n }\n\n private advance(): void {\n this.index++;\n this.elapsed = 0;\n if (this.index >= this.steps.length) {\n this.running = false;\n this.index = -1;\n this.emit('finished', undefined);\n this.onFinish?.();\n return;\n }\n this.steps[this.index].enter?.();\n }\n\n /** Abort the sequence immediately (no further enters, no finish callback). */\n stop(): void {\n this.running = false;\n this.index = -1;\n this.steps = [];\n }\n\n protected override onProcess(dt: number): void {\n if (!this.running) return;\n this.elapsed += dt;\n const s = this.steps[this.index];\n const durationDone = this.elapsed >= (s.duration ?? 0);\n const gateOpen = s.until ? s.until() : true;\n if (durationDone && gateOpen) this.advance();\n }\n}\n\n/**\n * Convenience: make a Transition sized to a world and add it to a parent (the\n * scene root by default, so it paints over everything). Returns the node.\n */\nexport function addTransition(parent: Node, config: TransitionConfig = {}): ScreenTransition {\n const t = new ScreenTransition({ z: 10_000, ...config });\n return parent.addChild(t);\n}\n\n/** A cinematic step that fires a wipe and gates advancement on its completion. */\nexport function wipeStep(transition: ScreenTransition, opts: WipeOptions & { name?: string } = {}): CinematicStep {\n return {\n name: opts.name ?? 'wipe',\n enter: () => transition.wipe(opts),\n until: () => !transition.busy,\n };\n}\n\n/** Screen rect helper for wiring a Transition into other 9-slice/UI code. */\nexport const screenRect = (w: number, h: number): Rect => ({ x: 0, y: 0, w, h });\n", "// Generic winnability solver. Turn-based/puzzle logic implements the pure\n// Puzzle interface; the solver proves a level beatable by search. Deterministic\n// opponent (fixed order + tie-breaks) means single-agent BFS \u2014 no adversarial\n// branching. (narrow-js's insight, generalized and typed.)\n//\n// Rule of the house: a hand-authored level is presumed WRONG until the solver\n// proves it winnable. In-head verification has a documented failure rate.\n\nexport interface Puzzle<State, Move> {\n /** Starting state (optionally per level index). */\n initial(level?: number): State;\n /** Legal moves from a state, in deterministic order. */\n moves(state: State): Move[];\n /** Apply a player move (may fold in a deterministic opponent response). */\n apply(state: State, move: Move): State;\n /** Win test. */\n isWin(state: State): boolean;\n /** Optional dead/lost test \u2014 pruned from the search. */\n isDead?(state: State): boolean;\n /** Canonical key for de-duplication (visited set). */\n key(state: State): string;\n}\n\nexport interface SolveResult<Move> {\n solvable: boolean;\n /** Shortest winning move sequence, if found. */\n path?: Move[];\n /** Depth of the shortest solution. */\n depth?: number;\n /** Nodes expanded (a difficulty/complexity proxy). */\n nodes: number;\n /** True if the search hit a cap before proving/\u200Bdisproving. */\n exhausted: boolean;\n}\n\nexport interface SolveOptions {\n level?: number;\n maxDepth?: number;\n nodeCap?: number;\n}\n\n/** Breadth-first search \u2192 the shortest solution and a real winnability proof. */\nexport function solve<State, Move>(\n puzzle: Puzzle<State, Move>,\n options: SolveOptions = {},\n): SolveResult<Move> {\n const maxDepth = options.maxDepth ?? 60;\n const nodeCap = options.nodeCap ?? 1_000_000;\n const start = puzzle.initial(options.level);\n\n if (puzzle.isWin(start)) return { solvable: true, path: [], depth: 0, nodes: 0, exhausted: false };\n\n interface QNode {\n state: State;\n path: Move[];\n }\n let frontier: QNode[] = [{ state: start, path: [] }];\n const seen = new Set<string>([puzzle.key(start)]);\n let nodes = 0;\n\n for (let depth = 0; depth < maxDepth && frontier.length > 0; depth++) {\n const next: QNode[] = [];\n for (const { state, path } of frontier) {\n for (const move of puzzle.moves(state)) {\n if (nodes >= nodeCap) return { solvable: false, nodes, exhausted: true };\n nodes++;\n const after = puzzle.apply(state, move);\n if (puzzle.isDead?.(after)) continue;\n if (puzzle.isWin(after)) {\n return { solvable: true, path: [...path, move], depth: depth + 1, nodes, exhausted: false };\n }\n const k = puzzle.key(after);\n if (!seen.has(k)) {\n seen.add(k);\n next.push({ state: after, path: [...path, move] });\n }\n }\n }\n frontier = next;\n }\n return { solvable: false, nodes, exhausted: frontier.length > 0 };\n}\n\n/**\n * Assert a puzzle level is winnable (throws with detail if not). Use in tests as\n * the content-balance gate.\n */\nexport function assertSolvable<State, Move>(\n puzzle: Puzzle<State, Move>,\n options: SolveOptions = {},\n): SolveResult<Move> {\n const result = solve(puzzle, options);\n if (!result.solvable) {\n throw new Error(\n `hayao: level ${options.level ?? 0} is NOT winnable ` +\n `(expanded ${result.nodes} nodes${result.exhausted ? ', search capped \u2014 raise nodeCap/maxDepth' : ''}).`,\n );\n }\n return result;\n}\n", "// Determinism verification. Re-run the same seed + input log twice; if any step's\n// state hash diverges, some hidden nondeterminism (Math.random, Date.now, Set\n// iteration, unordered map) leaked in. This is the regression net that lets you\n// refactor the sim fearlessly.\n\nimport type { World } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { frameActions } from '../input/actions';\n\nexport type WorldFactory = () => World;\n\n/** Run a world through an input log, returning the final hash and per-frame hashes. */\nexport function replay(makeWorld: WorldFactory, log: InputLog): { finalHash: string; hashes: string[] } {\n const world = makeWorld();\n const hashes: string[] = [];\n for (let i = 0; i < log.frames.length; i++) {\n world.step(frameActions(log, i));\n hashes.push(world.hash());\n }\n return { finalHash: world.hash(), hashes };\n}\n\nexport interface DeterminismReport {\n ok: boolean;\n frames: number;\n /** First frame index where the two runs diverged, or -1. */\n divergedAt: number;\n finalHash: string;\n}\n\n/** Run twice and compare every step's hash. */\nexport function checkDeterministic(makeWorld: WorldFactory, log: InputLog): DeterminismReport {\n const a = replay(makeWorld, log);\n const b = replay(makeWorld, log);\n let divergedAt = -1;\n for (let i = 0; i < a.hashes.length; i++) {\n if (a.hashes[i] !== b.hashes[i]) {\n divergedAt = i;\n break;\n }\n }\n return {\n ok: divergedAt === -1 && a.finalHash === b.finalHash,\n frames: log.frames.length,\n divergedAt,\n finalHash: a.finalHash,\n };\n}\n\n/** Assert determinism (throws with the divergence frame). */\nexport function assertDeterministic(makeWorld: WorldFactory, log: InputLog): DeterminismReport {\n const report = checkDeterministic(makeWorld, log);\n if (!report.ok) {\n throw new Error(\n `hayao: sim is NON-deterministic \u2014 runs diverged at frame ${report.divergedAt} ` +\n `of ${report.frames}. Check for Math.random/Date.now/Set-iteration/unordered-map in the sim.`,\n );\n }\n return report;\n}\n\n/**\n * Assert that restoring a snapshot reproduces the exact same continuation \u2014\n * i.e. save/load is lossless. Runs `warmup` steps, snapshots, runs `tail` more\n * on both the original and a restored copy, and compares final hashes.\n */\nexport function assertSnapshotStable(\n makeWorld: WorldFactory,\n log: InputLog,\n warmup: number,\n): { ok: boolean; hashA: string; hashB: string } {\n const original = makeWorld();\n for (let i = 0; i < warmup; i++) original.step(frameActions(log, i));\n const snap = original.snapshot();\n\n const restored = makeWorld();\n restored.restore(snap);\n\n for (let i = warmup; i < log.frames.length; i++) {\n original.step(frameActions(log, i));\n restored.step(frameActions(log, i));\n }\n const hashA = original.hash();\n const hashB = restored.hash();\n return { ok: hashA === hashB, hashA, hashB };\n}\n", "// Scripted playthroughs: drive a world headlessly with a sequence of held-input\n// segments and collect probe snapshots. This is Channel 1a \u2014 proving behavior on\n// game state, in Node, no browser. (Hold keys \u2265 a few frames: variable-height\n// jumps treat a 1-frame synthetic tap as a real short tap.)\n\nimport type { World } from '../world';\n\nexport interface Segment {\n /** Actions held down for this segment. */\n actions?: string[];\n /** Number of fixed steps to run. */\n frames: number;\n}\n\n/** Build a segment: hold `actions` for `frames` steps. */\nexport function hold(actions: string[], frames: number): Segment {\n return { actions, frames };\n}\n/** Build an idle segment (no input) for `frames` steps. */\nexport function wait(frames: number): Segment {\n return { actions: [], frames };\n}\n\nexport interface PlaythroughResult {\n totalFrames: number;\n finalHash: string;\n /** Probe snapshot after each segment. */\n probes: Record<string, unknown>[];\n}\n\n/** Run a scripted playthrough; returns a probe after each segment. */\nexport function scriptedPlaythrough(world: World, script: Segment[]): PlaythroughResult {\n const probes: Record<string, unknown>[] = [];\n let total = 0;\n for (const seg of script) {\n for (let i = 0; i < seg.frames; i++) world.step(seg.actions ?? []);\n total += seg.frames;\n probes.push(world.probe());\n }\n return { totalFrames: total, finalHash: world.hash(), probes };\n}\n\n/** Convenience: advance a world N frames with a fixed input set. */\nexport function pump(world: World, frames: number, actions: string[] = []): void {\n for (let i = 0; i < frames; i++) world.step(actions);\n}\n", "// Browser capture seam. Because the sim is headless-native \u2014 hayao owns the\n// clock and never touches document.hasFocus \u2014 this is ~30 lines, not the ~100 a\n// canvas engine needs. Exposes window.__hayao for scripted browser sessions and\n// aesthetic screenshots. Enable with ?capture=1.\n\nimport type { World } from '../world';\n\nexport interface CaptureTarget {\n readonly world: World;\n /** Advance one fixed step with the given actions and render. */\n stepOnce(actions?: string[]): void;\n /** Current frame as an SVG string (a vector screenshot). */\n renderSVG(): string;\n setPaused(paused: boolean): void;\n}\n\nexport interface HayaoCapture {\n pump(frames: number, actions?: string[]): Record<string, unknown>;\n probe(): Record<string, unknown>;\n hash(): string;\n shot(): string;\n save(path: string): Promise<boolean>;\n key(type: 'keydown' | 'keyup', code: string): void;\n readonly world: World;\n}\n\nexport function isCaptureMode(): boolean {\n return typeof location !== 'undefined' && new URLSearchParams(location.search).has('capture');\n}\n\n/** Install window.__hayao for scripted browser verification. */\nexport function installCapture(target: CaptureTarget): HayaoCapture {\n const api: HayaoCapture = {\n pump(frames, actions = []) {\n target.setPaused(true);\n for (let i = 0; i < frames; i++) target.stepOnce(actions);\n return target.world.probe();\n },\n probe: () => target.world.probe(),\n hash: () => target.world.hash(),\n shot: () => target.renderSVG(),\n async save(path) {\n const svg = target.renderSVG();\n try {\n const res = await fetch('/__shot', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ path, svg }),\n });\n return res.ok;\n } catch {\n return false;\n }\n },\n key(type, code) {\n document.dispatchEvent(new KeyboardEvent(type, { code, bubbles: true }));\n },\n get world() {\n return target.world;\n },\n };\n (globalThis as unknown as { __hayao: HayaoCapture }).__hayao = api;\n return api;\n}\n", "// Declarative input scripts: the ergonomic way to author headless playthroughs\n// for real-time games, where hand-writing per-frame action arrays is hopeless.\n// A script is a list of segments; each holds actions for N frames, optionally\n// tapping others on its first frame.\n\nimport type { World } from '../world';\n\nexport interface ScriptSegment {\n /** Actions held down for every frame of this segment. */\n hold?: string[];\n /** Actions pressed only on the first frame of this segment (taps). */\n press?: string[];\n /** How many fixed steps this segment lasts (default 1). */\n frames?: number;\n}\n\nexport type InputScript = ScriptSegment[];\n\n/** Expand a script into per-frame action arrays (an InputLog's frames). */\nexport function scriptToFrames(script: InputScript): string[][] {\n const out: string[][] = [];\n for (const seg of script) {\n const n = seg.frames ?? 1;\n const hold = seg.hold ?? [];\n for (let i = 0; i < n; i++) out.push(i === 0 && seg.press ? [...hold, ...seg.press] : [...hold]);\n }\n return out;\n}\n\nexport interface DriveResult {\n frames: number;\n /** True if driving stopped early because `until` matched. */\n matched: boolean;\n}\n\n/**\n * Step a world through a script. Pass `until` to stop as soon as a probe\n * predicate holds (e.g. level solved) \u2014 the tail of the script is slack, so\n * playthrough scripts don't need frame-perfect lengths.\n */\nexport function drive(world: World, script: InputScript, until?: (probe: Record<string, unknown>) => boolean): DriveResult {\n let frames = 0;\n for (const f of scriptToFrames(script)) {\n if (until && until(world.probe())) return { frames, matched: true };\n world.step(f);\n frames++;\n }\n return { frames, matched: until ? until(world.probe()) : false };\n}\n", "// The plan-interpreter bot skeleton \u2014 promoted to the engine after three\n// example games (shard-ascent, sproutveil, gleamvale) each rebuilt the same\n// shape: a plan of semantic steps, executed reactively against the probe each\n// frame, emitting actions. Games supply the step executors (steering is\n// genre-specific); the engine supplies the lifecycle, retries, and telemetry.\n//\n// const bot = createPlanBot(plan, {\n// walk(step, probe, out, ctx) { \u2026steer\u2026; if (arrived) ctx.next(); },\n// });\n// while (!probe.won) world.step(bot(world.probe()));\n\nexport interface BotCtx {\n /** Frames spent in the current step. */\n frames: number;\n /** Free per-step scratch (cleared on step change). */\n mem: Record<string, unknown>;\n /** Advance to the next plan step. */\n next(): void;\n /** Restart the current step (retry) \u2014 clears frames + mem. */\n retry(): void;\n}\n\nexport type StepExec<Step, Probe> = (step: Step, probe: Probe, out: string[], ctx: BotCtx) => void;\n\nexport interface PlanBot<Probe> {\n (probe: Probe): string[];\n stepIndex(): number;\n done(): boolean;\n}\n\nexport function createPlanBot<Step extends { kind: string }, Probe>(plan: Step[], execs: Record<string, StepExec<Step, Probe>>): PlanBot<Probe> {\n let i = 0;\n let frames = 0;\n let mem: Record<string, unknown> = {};\n\n const fn = (probe: Probe): string[] => {\n const out: string[] = [];\n const step = plan[i];\n if (!step) return out;\n frames++;\n const ctx: BotCtx = {\n get frames() {\n return frames;\n },\n mem,\n next() {\n i++;\n frames = 0;\n mem = {};\n },\n retry() {\n frames = 0;\n mem = {};\n },\n };\n const exec = execs[step.kind];\n if (!exec) throw new Error(`plan bot: no executor for step kind \"${step.kind}\"`);\n exec(step, probe, out, ctx);\n return out;\n };\n const bot = fn as PlanBot<Probe>;\n bot.stepIndex = () => i;\n bot.done = () => i >= plan.length;\n return bot;\n}\n\n/** Shared steering helper: 4/8-way movement toward a point. */\nexport function steer2D(px: number, py: number, tx: number, ty: number, out: string[], dead = 8): void {\n if (px < tx - dead) out.push('right');\n else if (px > tx + dead) out.push('left');\n if (py < ty - dead) out.push('down');\n else if (py > ty + dead) out.push('up');\n}\n", "// Layout lints \u2014 verification for the HUMAN-contact layer. The first real\n// playtest of the 20-genre campaign found that every reported defect lived in\n// the one layer the sim proofs cannot see: text buried under sprites, labels\n// kissing shapes, controls nobody explains. But the display list is pure\n// data, so the basics of readability are assertable like everything else.\n//\n// Rules enforced here (see CONVENTIONS \"The human-contact layer\"):\n// 1. TEXT IS SACRED. A shape may fully contain a text's box (it's a panel)\n// or be fully disjoint from it. Partial overlap = collision. Shapes at\n// z \u2264 1 are exempt \u2014 that's the background lattice (tile grids, felt).\n// 2. FIRST CONTACT. Every action in the input map must be mentioned by some\n// on-screen text on the first frame (its key or its name) \u2014 a player who\n// reads the screen must be able to discover the controls.\n\nimport type { DrawCommand, TextCommand } from '../render/commands';\nimport type { InputMap } from '../input/actions';\nimport type { World } from '../world';\n\nexport interface TextBox {\n cmd: TextCommand;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Approximate a text command's on-screen box (serif \u2248 0.56em per char). */\nexport function textBox(cmd: TextCommand): TextBox {\n const w = cmd.text.length * cmd.size * 0.56;\n const h = cmd.size * 1.25;\n const cx = cmd.transform.e + cmd.x;\n const by = cmd.transform.f + cmd.y; // baseline\n const left = cmd.align === 'center' ? cx - w / 2 : cmd.align === 'right' ? cx - w : cx;\n return { cmd, x: left, y: by - cmd.size, w, h };\n}\n\n/** Conservative bounds of a non-text command (local shape + translation). */\nexport function shapeBox(cmd: DrawCommand): { x: number; y: number; w: number; h: number } | null {\n const ex = cmd.transform.e;\n const ey = cmd.transform.f;\n switch (cmd.kind) {\n case 'rect':\n return { x: ex + cmd.x, y: ey + cmd.y, w: cmd.w, h: cmd.h };\n case 'circle':\n return { x: ex + cmd.cx - cmd.radius, y: ey + cmd.cy - cmd.radius, w: cmd.radius * 2, h: cmd.radius * 2 };\n case 'poly': {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (let i = 0; i < cmd.points.length; i += 2) {\n minX = Math.min(minX, cmd.points[i]);\n maxX = Math.max(maxX, cmd.points[i]);\n minY = Math.min(minY, cmd.points[i + 1]);\n maxY = Math.max(maxY, cmd.points[i + 1]);\n }\n return { x: ex + minX, y: ey + minY, w: maxX - minX, h: maxY - minY };\n }\n default:\n return null; // paths are decorative fans/arcs \u2014 skip (conservative)\n }\n}\n\nconst overlaps = (a: { x: number; y: number; w: number; h: number }, b: { x: number; y: number; w: number; h: number }): boolean =>\n a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n\nconst contains = (outer: { x: number; y: number; w: number; h: number }, inner: { x: number; y: number; w: number; h: number }, pad = 2): boolean =>\n outer.x - pad <= inner.x && outer.y - pad <= inner.y && outer.x + outer.w + pad >= inner.x + inner.w && outer.y + outer.h + pad >= inner.y + inner.h;\n\nexport interface LayoutOptions {\n /** Shapes at or below this z are background lattice (tiles/felt) and may sit under text. */\n backgroundZ?: number;\n /** Extra pixels of breathing room demanded around text (default 0 = touch is allowed, overlap is not). */\n margin?: number;\n}\n\n/**\n * Lint a display list for text readability. Returns human-readable issues\n * (empty = clean). Checks: text-vs-shape partial overlaps (rule 1) and\n * text-vs-text overlaps.\n */\nexport function layoutIssues(commands: DrawCommand[], opts: LayoutOptions = {}): string[] {\n const backgroundZ = opts.backgroundZ ?? 1;\n const margin = opts.margin ?? 0;\n const issues: string[] = [];\n const texts: TextBox[] = [];\n for (const c of commands) if (c.kind === 'text' && (c as TextCommand).text.trim().length) texts.push(textBox(c as TextCommand));\n\n for (const t of texts) {\n const r = { x: t.x - margin, y: t.y - margin, w: t.w + margin * 2, h: t.h + margin * 2 };\n // A backing panel (any shape that fully contains the text, below it in\n // paint order) occludes whatever sits underneath IT \u2014 collisions with\n // shapes the panel covers are forgiven. This is how HUD scrims work.\n let panelZ = -Infinity;\n for (const c of commands) {\n if (c.kind === 'text') continue;\n const b = shapeBox(c);\n if (b && contains(b, t) && (c.opacity === undefined || c.opacity >= 0.6)) panelZ = Math.max(panelZ, c.z ?? 0);\n }\n for (const c of commands) {\n if (c.kind === 'text') continue;\n if ((c.z ?? 0) <= backgroundZ) continue; // background lattice\n if ((c.z ?? 0) <= panelZ) continue; // hidden behind the text's panel\n if (c.opacity !== undefined && c.opacity < 0.25) continue; // ghosts\n const b = shapeBox(c);\n if (!b) continue;\n if (overlaps(r, b) && !contains(b, t)) {\n issues.push(`text \"${clip(t.cmd.text)}\" collides with a ${c.kind} (z${c.z}) at ~(${Math.round(b.x)},${Math.round(b.y)}) \u2014 back it with a panel, or stay clear`);\n }\n }\n }\n for (let i = 0; i < texts.length; i++)\n for (let j = i + 1; j < texts.length; j++)\n if (overlaps(texts[i], texts[j])) issues.push(`texts \"${clip(texts[i].cmd.text)}\" and \"${clip(texts[j].cmd.text)}\" overlap`);\n return dedupe(issues);\n}\n\nconst clip = (s: string): string => (s.length > 28 ? s.slice(0, 25) + '\u2026' : s);\nconst dedupe = (a: string[]): string[] => [...new Set(a)];\n\n/** Friendly names a hint text may use to reference a key code. */\nexport function keyMentions(code: string): string[] {\n if (code.startsWith('Digit')) return [code.slice(5)];\n if (code.startsWith('Key')) return [code.slice(3).toLowerCase()];\n if (code.startsWith('Arrow')) return ['arrow', '\u2190', '\u2192', '\u2191', '\u2193', code.slice(5).toLowerCase()];\n if (code.startsWith('Shift')) return ['shift'];\n if (code === 'Space') return ['space'];\n if (code === 'Enter') return ['enter'];\n if (code === 'Period') return ['.'];\n return [code.toLowerCase()];\n}\n\n/**\n * First-contact check: which actions does no on-screen text explain? An\n * action passes if any text mentions its name or one of its keys' friendly\n * names. 'restart' is exempt (universal convention).\n */\nexport function missingControlHints(world: World, inputMap: InputMap): string[] {\n const textBlob = world\n .render()\n .filter((c): c is TextCommand => c.kind === 'text')\n .map((c) => c.text.toLowerCase())\n .join(' \u00B7 ');\n const missing: string[] = [];\n const mentions = (n: string): boolean => {\n if (!n.length) return false;\n // Short tokens (single letters, digits) must appear as standalone words,\n // or \"f\" would be satisfied by the word \"fire\" losing the actual key.\n if (n.length <= 2 && /^[a-z0-9.]+$/.test(n)) return new RegExp(`(^|[^a-z0-9])${n.replace('.', '\\\\.')}($|[^a-z0-9])`).test(textBlob);\n return textBlob.includes(n);\n };\n for (const [action, keys] of Object.entries(inputMap)) {\n if (action === 'restart') continue;\n const names = [action.toLowerCase().replace(/-\\d+$/, ''), ...keys.flatMap(keyMentions)];\n if (!names.some(mentions)) missing.push(action);\n }\n return dedupe(missing);\n}\n", "// Feel probes (Channel 3): quality proxies computed from a per-frame probe\n// timeline. The harness cannot feel fun, but it can measure fun's precursors \u2014\n// time-to-first-meaningful-action, event cadence, difficulty ramp, input\n// decision density \u2014 and fail when a game drifts outside its tuned windows.\n// These are proxies, not proof: pair them with the filmstrip and a human-set\n// window per game (see docs/VERIFICATION.md \u00A7Channel 3).\n\nimport type { World } from '../world';\n\nexport type ProbeFrame = Record<string, unknown>;\n\n/**\n * Step a world through per-frame action arrays, probing after every step.\n * Returns frames.length + 1 probes: index 0 is the pre-step state, index i is\n * the state after frame i. (With the default 60Hz clock, index / 60 = sim\n * seconds.) For a segment-level timeline use scriptedPlaythrough instead.\n */\nexport function recordTimeline(world: World, frames: string[][]): ProbeFrame[] {\n const out: ProbeFrame[] = [world.probe()];\n for (const f of frames) {\n world.step(f);\n out.push(world.probe());\n }\n return out;\n}\n\n/** First timeline index where `pred` holds, or -1 if it never does. */\nexport function firstFrame(timeline: ProbeFrame[], pred: (p: ProbeFrame) => boolean): number {\n for (let i = 0; i < timeline.length; i++) if (pred(timeline[i])) return i;\n return -1;\n}\n\n/** The value of one probe key across the timeline. */\nexport function series(timeline: ProbeFrame[], key: string): unknown[] {\n return timeline.map((p) => p[key]);\n}\n\n/** Timeline indices where `key`'s value differs from the previous frame \u2014 an event cadence. */\nexport function changeFrames(timeline: ProbeFrame[], key: string): number[] {\n const out: number[] = [];\n for (let i = 1; i < timeline.length; i++) if (timeline[i][key] !== timeline[i - 1][key]) out.push(i);\n return out;\n}\n\n/** Monotonic within slack: 'up' means every value \u2265 previous \u2212 slack. */\nexport function isMonotonic(values: number[], dir: 'up' | 'down', slack = 0): boolean {\n for (let i = 1; i < values.length; i++) {\n if (dir === 'up' ? values[i] < values[i - 1] - slack : values[i] > values[i - 1] + slack) return false;\n }\n return true;\n}\n\n/**\n * Fraction of frames carrying at least one action \u2014 a crude engagement proxy.\n * Near 0 the player is waiting; near 1 they are mashing; a tuned game usually\n * lives somewhere in between (set the window per genre).\n */\nexport function inputDensity(frames: string[][]): number {\n if (frames.length === 0) return 0;\n return frames.filter((f) => f.length > 0).length / frames.length;\n}\n\n/** Largest gap (in frames) between consecutive events \u2014 dead-air detector. */\nexport function longestLull(eventFrames: number[], totalFrames: number): number {\n const pts = [0, ...eventFrames, totalFrames];\n let worst = 0;\n for (let i = 1; i < pts.length; i++) worst = Math.max(worst, pts[i] - pts[i - 1]);\n return worst;\n}\n", "// Filmstrip: sampled frames of a run composed into ONE SVG contact sheet, so\n// the \"judge looks from a headless screenshot\" step can see MOTION \u2014 pacing,\n// readability during play, layering under load \u2014 not a single posed frame.\n// Looks only, never correctness: state was already proven numerically.\n\nimport type { World } from '../world';\nimport { commandsToSVGInner } from '../render/svgString';\n\nexport interface FilmstripOptions {\n /** The game's view size (defineGame width/height). */\n width: number;\n height: number;\n background?: string;\n /** How many panels to sample across the run (default 12, min 2). */\n panels?: number;\n /** Panels per row (default 4). */\n cols?: number;\n /** Rendered width of one panel in px (default 320). */\n panelWidth?: number;\n}\n\n/**\n * Step `world` through per-frame actions, sampling evenly spaced panels\n * (always including the first and last frame), and return one standalone SVG.\n * Panel labels are frame numbers plus sim seconds at the 60Hz convention.\n */\nexport function renderFilmstrip(world: World, frames: string[][], opts: FilmstripOptions): string {\n const panels = Math.max(2, opts.panels ?? 12);\n const every = Math.max(1, Math.ceil(frames.length / (panels - 1)));\n const shots: { frame: number; inner: string }[] = [{ frame: 0, inner: commandsToSVGInner(world.render()) }];\n for (let i = 0; i < frames.length; i++) {\n world.step(frames[i]);\n if ((i + 1) % every === 0 || i === frames.length - 1) {\n shots.push({ frame: i + 1, inner: commandsToSVGInner(world.render()) });\n }\n }\n\n const cols = Math.max(1, opts.cols ?? 4);\n const pw = opts.panelWidth ?? 320;\n const ph = Math.round((pw * opts.height) / opts.width);\n const labelH = 18;\n const gap = 8;\n const cellW = pw + gap;\n const cellH = ph + labelH + gap;\n const rows = Math.ceil(shots.length / cols);\n const totalW = cols * cellW + gap;\n const totalH = rows * cellH + gap;\n const bg = opts.background ?? '#ffffff';\n\n const cells = shots\n .map((s, i) => {\n const x = gap + (i % cols) * cellW;\n const y = gap + Math.floor(i / cols) * cellH;\n return (\n `<g transform=\"translate(${x} ${y})\">` +\n `<svg width=\"${pw}\" height=\"${ph}\" viewBox=\"0 0 ${opts.width} ${opts.height}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${opts.width}\" height=\"${opts.height}\" fill=\"${bg}\"/>` +\n s.inner +\n `</svg>` +\n `<rect x=\"0\" y=\"0\" width=\"${pw}\" height=\"${ph}\" fill=\"none\" stroke=\"#999\" stroke-width=\"1\"/>` +\n `<text x=\"${pw / 2}\" y=\"${ph + 13}\" font-size=\"11\" font-family=\"monospace\" text-anchor=\"middle\" fill=\"#555\">` +\n `f ${s.frame} \u00B7 ${(s.frame / 60).toFixed(1)}s</text>` +\n `</g>`\n );\n })\n .join('');\n\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${totalW} ${totalH}\" width=\"${totalW}\" height=\"${totalH}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${totalW}\" height=\"${totalH}\" fill=\"#f4f4f2\"/>` +\n cells +\n `</svg>`\n );\n}\n", "// Finite state machines for AI, screens, and move-animation. Two flavours:\n//\n// \u2022 `Fsm` \u2014 classic onEnter/onUpdate/onLeave states + an ORDERED transition\n// table (first matching guard wins). For enemy brains, UI phases, anything\n// driven by conditions.\n// \u2022 `PhaseClock` \u2014 the pure-logic\u2194`cosmetic` bridge. A timed phase with an\n// eased 0\u21921 progress value and a `next`-phase map (super-castle-game's\n// `IState` + `NextPhaseMap`, generalised): logical moves advance in discrete\n// phases while `progress()` feeds smooth interpolation to the view.\n//\n// Both are DETERMINISTIC: time arrives as a fixed `dt` (from the `Clock`, never\n// wall-clock), transitions are evaluated in array order, and the whole state is\n// a single serializable key + timer so it round-trips through `world.state`.\n\n/** Per-state lifecycle hooks. All optional; all pure over the shared context. */\nexport interface StateHandlers<C> {\n /** Ran once when the machine enters this state. */\n onEnter?(ctx: C): void;\n /** Ran every `update(dt)` while in this state. */\n onUpdate?(ctx: C, dt: number): void;\n /** Ran once when the machine leaves this state. */\n onLeave?(ctx: C): void;\n}\n\n/**\n * A guarded edge. `from` is a source state or `'*'` (any). Edges are evaluated\n * in table order every tick; the first whose `when` returns true fires. Keep\n * the table ordered \u2014 order IS the tie-break, so the machine stays hash-stable.\n */\nexport interface Transition<S extends string, C> {\n from: S | '*';\n to: S;\n when(ctx: C): boolean;\n}\n\nexport class Fsm<S extends string, C> {\n /** The active state key \u2014 this is the whole serializable state. */\n current: S;\n\n constructor(\n private readonly states: Record<S, StateHandlers<C>>,\n private readonly transitions: readonly Transition<S, C>[],\n initial: S,\n private readonly ctx: C,\n ) {\n this.current = initial;\n this.states[initial]?.onEnter?.(ctx);\n }\n\n /**\n * Advance one fixed step: fire the first satisfied transition (if any), then\n * run the current state's `onUpdate`. A transition runs its target's\n * `onUpdate` this same tick, so entering and acting aren't a frame apart.\n */\n update(dt: number): void {\n for (const t of this.transitions) {\n if ((t.from === '*' || t.from === this.current) && t.when(this.ctx)) {\n this.go(t.to);\n break;\n }\n }\n this.states[this.current]?.onUpdate?.(this.ctx, dt);\n }\n\n /** Force a transition (fires onLeave/onEnter). No-op if already there. */\n go(to: S): void {\n if (to === this.current) return;\n this.states[this.current]?.onLeave?.(this.ctx);\n this.current = to;\n this.states[to]?.onEnter?.(this.ctx);\n }\n\n /** True when in one of the given states. */\n is(...states: S[]): boolean {\n return states.includes(this.current);\n }\n\n /** Serialize (games persist this in `world.state`; the handlers are code). */\n getState(): S {\n return this.current;\n }\n /** Restore without firing enter/leave (it's a resume, not a transition). */\n setState(state: S): void {\n this.current = state;\n }\n}\n\n/** Eased progress curve `[0,1] \u2192 [0,1]`. Identity by default. */\nexport type Ease = (t: number) => number;\n\n/** A timed phase: how long it lasts and (optionally) what follows it. */\nexport interface PhaseDef {\n /** Duration in seconds (same units as the `dt` you feed `update`). */\n duration: number;\n /** Successor phase when this one elapses. Omit for a terminal phase. */\n next?: string;\n}\n\n/**\n * A phase with a countdown and an eased progress readout. Drives discrete\n * logical steps (each phase = one settled move) while exposing `progress()` for\n * the view to interpolate between the old and new position \u2014 so animation\n * timing rides on the same deterministic clock as the logic.\n */\nexport class PhaseClock {\n /** Current phase key \u2014 serializable with `elapsed`. */\n phase: string;\n /** Seconds spent in the current phase so far. */\n elapsed = 0;\n\n constructor(\n private readonly defs: Record<string, PhaseDef>,\n initial: string,\n ) {\n if (!defs[initial]) throw new Error(`hayao: PhaseClock has no phase '${initial}'`);\n this.phase = initial;\n }\n\n private get duration(): number {\n return this.defs[this.phase]?.duration ?? 0;\n }\n\n /** Eased fraction 0\u21921 through the current phase (clamped). For cosmetic interp. */\n progress(ease: Ease = (t) => t): number {\n const d = this.duration;\n const raw = d > 0 ? this.elapsed / d : 1;\n return ease(raw < 0 ? 0 : raw > 1 ? 1 : raw);\n }\n\n /** True once the current phase's duration has fully elapsed. */\n get done(): boolean {\n return this.elapsed >= this.duration;\n }\n\n /**\n * Advance by `dt`. When a phase completes and has a `next`, roll into it\n * (carrying any overshoot so long phases don't drift). Returns true on the\n * tick a new phase begins \u2014 the game's cue to commit the next logical step.\n */\n update(dt: number): boolean {\n this.elapsed += dt;\n let advanced = false;\n // Loop in case a very small duration is stepped over in one big dt.\n let guard = 0;\n while (this.elapsed >= this.duration && this.defs[this.phase]?.next !== undefined && guard++ < 1024) {\n const overshoot = this.elapsed - this.duration;\n this.phase = this.defs[this.phase].next as string;\n this.elapsed = overshoot;\n advanced = true;\n }\n return advanced;\n }\n\n /** Jump to a phase and reset its timer (fresh `onEnter`-style restart). */\n to(phase: string): void {\n if (!this.defs[phase]) throw new Error(`hayao: PhaseClock has no phase '${phase}'`);\n this.phase = phase;\n this.elapsed = 0;\n }\n\n getState(): { phase: string; elapsed: number } {\n return { phase: this.phase, elapsed: this.elapsed };\n }\n setState(state: { phase: string; elapsed: number }): void {\n this.phase = state.phase;\n this.elapsed = state.elapsed;\n }\n}\n", "// Weighted random picking + loot/spawn tables. Built strictly ON `world.rng`\n// (an `Rng`) \u2014 never `Math.random`. A single float draw per pick, scanned over\n// cumulative weights in array order, so results are deterministic and\n// reproducible from the RNG state alone. (js13k games fake this with\n// filter+shuffle or reach for `Math.random`; this is the honest primitive.)\n\nimport type { Rng } from '../core/rng';\n\n/** One weighted option: a value and its relative weight (\u2265 0). */\nexport interface WeightedEntry<T> {\n value: T;\n weight: number;\n}\n\n/** Sum a weight list, clamping negatives to 0 (a negative weight is a bug, not a subtraction). */\nfunction totalWeight(weights: readonly number[]): number {\n let sum = 0;\n for (const w of weights) sum += w > 0 ? w : 0;\n return sum;\n}\n\n/**\n * Pick an index in [0, weights.length) with probability \u221D weights[i]. Draws\n * exactly one `rng.float()` and walks the weights in order, so the choice is a\n * pure function of the RNG state. Throws if no weight is positive.\n */\nexport function weightedIndex(rng: Rng, weights: readonly number[]): number {\n const total = totalWeight(weights);\n if (total <= 0) throw new Error('hayao: weightedIndex needs at least one positive weight');\n let r = rng.float() * total;\n for (let i = 0; i < weights.length; i++) {\n const w = weights[i] > 0 ? weights[i] : 0;\n if (r < w) return i;\n r -= w;\n }\n // Float rounding can leave r \u2265 every remaining bucket; hand it the last positive one.\n for (let i = weights.length - 1; i >= 0; i--) if (weights[i] > 0) return i;\n return weights.length - 1;\n}\n\n/** Pick `items[i]` with probability \u221D `weights[i]` (parallel arrays). */\nexport function weightedPick<T>(rng: Rng, items: readonly T[], weights: readonly number[]): T {\n if (items.length !== weights.length) throw new Error('hayao: weightedPick items/weights length mismatch');\n return items[weightedIndex(rng, weights)];\n}\n\n/** Pick the value of one weighted entry. */\nexport function pickEntry<T>(rng: Rng, entries: readonly WeightedEntry<T>[]): T {\n return entries[weightedIndex(rng, entries.map((e) => e.weight))].value;\n}\n\n/**\n * A reusable loot/spawn table. Precomputes cumulative weights once so repeated\n * rolls are cheap; every draw still comes from the passed `Rng`, keeping the\n * table itself stateless and the randomness owned by `world.rng`.\n */\nexport class LootTable<T> {\n private readonly values: readonly T[];\n /** Cumulative (prefix-sum) weights; last element is the total. */\n private readonly cumulative: readonly number[];\n readonly total: number;\n\n constructor(entries: readonly WeightedEntry<T>[]) {\n if (entries.length === 0) throw new Error('hayao: LootTable needs at least one entry');\n const values: T[] = [];\n const cumulative: number[] = [];\n let sum = 0;\n for (const e of entries) {\n sum += e.weight > 0 ? e.weight : 0;\n values.push(e.value);\n cumulative.push(sum);\n }\n if (sum <= 0) throw new Error('hayao: LootTable needs at least one positive weight');\n this.values = values;\n this.cumulative = cumulative;\n this.total = sum;\n }\n\n /** One draw with replacement. */\n roll(rng: Rng): T {\n const r = rng.float() * this.total;\n // Linear scan (tables are small); ordered \u2192 deterministic.\n for (let i = 0; i < this.cumulative.length; i++) if (r < this.cumulative[i]) return this.values[i];\n return this.values[this.values.length - 1];\n }\n\n /** `n` independent draws with replacement, in order. */\n rollMany(rng: Rng, n: number): T[] {\n const out: T[] = [];\n for (let i = 0; i < n; i++) out.push(this.roll(rng));\n return out;\n }\n}\n", "// Graph search: BFS, flood-fill, connected-components, and grid A*/Dijkstra.\n// Pairs with `physics/tilemap.ts` (enemy nav, region/cluster detection, unit\n// routing) but works over any adjacency function too.\n//\n// DETERMINISM: neighbours are visited in a fixed order, the frontier is an\n// array (BFS) or a binary heap tie-broken by a monotonic insertion counter\n// (A*/Dijkstra), and grids are scanned row-major. `cameFrom`/`cost` maps are\n// only ever read by key \u2014 never iterated to drive logic \u2014 so no Set/Map\n// ordering hazard reaches `world.hash()`. No RNG, no wall-clock; fully pure.\n\nimport { TILE, tileAt, type TilemapData } from '../physics/tilemap';\n\n// \u2500\u2500 generic graph search over an adjacency function \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Neighbours of a node, in deterministic order. */\nexport type Neighbours<N> = (node: N) => N[];\n/** Stable string identity for a node (visited-set + path keys). */\nexport type NodeKey<N> = (node: N) => string;\n\nexport interface BfsResult<N> {\n /** Nodes in expansion order (breadth-first). */\n order: N[];\n /** key \u2192 the node it was first reached from (for path reconstruction). */\n cameFrom: Map<string, N>;\n /** key \u2192 steps from the start (start = 0). */\n dist: Map<string, number>;\n}\n\n/**\n * Breadth-first search from `start`. Explores the whole reachable component\n * unless `goal` short-circuits it. `maxNodes` caps work on huge/open graphs.\n */\nexport function bfs<N>(\n start: N,\n neighbours: Neighbours<N>,\n key: NodeKey<N>,\n opts: { goal?: (n: N) => boolean; maxNodes?: number } = {},\n): BfsResult<N> {\n const maxNodes = opts.maxNodes ?? 1_000_000;\n const order: N[] = [];\n const cameFrom = new Map<string, N>();\n const dist = new Map<string, number>();\n const startKey = key(start);\n dist.set(startKey, 0);\n let frontier: N[] = [start];\n order.push(start);\n if (opts.goal?.(start)) return { order, cameFrom, dist };\n\n let expanded = 0;\n while (frontier.length > 0 && expanded < maxNodes) {\n const next: N[] = [];\n for (const node of frontier) {\n const d = dist.get(key(node)) ?? 0;\n for (const nb of neighbours(node)) {\n const k = key(nb);\n if (dist.has(k)) continue;\n dist.set(k, d + 1);\n cameFrom.set(k, node);\n order.push(nb);\n expanded++;\n if (opts.goal?.(nb)) return { order, cameFrom, dist };\n next.push(nb);\n }\n }\n frontier = next;\n }\n return { order, cameFrom, dist };\n}\n\n/** Reconstruct the path start\u2192goal from a `cameFrom` map, or [] if unreachable. */\nexport function reconstructPath<N>(cameFrom: Map<string, N>, key: NodeKey<N>, start: N, goal: N): N[] {\n const path: N[] = [goal];\n let cur = goal;\n const startKey = key(start);\n while (key(cur) !== startKey) {\n const prev = cameFrom.get(key(cur));\n if (prev === undefined) return []; // goal not connected to start\n cur = prev;\n path.push(cur);\n }\n path.reverse();\n return path;\n}\n\n// \u2500\u2500 weighted search: Dijkstra / A* over an adjacency function \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A neighbour with the step cost to reach it (must be \u2265 0). */\nexport interface WeightedEdge<N> {\n node: N;\n cost: number;\n}\nexport type WeightedNeighbours<N> = (node: N) => WeightedEdge<N>[];\n\n/**\n * A* (Dijkstra when `heuristic` is omitted/zero) over a weighted adjacency\n * function. Returns the least-cost path start\u2192goal (inclusive) or null.\n * Tie-broken by insertion order via a monotonic counter \u2192 identical path on\n * every engine.\n */\nexport function astar<N>(\n start: N,\n isGoal: (n: N) => boolean,\n neighbours: WeightedNeighbours<N>,\n key: NodeKey<N>,\n opts: { heuristic?: (n: N) => number; maxNodes?: number } = {},\n): { path: N[]; cost: number } | null {\n const h = opts.heuristic ?? (() => 0);\n const maxNodes = opts.maxNodes ?? 1_000_000;\n const cameFrom = new Map<string, N>();\n const gScore = new Map<string, number>();\n const heap = new MinHeap<N>();\n const startKey = key(start);\n gScore.set(startKey, 0);\n heap.push(start, h(start));\n\n let expanded = 0;\n while (heap.size > 0 && expanded < maxNodes) {\n const { item: cur, priority: f } = heap.pop();\n const ck = key(cur);\n const g = gScore.get(ck) ?? Infinity;\n // Stale heap entry (a cheaper path superseded it): f encodes g+h at push time.\n if (f > g + h(cur) + 1e-9) continue;\n if (isGoal(cur)) return { path: rebuild(cameFrom, key, cur), cost: g };\n expanded++;\n for (const edge of neighbours(cur)) {\n const nk = key(edge.node);\n const tentative = g + edge.cost;\n if (tentative < (gScore.get(nk) ?? Infinity)) {\n gScore.set(nk, tentative);\n cameFrom.set(nk, cur);\n heap.push(edge.node, tentative + h(edge.node));\n }\n }\n }\n return null;\n}\n\nfunction rebuild<N>(cameFrom: Map<string, N>, key: NodeKey<N>, goal: N): N[] {\n const path: N[] = [goal];\n let cur = goal;\n let prev = cameFrom.get(key(cur));\n while (prev !== undefined) {\n cur = prev;\n path.push(cur);\n prev = cameFrom.get(key(cur));\n }\n path.reverse();\n return path;\n}\n\n/**\n * Binary min-heap keyed on a numeric priority, tie-broken by insertion sequence\n * so equal-priority items pop in push order \u2014 the source of A*'s determinism.\n */\nclass MinHeap<T> {\n private items: T[] = [];\n private prio: number[] = [];\n private seq: number[] = [];\n private counter = 0;\n\n get size(): number {\n return this.items.length;\n }\n\n push(item: T, priority: number): void {\n this.items.push(item);\n this.prio.push(priority);\n this.seq.push(this.counter++);\n this.bubbleUp(this.items.length - 1);\n }\n\n pop(): { item: T; priority: number } {\n const item = this.items[0];\n const priority = this.prio[0];\n const last = this.items.length - 1;\n this.swap(0, last);\n this.items.pop();\n this.prio.pop();\n this.seq.pop();\n if (this.items.length > 0) this.bubbleDown(0);\n return { item, priority };\n }\n\n /** true if a is strictly higher priority (lower value, then earlier seq). */\n private less(a: number, b: number): boolean {\n return this.prio[a] < this.prio[b] || (this.prio[a] === this.prio[b] && this.seq[a] < this.seq[b]);\n }\n\n private bubbleUp(i: number): void {\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (!this.less(i, parent)) break;\n this.swap(i, parent);\n i = parent;\n }\n }\n\n private bubbleDown(i: number): void {\n const n = this.items.length;\n for (;;) {\n const l = 2 * i + 1;\n const r = 2 * i + 2;\n let smallest = i;\n if (l < n && this.less(l, smallest)) smallest = l;\n if (r < n && this.less(r, smallest)) smallest = r;\n if (smallest === i) break;\n this.swap(i, smallest);\n i = smallest;\n }\n }\n\n private swap(a: number, b: number): void {\n [this.items[a], this.items[b]] = [this.items[b], this.items[a]];\n [this.prio[a], this.prio[b]] = [this.prio[b], this.prio[a]];\n [this.seq[a], this.seq[b]] = [this.seq[b], this.seq[a]];\n }\n}\n\n// \u2500\u2500 grid conveniences (row-major, tilemap-friendly) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface Cell {\n x: number;\n y: number;\n}\n\n/** 4-neighbour offsets (N, E, S, W), in a fixed order. */\nexport const NEIGHBORS_4: readonly Cell[] = [\n { x: 0, y: -1 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n];\n/** 8-neighbour offsets (orthogonals then diagonals), in a fixed order. */\nexport const NEIGHBORS_8: readonly Cell[] = [\n ...NEIGHBORS_4,\n { x: 1, y: -1 },\n { x: 1, y: 1 },\n { x: -1, y: 1 },\n { x: -1, y: -1 },\n];\n\n/** Is a cell walkable? Called for in-bounds cells only. */\nexport type Passable = (x: number, y: number) => boolean;\n\nconst cellKey = (c: Cell): string => `${c.x},${c.y}`;\n\nfunction gridNeighbours(passable: Passable, cols: number, rows: number, diagonal: boolean): Neighbours<Cell> {\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n return (c: Cell) => {\n const out: Cell[] = [];\n for (const o of offsets) {\n const x = c.x + o.x;\n const y = c.y + o.y;\n if (x < 0 || y < 0 || x >= cols || y >= rows) continue;\n if (!passable(x, y)) continue;\n out.push({ x, y });\n }\n return out;\n };\n}\n\n/**\n * Flood-fill from a seed cell over `passable`, returning every reachable cell\n * in breadth-first (deterministic) order. The classic bucket-fill / region-grab.\n */\nexport function floodFill(\n start: Cell,\n passable: Passable,\n opts: { cols: number; rows: number; diagonal?: boolean },\n): Cell[] {\n if (!passable(start.x, start.y)) return [];\n const nb = gridNeighbours(passable, opts.cols, opts.rows, opts.diagonal ?? false);\n return bfs(start, nb, cellKey).order;\n}\n\nexport interface Components {\n /** Row-major label per cell: -1 for impassable, else a component id \u2265 0. */\n labels: number[];\n /** Cells of each component, indexed by id, each in row-major order. */\n cells: Cell[][];\n}\n\n/**\n * Label connected regions of passable cells. Scans row-major and flood-fills\n * each unlabeled passable cell, so component ids are assigned deterministically\n * (top-left region first). Region/cluster detection for match-3, territory, etc.\n */\nexport function connectedComponents(cols: number, rows: number, passable: Passable, diagonal = false): Components {\n const labels = new Array<number>(cols * rows).fill(-1);\n const cells: Cell[][] = [];\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (labels[y * cols + x] !== -1 || !passable(x, y)) continue;\n const id = cells.length;\n const region: Cell[] = [];\n // Iterative BFS with an in-place label as the visited marker.\n let frontier: Cell[] = [{ x, y }];\n labels[y * cols + x] = id;\n while (frontier.length > 0) {\n const next: Cell[] = [];\n for (const c of frontier) {\n region.push(c);\n for (const o of offsets) {\n const nx = c.x + o.x;\n const ny = c.y + o.y;\n if (nx < 0 || ny < 0 || nx >= cols || ny >= rows) continue;\n const idx = ny * cols + nx;\n if (labels[idx] !== -1 || !passable(nx, ny)) continue;\n labels[idx] = id;\n next.push({ x: nx, y: ny });\n }\n }\n frontier = next;\n }\n cells.push(region);\n }\n }\n return { labels, cells };\n}\n\n/**\n * Grid A* / Dijkstra. Returns the least-cost cell path start\u2192goal (inclusive)\n * or null if unreachable. Default step cost is 1 (orthogonal) / \u221A2 (diagonal);\n * pass `cost(x,y)` to weight terrain. Heuristic defaults to Manhattan (4-dir)\n * or octile (8-dir) \u2014 admissible, integer-stable, so paths reproduce exactly.\n */\nexport function astarGrid(\n start: Cell,\n goal: Cell,\n passable: Passable,\n opts: { cols: number; rows: number; diagonal?: boolean; cost?: (x: number, y: number) => number; maxNodes?: number },\n): Cell[] | null {\n const diagonal = opts.diagonal ?? false;\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n const stepCost = opts.cost ?? (() => 1);\n const SQRT2 = 1.4142135623730951;\n\n const neighbours: WeightedNeighbours<Cell> = (c) => {\n const out: WeightedEdge<Cell>[] = [];\n for (const o of offsets) {\n const x = c.x + o.x;\n const y = c.y + o.y;\n if (x < 0 || y < 0 || x >= opts.cols || y >= opts.rows) continue;\n if (!passable(x, y)) continue;\n const diag = o.x !== 0 && o.y !== 0;\n out.push({ node: { x, y }, cost: stepCost(x, y) * (diag ? SQRT2 : 1) });\n }\n return out;\n };\n\n const heuristic = (c: Cell): number => {\n const dx = Math.abs(c.x - goal.x);\n const dy = Math.abs(c.y - goal.y);\n if (!diagonal) return dx + dy; // Manhattan\n const lo = Math.min(dx, dy);\n return dx + dy - (2 - SQRT2) * lo; // octile\n };\n\n if (!passable(goal.x, goal.y)) return null;\n const result = astar(start, (c) => c.x === goal.x && c.y === goal.y, neighbours, cellKey, {\n heuristic,\n maxNodes: opts.maxNodes,\n });\n return result ? result.path : null;\n}\n\n/** Build a `Passable` from a tilemap: everything but SOLID/out-of-bounds walks. */\nexport function passableFromTilemap(map: TilemapData): Passable {\n return (x, y) => tileAt(map, x, y) !== TILE.SOLID;\n}\n", "// Undo / record-replay buffers over pure state. Nearly free given Hayao's\n// pure-logic + snapshot model, but worth packaging cleanly:\n// \u2022 UndoStack \u2014 a bounded memento (state-clone) stack with redo, for puzzle\n// undo over an immutable-ish State (dying-dreams clones its\n// PuzzleState; this is that, with a cursor and a size cap).\n// \u2022 RingBuffer \u2014 a bounded FIFO for ghost/echo trails (soul-jumper's 8-frame\n// pose history) \u2014 overwrites oldest, O(1) push.\n// Both are pure and deterministic; store their contents as plain data so they\n// ride along in `world.state` without escaping the hash.\n\n/** Deep clone used by default. structuredClone is available in Node \u226517 & browsers. */\nfunction deepClone<S>(s: S): S {\n return structuredClone(s);\n}\n\n/**\n * A memento stack for undo/redo over snapshots of pure state. Call `record()`\n * after every committed move; `undo()`/`redo()` walk the cursor. States are\n * cloned in and out so callers can freely mutate what they get back. Capacity is\n * bounded \u2014 the oldest entry is dropped once `limit` is exceeded (undo has a\n * horizon, memory doesn't grow without bound).\n */\nexport class UndoStack<S> {\n private history: S[] = [];\n private cursor = -1;\n private readonly limit: number;\n private readonly clone: (s: S) => S;\n\n constructor(opts: { limit?: number; clone?: (s: S) => S } = {}) {\n this.limit = Math.max(1, opts.limit ?? 64);\n this.clone = opts.clone ?? deepClone;\n }\n\n /** Push a new state as the present, discarding any redo branch ahead of it. */\n record(state: S): void {\n // Drop the redo tail, then append.\n this.history.length = this.cursor + 1;\n this.history.push(this.clone(state));\n this.cursor = this.history.length - 1;\n // Enforce the horizon from the front.\n if (this.history.length > this.limit) {\n const overflow = this.history.length - this.limit;\n this.history.splice(0, overflow);\n this.cursor -= overflow;\n }\n }\n\n /** Step back one state and return a clone of it (undefined if nothing to undo). */\n undo(): S | undefined {\n if (this.cursor <= 0) return undefined;\n this.cursor--;\n return this.clone(this.history[this.cursor]);\n }\n\n /** Step forward one state and return a clone of it (undefined if nothing to redo). */\n redo(): S | undefined {\n if (this.cursor >= this.history.length - 1) return undefined;\n this.cursor++;\n return this.clone(this.history[this.cursor]);\n }\n\n /** A clone of the current state, or undefined if empty. */\n current(): S | undefined {\n return this.cursor >= 0 ? this.clone(this.history[this.cursor]) : undefined;\n }\n\n get canUndo(): boolean {\n return this.cursor > 0;\n }\n get canRedo(): boolean {\n return this.cursor < this.history.length - 1;\n }\n /** Number of recorded states retained. */\n get size(): number {\n return this.history.length;\n }\n\n clear(): void {\n this.history.length = 0;\n this.cursor = -1;\n }\n}\n\n/**\n * A fixed-capacity ring buffer \u2014 the ghost/echo trail. Push a pose (or any value)\n * each frame; when full, the oldest is overwritten. `toArray()` returns\n * oldest\u2192newest, which is exactly the order a trail renderer wants (tail first,\n * head last). Pure and O(1) per push.\n */\nexport class RingBuffer<T> {\n private readonly buf: (T | undefined)[];\n private start = 0;\n private count = 0;\n\n constructor(readonly capacity: number) {\n if (!Number.isInteger(capacity) || capacity < 1) throw new Error('hayao: RingBuffer capacity must be a positive integer');\n this.buf = new Array<T | undefined>(capacity);\n }\n\n push(item: T): void {\n const end = (this.start + this.count) % this.capacity;\n this.buf[end] = item;\n if (this.count < this.capacity) {\n this.count++;\n } else {\n // Full: the write above overwrote the oldest slot; advance start past it.\n this.start = (this.start + 1) % this.capacity;\n }\n }\n\n /** Number of items currently held (\u2264 capacity). */\n get length(): number {\n return this.count;\n }\n get isFull(): boolean {\n return this.count === this.capacity;\n }\n\n /** Item by age index: 0 = oldest, length-1 = newest. Undefined if out of range. */\n at(i: number): T | undefined {\n if (i < 0 || i >= this.count) return undefined;\n return this.buf[(this.start + i) % this.capacity];\n }\n\n /** The most recently pushed item, or undefined if empty. */\n latest(): T | undefined {\n return this.at(this.count - 1);\n }\n\n /** Contents oldest\u2192newest. */\n toArray(): T[] {\n const out: T[] = [];\n for (let i = 0; i < this.count; i++) out.push(this.buf[(this.start + i) % this.capacity]!);\n return out;\n }\n\n clear(): void {\n this.start = 0;\n this.count = 0;\n this.buf.fill(undefined);\n }\n}\n", "// Pluggable persistence backend. The ONLY browser-coupled piece of save/load:\n// everything above it (codec, save manager) is pure and headless-stable. In the\n// browser you get `localStorage`; headless you get an in-memory map (so tests can\n// round-trip a save without touching disk or leaking global state) or a true\n// no-op. The sim never imports this directly \u2014 it snapshots/restores plain data.\n\n/**\n * A minimal key\u2192string store. Deliberately tiny (get/set/remove/keys) so any\n * backend \u2014 `localStorage`, a Map, a file, IndexedDB \u2014 satisfies it trivially.\n */\nexport interface StorageAdapter {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n /** All keys currently held, in insertion order where the backend preserves it. */\n keys(): string[];\n}\n\n/** In-memory backend. Deterministic and self-contained \u2014 the headless default. */\nexport class MemoryStorage implements StorageAdapter {\n private readonly map = new Map<string, string>();\n\n get(key: string): string | null {\n return this.map.has(key) ? this.map.get(key)! : null;\n }\n set(key: string, value: string): void {\n this.map.set(key, value);\n }\n remove(key: string): void {\n this.map.delete(key);\n }\n keys(): string[] {\n return [...this.map.keys()];\n }\n}\n\n/** Swallows everything \u2014 reads always miss. For runs that must stay pristine. */\nexport class NullStorage implements StorageAdapter {\n get(_key: string): string | null {\n return null;\n }\n set(_key: string, _value: string): void {}\n remove(_key: string): void {}\n keys(): string[] {\n return [];\n }\n}\n\n/**\n * `localStorage`-backed, guarded on every call: a disabled/absent/full store\n * (private mode, quota, SSR) degrades to a silent miss instead of throwing, so a\n * save failure never crashes a game. Keys are namespaced by `prefix`.\n */\nexport class LocalStorageAdapter implements StorageAdapter {\n constructor(private readonly prefix = 'hayao.save.') {}\n\n private ls(): Storage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null; // access itself can throw when cookies/storage are blocked\n }\n }\n\n get(key: string): string | null {\n try {\n return this.ls()?.getItem(this.prefix + key) ?? null;\n } catch {\n return null;\n }\n }\n set(key: string, value: string): void {\n try {\n this.ls()?.setItem(this.prefix + key, value);\n } catch {\n /* quota / disabled \u2014 a lost save beats a crash */\n }\n }\n remove(key: string): void {\n try {\n this.ls()?.removeItem(this.prefix + key);\n } catch {\n /* ignore */\n }\n }\n keys(): string[] {\n const ls = this.ls();\n if (!ls) return [];\n const out: string[] = [];\n try {\n for (let i = 0; i < ls.length; i++) {\n const k = ls.key(i);\n if (k && k.startsWith(this.prefix)) out.push(k.slice(this.prefix.length));\n }\n } catch {\n /* ignore */\n }\n return out;\n }\n}\n\n/**\n * The right adapter for the current environment: `localStorage` when a real one\n * is present (browser), otherwise an in-memory map (headless tests/CI). Pass\n * `NullStorage` explicitly when you want reads to always miss.\n */\nexport function defaultStorage(prefix?: string): StorageAdapter {\n try {\n if (typeof localStorage !== 'undefined') {\n // Feature-probe rather than trust the global: some headless runtimes expose\n // a `localStorage` object whose methods throw. A real write/read/remove is\n // the only honest test; any failure falls through to the in-memory backend.\n const probe = '__hayao_probe__';\n localStorage.setItem(probe, '1');\n localStorage.removeItem(probe);\n return new LocalStorageAdapter(prefix);\n }\n } catch {\n /* fall through to memory */\n }\n return new MemoryStorage();\n}\n", "// Compact string codecs for levels and state \u2014 the js13k byte-squeeze trick, made\n// deterministic and fully reversible. Two independent tools:\n// \u2022 RLE \u2014 collapse runs in grid/level strings (walls, tiles), witchcat-style.\n// \u2022 varint pack \u2014 pack a list of small non-negative ints into a short URL-safe\n// string (base-64 continuation varints), soul-surf encode/decode.\n// Both are pure functions with exact round-trips; no RNG, no clock, no browser.\n\n// \u2500\u2500 Run-length encoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Reversible for ANY string. A run of \u22654 (or any literal escape char) becomes\n// `~<char><count>~`; shorter runs stay literal. Compact for repetitive maps,\n// never larger by more than the escapes it introduces.\nconst ESC = '~';\nconst RLE_MIN_RUN = 4;\n\nexport function rleEncode(input: string): string {\n let out = '';\n let i = 0;\n while (i < input.length) {\n const ch = input[i];\n let run = 1;\n while (i + run < input.length && input[i + run] === ch) run++;\n if (run >= RLE_MIN_RUN || ch === ESC) {\n out += ESC + ch + run.toString(36) + ESC;\n } else {\n out += ch.repeat(run);\n }\n i += run;\n }\n return out;\n}\n\nexport function rleDecode(input: string): string {\n let out = '';\n let i = 0;\n while (i < input.length) {\n if (input[i] === ESC) {\n const ch = input[i + 1];\n const end = input.indexOf(ESC, i + 2);\n if (ch === undefined || end < 0) throw new Error('hayao: malformed RLE stream');\n const count = parseInt(input.slice(i + 2, end), 36);\n if (!Number.isFinite(count) || count < 1) throw new Error('hayao: malformed RLE count');\n out += ch.repeat(count);\n i = end + 1;\n } else {\n out += input[i];\n i++;\n }\n }\n return out;\n}\n\n// \u2500\u2500 Base-64 variable-length integers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Pack non-negative integers into a URL/JSON-safe string: 6 bits per char, the\n// top bit a continuation flag (LEB128-style, base 32 per digit). Ideal for\n// coordinate lists, tile ids, and other small-int level payloads.\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\nconst INDEX: Record<string, number> = {};\nfor (let i = 0; i < ALPHABET.length; i++) INDEX[ALPHABET[i]] = i;\n\nexport function packVarints(nums: readonly number[]): string {\n let out = '';\n for (const n of nums) {\n if (!Number.isInteger(n) || n < 0) throw new Error(`hayao: packVarints expects non-negative integers, got ${n}`);\n let v = n;\n do {\n let digit = v & 0x1f; // low 5 bits\n v = Math.floor(v / 32);\n if (v > 0) digit |= 0x20; // continuation bit\n out += ALPHABET[digit];\n } while (v > 0);\n }\n return out;\n}\n\nexport function unpackVarints(input: string): number[] {\n const out: number[] = [];\n let v = 0;\n let shift = 1;\n for (const ch of input) {\n const digit = INDEX[ch];\n if (digit === undefined) throw new Error(`hayao: unpackVarints saw invalid char \"${ch}\"`);\n v += (digit & 0x1f) * shift;\n if (digit & 0x20) {\n shift *= 32; // more digits follow\n } else {\n out.push(v);\n v = 0;\n shift = 1;\n }\n }\n if (shift !== 1) throw new Error('hayao: unpackVarints hit a truncated stream');\n return out;\n}\n", "// Player-facing save/load over a pluggable StorageAdapter. Built ON TOP of the\n// existing `world.snapshot()`/`world.restore()` seam \u2014 it does NOT reinvent\n// serialization; it versions, guards, and persists what the world already emits.\n// A restored world reproduces the saved `hash()`/`probe()` exactly.\n\nimport type { World, WorldSnapshot } from '../world';\nimport { defaultStorage, type StorageAdapter } from './storage';\n\n/** Envelope stored per slot: a version tag around the raw WorldSnapshot. */\ninterface SaveEnvelope {\n v: number;\n snap: WorldSnapshot;\n}\n\n/** Bump when the snapshot shape changes in a way old saves can't satisfy. */\nexport const SAVE_FORMAT_VERSION = 1;\n\n/** Serialize a snapshot to a compact JSON string with a version envelope. */\nexport function serializeSnapshot(snap: WorldSnapshot): string {\n const envelope: SaveEnvelope = { v: SAVE_FORMAT_VERSION, snap };\n return JSON.stringify(envelope);\n}\n\n/**\n * Parse a serialized snapshot back. Returns `null` on anything malformed \u2014\n * corrupt JSON, wrong version, missing fields \u2014 so a bad save is a clean miss,\n * never a thrown exception mid-game. Guards `JSON.parse` per the invariant.\n */\nexport function parseSnapshot(text: string | null): WorldSnapshot | null {\n if (!text) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== 'object') return null;\n const env = parsed as Partial<SaveEnvelope>;\n if (env.v !== SAVE_FORMAT_VERSION || !env.snap || typeof env.snap !== 'object') return null;\n const snap = env.snap as Partial<WorldSnapshot>;\n // Minimal shape check on the fields `restore()` reads.\n if (typeof snap.seed !== 'number' || !snap.rng || !snap.clock || !snap.input || !snap.state || !snap.tree) {\n return null;\n }\n return snap as WorldSnapshot;\n}\n\n/**\n * A tiny save API bound to one World and one storage backend. Slots are named\n * ('auto', 'slot1', \u2026). Everything routes through `world.snapshot()`/`restore()`\n * so the saved and restored states share a hash.\n */\nexport class SaveManager {\n constructor(\n private readonly world: World,\n private readonly storage: StorageAdapter = defaultStorage(),\n ) {}\n\n /** Snapshot the world and persist it under `slot`. */\n save(slot = 'auto'): void {\n this.storage.set(slot, serializeSnapshot(this.world.snapshot()));\n }\n\n /** Restore `slot` into the world. Returns false if absent/corrupt (world untouched). */\n load(slot = 'auto'): boolean {\n const snap = parseSnapshot(this.storage.get(slot));\n if (!snap) return false;\n this.world.restore(snap);\n return true;\n }\n\n /** Is there a well-formed save in `slot`? */\n has(slot = 'auto'): boolean {\n return parseSnapshot(this.storage.get(slot)) !== null;\n }\n\n /** Delete a save slot. */\n delete(slot = 'auto'): void {\n this.storage.remove(slot);\n }\n\n /** All slot names currently persisted. */\n slots(): string[] {\n return this.storage.keys();\n }\n}\n", "// Data-driven content: a small schema + interpreter for declarative game content,\n// so waves, spawn tables, and upgrade trees are DATA (hashable, editable, diff-able)\n// rather than hand-rolled control flow. Two primitives, one determinism rule \u2014\n// rolls draw from `world.rng`, scheduling reads `world.time` (fixed sim seconds):\n// \u2022 SpawnDirector \u2014 a flat wave/spawn schedule (norman) with repeats and an\n// optional weighted spawn set (cat-survivors' director).\n// \u2022 upgrade trees \u2014 availability gating by owned prerequisites (evolutions).\n// Weighted rolls reuse `logic/random` (WeightedEntry + pickEntry), not a private\n// copy. The director's cursor state is plain JSON, so it lives in `world.state`\n// and is snapshotted/hashed like everything else.\n\nimport type { Rng } from '../core/rng';\nimport { pickEntry, type WeightedEntry } from '../logic/random';\n\n// \u2500\u2500 Wave / spawn director \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * One declarative wave. Fires `count` of `spawn` at time `time` (sim seconds).\n * When `every` is set it repeats on that interval until `end` (exclusive),\n * modelling a continuous spawn stream. `spawn` may be a single id or a weighted\n * table, in which case each firing rolls the table via `world.rng`.\n */\nexport interface WaveDef {\n /** First fire time, in fixed sim seconds (compare against `world.time`). */\n time: number;\n /** What to spawn: a fixed id, or a weighted set rolled per firing. */\n spawn: string | WeightedEntry<string>[];\n /** How many per firing (default 1). */\n count?: number;\n /** Repeat interval in seconds; omit for a one-shot wave. */\n every?: number;\n /** Repeats stop once the next fire time reaches this (seconds). */\n end?: number;\n}\n\n/** Mutable director cursor \u2014 plain JSON, keep it in `world.state`. */\nexport interface DirectorState {\n /** Next fire time per wave index; Infinity once a wave is exhausted. */\n next: number[];\n}\n\n/** One resolved spawn instruction emitted by the director. */\nexport interface SpawnEvent {\n /** Concrete spawn id (already rolled if the wave used a weighted set). */\n spawn: string;\n count: number;\n /** Source wave index, for callers that want to key behavior off the wave. */\n wave: number;\n}\n\n/** Initialize a director cursor for a schedule. */\nexport function initDirector(waves: readonly WaveDef[]): DirectorState {\n return { next: waves.map((w) => w.time) };\n}\n\n/**\n * Advance the director to `time` (sim seconds) and return every spawn that is\n * now due, in wave order. Mutates `state.next` in place. Deterministic: it emits\n * the same events for the same (schedule, time, rng-state) on every machine.\n * A repeating wave can fire multiple times in one poll if the frame straddled\n * several intervals (e.g. after a restore), so catch-up never drops spawns.\n */\nexport function pollDirector(waves: readonly WaveDef[], state: DirectorState, time: number, rng?: Rng): SpawnEvent[] {\n const out: SpawnEvent[] = [];\n for (let i = 0; i < waves.length; i++) {\n const w = waves[i];\n let next = state.next[i] ?? w.time;\n while (next <= time) {\n let spawn: string;\n if (typeof w.spawn === 'string') {\n spawn = w.spawn;\n } else {\n if (!rng) throw new Error('hayao: pollDirector needs an Rng to roll a weighted wave');\n spawn = pickEntry(rng, w.spawn);\n }\n out.push({ spawn, count: w.count ?? 1, wave: i });\n if (w.every && w.every > 0) {\n next += w.every;\n if (w.end !== undefined && next >= w.end) {\n next = Infinity;\n break;\n }\n } else {\n next = Infinity;\n break;\n }\n }\n state.next[i] = next;\n }\n return out;\n}\n\n// \u2500\u2500 Upgrade / evolution trees \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * A declarative upgrade or evolution node. `requires` lists ids that must all be\n * owned before this one can be offered \u2014 the cat-survivors evolution gate and a\n * deckbuilder's upgrade prerequisites are the same shape.\n */\nexport interface UpgradeDef {\n id: string;\n /** Ids that must all be owned before this becomes available. */\n requires?: string[];\n /** Optional: only offer while UNDER this many owned copies (repeatable upgrades). */\n maxStacks?: number;\n}\n\n/**\n * Which upgrades are offerable given what's owned: prerequisites all met, and\n * not already at `maxStacks` (default 1 \u2014 offered until owned once). `owned` may\n * repeat ids to represent stacks. Ordered by definition order for hash stability.\n */\nexport function availableUpgrades(defs: readonly UpgradeDef[], owned: readonly string[]): UpgradeDef[] {\n const counts = new Map<string, number>();\n for (const id of owned) counts.set(id, (counts.get(id) ?? 0) + 1);\n const has = (id: string) => (counts.get(id) ?? 0) > 0;\n return defs.filter((d) => {\n const stacks = counts.get(d.id) ?? 0;\n if (stacks >= (d.maxStacks ?? 1)) return false;\n return (d.requires ?? []).every(has);\n });\n}\n", "// Multiplayer inputs without touching the sim kernel: each player's actions are\n// namespaced (`p1:left`, `p2:jump`) and merged into the single flat action set\n// that `world.step()` already takes. The whole verify harness (InputLog, replay,\n// determinism checks) works on multiplayer games unchanged \u2014 a merged frame is\n// just a frame.\n\nimport type { World } from '../world';\n\n/** A player identity: 'p1', 'p2', \u2026 (any short string without ':' works). */\nexport type PlayerId = string;\n\n/** The canonical roster for n players: ['p1', \u2026, 'pn']. */\nexport function playerIds(count: number): PlayerId[] {\n const out: PlayerId[] = [];\n for (let i = 1; i <= count; i++) out.push(`p${i}`);\n return out;\n}\n\n/** Namespace one action for a player: ('p2', 'left') \u2192 'p2:left'. */\nexport const playerAction = (player: PlayerId, action: string): string => `${player}:${action}`;\n\n/**\n * Merge per-player action sets into one flat, sorted frame for `world.step()`.\n * Deterministic: players are processed in roster order and the result is sorted,\n * so every peer computes the identical frame from the same inputs.\n */\nexport function mergePlayerFrames(players: readonly PlayerId[], inputs: ReadonlyMap<PlayerId, readonly string[]>): string[] {\n const out: string[] = [];\n for (const p of players) {\n const actions = inputs.get(p) ?? [];\n for (const a of actions) out.push(playerAction(p, a));\n }\n return out.sort();\n}\n\n/**\n * A per-player view over the world's input state. Game logic asks\n * `player.isDown('left')` and never sees the namespacing.\n */\nexport class PlayerInput {\n constructor(\n private readonly world: World,\n readonly player: PlayerId,\n ) {}\n\n isDown(action: string): boolean {\n return this.world.input.isDown(playerAction(this.player, action));\n }\n justPressed(action: string): boolean {\n return this.world.input.justPressed(playerAction(this.player, action));\n }\n justReleased(action: string): boolean {\n return this.world.input.justReleased(playerAction(this.player, action));\n }\n}\n\n/** Convenience: the input view for one player. */\nexport const playerInput = (world: World, player: PlayerId): PlayerInput => new PlayerInput(world, player);\n", "// The wire protocol. Plain JSON messages over a bus transport (every peer sees\n// every message; `to` filters when a message is for one endpoint). Two layers\n// share the bus: the room layer (hello/welcome/join/leave/start \u2014 owned by\n// RoomHost/RoomClient) and the session layer (input/hash \u2014 owned by the\n// lockstep/rollback sessions).\n\nimport type { WorldSnapshot } from '../world';\nimport type { PlayerId } from './players';\n\nexport const NET_PROTOCOL_VERSION = 1;\n\n/** Session tuning shared by every peer (the host dictates it in `welcome`). */\nexport interface NetSessionConfig {\n mode: 'lockstep' | 'rollback';\n /** Frames of input delay (lockstep) \u2014 hides transport latency. */\n inputDelay: number;\n /** Exchange a state hash every N frames to catch desyncs early. */\n hashInterval: number;\n /** Rollback: how many frames of history can be rewound. */\n maxRollback: number;\n /** How many recent frames each input message re-sends (loss tolerance). */\n redundancy: number;\n}\n\nexport const DEFAULT_SESSION_CONFIG: NetSessionConfig = {\n mode: 'lockstep',\n inputDelay: 2,\n hashInterval: 20,\n maxRollback: 12,\n redundancy: 3,\n};\n\nexport type NetMessage =\n // \u2500\u2500 room layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** A new endpoint asks to join. `uid` is its transport-unique id. */\n | { v: number; t: 'hello'; uid: string; name?: string }\n /** Host \u2192 one endpoint: your player id + everything needed to start/join. */\n | {\n v: number;\n t: 'welcome';\n to: string;\n player: PlayerId;\n players: PlayerId[];\n seed: number;\n config: NetSessionConfig;\n /** Frame the joiner starts at (0 for a fresh game). */\n startFrame: number;\n /** Mid-game join: the world state at `startFrame`. */\n snapshot?: WorldSnapshot;\n /** Other joins announced but not yet live (their bootstrap frames). */\n joins?: Array<{ player: PlayerId; atFrame: number }>;\n }\n /** Host \u2192 all: a player will exist from `atFrame` on (late join). */\n | { v: number; t: 'join'; player: PlayerId; atFrame: number }\n /** Host \u2192 all: a player's inputs end at `atFrame` (disconnect/quit). */\n | { v: number; t: 'leave'; player: PlayerId; atFrame: number }\n /** Host \u2192 all: begin simulating from frame 0 with this final roster. */\n | { v: number; t: 'start'; players: PlayerId[] }\n /** Any endpoint \u2192 host: polite disconnect. */\n | { v: number; t: 'bye'; uid: string }\n /** Host \u2192 one endpoint: join refused (room full, mode without late join\u2026). */\n | { v: number; t: 'deny'; to: string; reason: string }\n // \u2500\u2500 session layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Player inputs for frames [from, from+frames.length). Re-sends a small\n * window so a dropped message doesn't stall anyone. */\n | { v: number; t: 'input'; player: PlayerId; from: number; frames: string[][] }\n /** Structural world hash at a frame \u2014 cross-checked by every peer. */\n | { v: number; t: 'hash'; player: PlayerId; frame: number; hash: string };\n\nexport function encodeMessage(msg: NetMessage): string {\n return JSON.stringify(msg);\n}\n\n/** Decode + shallow-validate. Returns null for junk or version mismatch. */\nexport function decodeMessage(data: string): NetMessage | null {\n try {\n const msg = JSON.parse(data) as NetMessage;\n if (!msg || typeof msg !== 'object' || msg.v !== NET_PROTOCOL_VERSION || typeof msg.t !== 'string') return null;\n return msg;\n } catch {\n return null;\n }\n}\n\n/** Build a message with the protocol version stamped in. */\nexport function netMessage<T extends Omit<NetMessage, 'v'>>(msg: T): T & { v: number } {\n return { v: NET_PROTOCOL_VERSION, ...msg };\n}\n", "// Transports: how bytes move between peers. All transports are BUSES \u2014 send()\n// reaches every other peer on the same medium. That matches BroadcastChannel\n// (multi-tab), a dumb WebSocket relay (one room = one bus), and the in-memory\n// loopback hub (tests) with a single semantics, so sessions never care which\n// one they run on. Addressing, when needed, lives in the message (`to` field).\n\nexport interface Transport {\n /** Deliver to every other peer on the bus. */\n send(data: string): void;\n /** Subscribe to incoming data. Returns an unsubscribe function. */\n onMessage(cb: (data: string) => void): () => void;\n /** Fires when the transport goes away (socket close, hub shutdown). */\n onClose(cb: () => void): () => void;\n close(): void;\n readonly isOpen: boolean;\n}\n\n// \u2500\u2500 loopback: deterministic in-memory bus for tests \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface LoopbackOptions {\n /** Delivery delay in ticks (calls to hub.tick()). Default 0 = next tick. */\n delay?: number;\n /** Drop every Nth message (deterministic loss pattern). 0 = lossless. */\n dropEvery?: number;\n}\n\ninterface QueuedMessage {\n data: string;\n from: number;\n dueTick: number;\n seq: number;\n}\n\n/**\n * An in-memory bus with explicit, deterministic time: nothing is delivered\n * until `tick()` runs, messages arrive in send order, and loss follows a fixed\n * pattern. Network tests stay exactly reproducible \u2014 no timers, no races.\n */\nexport class LoopbackHub {\n private peers: LoopbackTransport[] = [];\n private queue: QueuedMessage[] = [];\n private tickCount = 0;\n private seq = 0;\n private sent = 0;\n private readonly delay: number;\n private readonly dropEvery: number;\n\n constructor(opts: LoopbackOptions = {}) {\n this.delay = opts.delay ?? 0;\n this.dropEvery = opts.dropEvery ?? 0;\n }\n\n /** Create a new endpoint on this bus. */\n connect(): LoopbackTransport {\n const t = new LoopbackTransport(this, this.peers.length);\n this.peers.push(t);\n return t;\n }\n\n /** @internal */\n enqueue(data: string, from: number): void {\n this.sent++;\n if (this.dropEvery > 0 && this.sent % this.dropEvery === 0) return;\n this.queue.push({ data, from, dueTick: this.tickCount + this.delay, seq: this.seq++ });\n }\n\n /** Advance one network tick, delivering everything that is due. */\n tick(): void {\n const due = this.queue.filter((m) => m.dueTick <= this.tickCount).sort((a, b) => a.seq - b.seq);\n this.queue = this.queue.filter((m) => m.dueTick > this.tickCount);\n this.tickCount++;\n for (const m of due) {\n for (const peer of this.peers) {\n if (peer.peerIndex !== m.from && peer.isOpen) peer.deliver(m.data);\n }\n }\n }\n\n /** Deliver everything in flight (repeated ticks until the queue drains). */\n flush(): void {\n while (this.queue.length > 0) this.tick();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n}\n\nexport class LoopbackTransport implements Transport {\n private listeners: Array<(data: string) => void> = [];\n private closeListeners: Array<() => void> = [];\n private open = true;\n\n constructor(\n private readonly hub: LoopbackHub,\n readonly peerIndex: number,\n ) {}\n\n send(data: string): void {\n if (this.open) this.hub.enqueue(data, this.peerIndex);\n }\n onMessage(cb: (data: string) => void): () => void {\n this.listeners.push(cb);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== cb);\n };\n }\n onClose(cb: () => void): () => void {\n this.closeListeners.push(cb);\n return () => {\n this.closeListeners = this.closeListeners.filter((l) => l !== cb);\n };\n }\n close(): void {\n if (!this.open) return;\n this.open = false;\n for (const cb of this.closeListeners) cb();\n }\n get isOpen(): boolean {\n return this.open;\n }\n /** @internal */\n deliver(data: string): void {\n for (const cb of this.listeners) cb(data);\n }\n}\n\n// \u2500\u2500 BroadcastChannel: zero-server multi-tab play \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A bus over the browser's BroadcastChannel \u2014 every tab on the same origin\n * that opens the same room name is a peer. Perfect for local two-tab netplay\n * and demos: no server at all.\n */\nexport class BroadcastChannelTransport implements Transport {\n private channel: BroadcastChannel;\n private listeners: Array<(data: string) => void> = [];\n private closeListeners: Array<() => void> = [];\n private open = true;\n\n constructor(room: string) {\n this.channel = new BroadcastChannel(`hayao-net:${room}`);\n this.channel.onmessage = (e: MessageEvent) => {\n if (typeof e.data === 'string') for (const cb of this.listeners) cb(e.data);\n };\n }\n\n send(data: string): void {\n if (this.open) this.channel.postMessage(data);\n }\n onMessage(cb: (data: string) => void): () => void {\n this.listeners.push(cb);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== cb);\n };\n }\n onClose(cb: () => void): () => void {\n this.closeListeners.push(cb);\n return () => {\n this.closeListeners = this.closeListeners.filter((l) => l !== cb);\n };\n }\n close(): void {\n if (!this.open) return;\n this.open = false;\n this.channel.close();\n for (const cb of this.closeListeners) cb();\n }\n get isOpen(): boolean {\n return this.open;\n }\n}\n\n// \u2500\u2500 WebSocket: real network play via the relay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A bus over a WebSocket to the hayao relay (`npm run relay`): everyone\n * connected to the same room URL is a peer; the relay forwards each message to\n * the room's other sockets. Resolves once the socket is open.\n */\nexport function connectWebSocket(url: string): Promise<Transport> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const listeners: Array<(data: string) => void> = [];\n const closeListeners: Array<() => void> = [];\n let open = false;\n\n const transport: Transport = {\n send(data: string) {\n if (open) ws.send(data);\n },\n onMessage(cb) {\n listeners.push(cb);\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n },\n onClose(cb) {\n closeListeners.push(cb);\n return () => {\n const i = closeListeners.indexOf(cb);\n if (i >= 0) closeListeners.splice(i, 1);\n };\n },\n close() {\n open = false;\n ws.close();\n },\n get isOpen() {\n return open;\n },\n };\n\n ws.onopen = () => {\n open = true;\n resolve(transport);\n };\n ws.onmessage = (e: MessageEvent) => {\n if (typeof e.data === 'string') for (const cb of listeners) cb(e.data);\n };\n ws.onclose = () => {\n const wasOpen = open;\n open = false;\n if (wasOpen) for (const cb of closeListeners) cb();\n };\n ws.onerror = () => {\n if (!open) reject(new Error(`hayao-net: could not connect to ${url}`));\n };\n });\n}\n", "// Per-player input history. Both session kinds keep one: lockstep asks \"do I\n// have everyone's frame N?\", rollback asks \"what changed vs. my prediction?\".\n// First-write-wins per (player, frame) so duplicated or reordered redundancy\n// windows can never rewrite history.\n\nimport type { PlayerId } from './players';\n\nexport class InputBuffer {\n /** player \u2192 frame \u2192 actions (sorted). */\n private frames = new Map<PlayerId, Map<number, string[]>>();\n /** player \u2192 highest contiguous frame received (for prediction + confirm). */\n private contiguous = new Map<PlayerId, number>();\n\n addPlayer(player: PlayerId): void {\n if (!this.frames.has(player)) {\n this.frames.set(player, new Map());\n this.contiguous.set(player, -1);\n }\n }\n\n removePlayer(player: PlayerId): void {\n this.frames.delete(player);\n this.contiguous.delete(player);\n }\n\n players(): PlayerId[] {\n return [...this.frames.keys()];\n }\n\n /**\n * Record a player's actions for a frame. Returns true if this was new\n * information (first write for that slot).\n */\n set(player: PlayerId, frame: number, actions: readonly string[]): boolean {\n const perPlayer = this.frames.get(player);\n if (!perPlayer || perPlayer.has(frame)) return false;\n perPlayer.set(frame, [...actions].sort());\n // Advance the contiguous watermark as far as the new frame allows.\n let c = this.contiguous.get(player) ?? -1;\n while (perPlayer.has(c + 1)) c++;\n this.contiguous.set(player, c);\n return true;\n }\n\n has(player: PlayerId, frame: number): boolean {\n return this.frames.get(player)?.has(frame) ?? false;\n }\n\n get(player: PlayerId, frame: number): string[] | undefined {\n return this.frames.get(player)?.get(frame);\n }\n\n /** The last actions at or before `frame` \u2014 the rollback predictor's guess. */\n latestAt(player: PlayerId, frame: number): string[] {\n const perPlayer = this.frames.get(player);\n if (!perPlayer) return [];\n for (let f = frame; f >= 0; f--) {\n const a = perPlayer.get(f);\n if (a) return a;\n }\n return [];\n }\n\n /** Highest frame such that this player's inputs 0..frame are all known. */\n contiguousThrough(player: PlayerId): number {\n return this.contiguous.get(player) ?? -1;\n }\n\n /** Highest frame with ALL players' inputs known contiguously. */\n confirmedFrame(): number {\n let min = Infinity;\n for (const c of this.contiguous.values()) min = Math.min(min, c);\n return min === Infinity ? -1 : min;\n }\n\n /** Forget a player's frames at/after `frame` (leave cutoff). */\n clearFrom(player: PlayerId, frame: number): void {\n const perPlayer = this.frames.get(player);\n if (!perPlayer) return;\n for (const f of perPlayer.keys()) if (f >= frame) perPlayer.delete(f);\n let c = this.contiguous.get(player) ?? -1;\n if (c >= frame) c = frame - 1;\n this.contiguous.set(player, c);\n }\n\n /** Drop history strictly before `frame` (memory hygiene on long sessions). */\n prune(frame: number): void {\n for (const perPlayer of this.frames.values()) {\n for (const f of perPlayer.keys()) if (f < frame) perPlayer.delete(f);\n }\n }\n}\n", "// Deterministic lockstep: every peer runs the identical sim and only steps\n// frame N once it holds EVERY active player's input for N. Local input is\n// scheduled `inputDelay` frames ahead to hide transport latency. Because\n// `world.step(mergedFrame)` is already a pure transition, the network layer\n// never touches the sim \u2014 it only decides when a step may run and what the\n// merged frame contains.\n//\n// Desync safety: every `hashInterval` frames each peer broadcasts its\n// `world.hash()`; any mismatch surfaces the frame, both hashes, and the full\n// merged input log \u2014 which `replay()` can binary-search offline.\n\nimport type { World } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { InputBuffer } from './inputBuffer';\nimport { mergePlayerFrames, type PlayerId } from './players';\nimport { DEFAULT_SESSION_CONFIG, decodeMessage, encodeMessage, netMessage, type NetSessionConfig } from './protocol';\nimport type { Transport } from './transport';\n\nexport interface DesyncInfo {\n frame: number;\n player: PlayerId;\n localHash: string;\n remoteHash: string;\n /** Merged frames from this session's startFrame \u2014 replay fodder. */\n log: InputLog;\n startFrame: number;\n}\n\nexport interface LockstepOptions {\n world: World;\n transport: Transport;\n localPlayer: PlayerId;\n /** Roster at startFrame, in canonical order. */\n players: PlayerId[];\n /** Frame this session begins at (0 for a fresh game, >0 for a late joiner). */\n startFrame?: number;\n config?: Partial<NetSessionConfig>;\n onDesync?: (info: DesyncInfo) => void;\n /** Fired when a step is blocked waiting on a player's input. */\n onStall?: (player: PlayerId, frame: number) => void;\n}\n\ninterface RosterEntry {\n player: PlayerId;\n from: number;\n until: number; // exclusive; Infinity = still present\n}\n\nexport class LockstepSession {\n readonly world: World;\n readonly localPlayer: PlayerId;\n readonly config: NetSessionConfig;\n readonly startFrame: number;\n\n private readonly transport: Transport;\n private readonly buffer = new InputBuffer();\n private roster: RosterEntry[] = [];\n private mergedLog: string[][] = [];\n private localHashes = new Map<number, string>();\n private pendingRemoteHashes: Array<{ player: PlayerId; frame: number; hash: string }> = [];\n private sentThrough: number;\n private stallCount = 0;\n private desynced = false;\n private afterStepListeners: Array<(frame: number) => void> = [];\n private unsubscribe: () => void;\n private readonly onDesync?: (info: DesyncInfo) => void;\n private readonly onStall?: (player: PlayerId, frame: number) => void;\n\n constructor(opts: LockstepOptions) {\n this.world = opts.world;\n this.transport = opts.transport;\n this.localPlayer = opts.localPlayer;\n this.config = { ...DEFAULT_SESSION_CONFIG, ...opts.config, mode: 'lockstep' };\n this.startFrame = opts.startFrame ?? 0;\n this.onDesync = opts.onDesync;\n this.onStall = opts.onStall;\n\n for (const p of opts.players) {\n this.roster.push({ player: p, from: this.startFrame, until: Infinity });\n this.buffer.addPlayer(p);\n // Bootstrap: a player's first `inputDelay` frames are empty \u2014 identical\n // on every peer without a single message. At a fresh start that is\n // everyone; a late joiner seeds only ITSELF (the veterans have real\n // inputs at its startFrame, which must be used, not zeroed).\n if (this.startFrame === 0 || p === this.localPlayer) {\n for (let f = this.startFrame; f < this.startFrame + this.config.inputDelay; f++) this.buffer.set(p, f, []);\n }\n }\n this.sentThrough = this.startFrame + this.config.inputDelay - 1;\n\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n // \u2500\u2500 the roster (players can come and go at agreed frames) \u2500\u2500\u2500\u2500\n activePlayers(frame: number): PlayerId[] {\n return this.roster.filter((r) => r.from <= frame && frame < r.until).map((r) => r.player);\n }\n\n /** All peers must call this with the SAME atFrame (the room layer's job). */\n addPlayer(player: PlayerId, atFrame: number): void {\n if (this.roster.some((r) => r.player === player && r.until === Infinity)) return; // already present\n this.roster.push({ player, from: atFrame, until: Infinity });\n this.buffer.addPlayer(player);\n for (let f = atFrame; f < atFrame + this.config.inputDelay; f++) this.buffer.set(player, f, []);\n }\n\n /** All peers must call this with the SAME atFrame. */\n removePlayer(player: PlayerId, atFrame: number): void {\n const entry = this.roster.find((r) => r.player === player && r.until === Infinity);\n if (entry) entry.until = atFrame;\n // Frames at/after the cutoff must never merge, even if they arrived.\n this.buffer.clearFrom(player, atFrame);\n }\n\n // \u2500\u2500 driving the sim \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n get frame(): number {\n return this.world.frame;\n }\n\n /** Highest frame every currently-active player's input is known for. */\n get confirmedFrame(): number {\n let min = Infinity;\n for (const p of this.activePlayers(this.world.frame)) min = Math.min(min, this.buffer.contiguousThrough(p));\n return min === Infinity ? -1 : min;\n }\n\n get stalls(): number {\n return this.stallCount;\n }\n\n /**\n * Try to advance exactly one frame with the local player's current actions.\n * Returns 1 if the world stepped, 0 if blocked waiting for a remote input.\n */\n tick(localActions: readonly string[] = []): number {\n if (this.desynced) return 0;\n const f = this.world.frame;\n this.scheduleLocal(localActions);\n\n const active = this.activePlayers(f);\n for (const p of active) {\n if (!this.buffer.has(p, f)) {\n this.stallCount++;\n this.onStall?.(p, f);\n return 0;\n }\n }\n\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of active) inputs.set(p, this.buffer.get(p, f)!);\n const merged = mergePlayerFrames(active, inputs);\n this.world.step(merged);\n this.mergedLog.push(merged);\n this.afterStep(this.world.frame);\n return 1;\n }\n\n /**\n * Feed real elapsed ms (the browser loop's dt). Runs the fixed steps the\n * clock grants \u2014 stalling drops time (the sim slows rather than desyncs) \u2014\n * then catches up if we're measurably behind the other peers.\n */\n advance(realMs: number, localActions: readonly string[] = []): number {\n let stepped = 0;\n const steps = this.world.clock.advance(realMs);\n for (let i = 0; i < steps; i++) {\n if (this.tick(localActions) === 0) break;\n stepped++;\n }\n // Catch-up: if remote inputs prove peers are ahead, step extra frames now.\n let guard = 0;\n while (guard++ < 8 && this.world.frame < this.remoteFrameEstimate() && this.tick(localActions) === 1) stepped++;\n return stepped;\n }\n\n /** The merged input log from startFrame \u2014 replayable when startFrame is 0. */\n inputLog(): InputLog {\n return { frames: this.mergedLog.map((f) => f.slice()) };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n\n /** Feed a raw transport message that arrived before this session existed. */\n deliver(data: string): void {\n this.receive(data);\n }\n\n /** Subscribe to \"the world just reached frame N\" (room layer uses this). */\n onAfterStep(cb: (frame: number) => void): () => void {\n this.afterStepListeners.push(cb);\n return () => {\n this.afterStepListeners = this.afterStepListeners.filter((l) => l !== cb);\n };\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private scheduleLocal(localActions: readonly string[]): void {\n const target = this.world.frame + this.config.inputDelay;\n if (this.sentThrough >= target) return;\n while (this.sentThrough < target) {\n this.sentThrough++;\n this.buffer.set(this.localPlayer, this.sentThrough, localActions);\n }\n // Send a small window ending at the newest frame so one lost message\n // cannot stall the room.\n const from = Math.max(this.startFrame, target - this.config.redundancy + 1);\n const frames: string[][] = [];\n for (let f = from; f <= target; f++) frames.push(this.buffer.get(this.localPlayer, f) ?? []);\n this.transport.send(encodeMessage(netMessage({ t: 'input', player: this.localPlayer, from, frames })));\n }\n\n private afterStep(frame: number): void {\n if (frame % this.config.hashInterval === 0) {\n const hash = this.world.hash();\n this.localHashes.set(frame, hash);\n this.transport.send(encodeMessage(netMessage({ t: 'hash', player: this.localPlayer, frame, hash })));\n this.checkPendingHashes();\n }\n // Memory hygiene: keep a generous tail, drop ancient history.\n if (frame % 64 === 0) {\n this.buffer.prune(frame - 128);\n for (const f of this.localHashes.keys()) if (f < frame - 512) this.localHashes.delete(f);\n }\n for (const cb of this.afterStepListeners) cb(frame);\n }\n\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'input' && msg.player !== this.localPlayer) {\n for (let i = 0; i < msg.frames.length; i++) this.buffer.set(msg.player, msg.from + i, msg.frames[i]);\n } else if (msg.t === 'hash' && msg.player !== this.localPlayer) {\n this.pendingRemoteHashes.push({ player: msg.player, frame: msg.frame, hash: msg.hash });\n this.checkPendingHashes();\n }\n }\n\n private checkPendingHashes(): void {\n const still: typeof this.pendingRemoteHashes = [];\n for (const remote of this.pendingRemoteHashes) {\n const local = this.localHashes.get(remote.frame);\n if (local === undefined) {\n // We haven't reached (or have already pruned) that frame \u2014 keep it\n // unless it is ancient.\n if (remote.frame > this.world.frame - 512) still.push(remote);\n continue;\n }\n if (local !== remote.hash && !this.desynced) {\n this.desynced = true;\n this.onDesync?.({\n frame: remote.frame,\n player: remote.player,\n localHash: local,\n remoteHash: remote.hash,\n log: this.inputLog(),\n startFrame: this.startFrame,\n });\n }\n }\n this.pendingRemoteHashes = still;\n }\n\n private remoteFrameEstimate(): number {\n let max = -1;\n for (const entry of this.roster) {\n if (entry.player === this.localPlayer || entry.until !== Infinity) continue;\n // A peer schedules input `inputDelay` ahead of its sim frame.\n max = Math.max(max, this.buffer.contiguousThrough(entry.player) - this.config.inputDelay);\n }\n return max;\n }\n}\n", "// Predict-rollback netcode (GGPO/Rune-style) on top of the engine's proven\n// snapshot/restore. Every frame: send local input immediately, predict remote\n// inputs (repeat-last), step. When a real input contradicts a prediction,\n// restore the snapshot at the mispredicted frame and re-simulate to the\n// present with corrected inputs. `assertSnapshotStable` already proves\n// restore is lossless, so a rollback is exactly \"rewind + replay\".\n//\n// One engine-specific caveat: `World.restore()` rebuilds the scene tree from\n// data, and behaviors (closures) do not survive that. Games played under\n// rollback must either keep all sim logic in `world.state` + `onProcess`-free\n// nodes, or pass `attach(world)` to re-wire behaviors after every restore \u2014\n// the same hook scene code already uses for save/load.\n\nimport type { World, WorldSnapshot } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { hashValue } from '../core/hash';\nimport { InputBuffer } from './inputBuffer';\nimport { mergePlayerFrames, type PlayerId } from './players';\nimport { DEFAULT_SESSION_CONFIG, decodeMessage, encodeMessage, netMessage, type NetSessionConfig } from './protocol';\nimport type { Transport } from './transport';\nimport type { DesyncInfo } from './lockstep';\n\nexport interface RollbackOptions {\n world: World;\n transport: Transport;\n localPlayer: PlayerId;\n players: PlayerId[];\n config?: Partial<NetSessionConfig>;\n /** Re-attach behaviors/controllers after every restore (save/load hook). */\n attach?: (world: World) => void;\n onDesync?: (info: DesyncInfo) => void;\n /** A correction arrived deeper than maxRollback \u2014 unrecoverable. */\n onRollbackOverflow?: (frame: number) => void;\n}\n\ninterface RingEntry {\n frame: number;\n snap: WorldSnapshot;\n}\n\nexport class RollbackSession {\n readonly world: World;\n readonly localPlayer: PlayerId;\n readonly config: NetSessionConfig;\n\n private readonly transport: Transport;\n private readonly players: PlayerId[];\n private readonly buffer = new InputBuffer();\n private readonly attach?: (world: World) => void;\n private readonly onDesync?: (info: DesyncInfo) => void;\n private readonly onRollbackOverflow?: (frame: number) => void;\n\n /** Snapshot AT frame f (state before stepping f), keyed f % ring length. */\n private ring: Array<RingEntry | null>;\n /** What we actually fed `step()` per frame \u2014 prediction bookkeeping. */\n private usedInputs = new Map<number, Map<PlayerId, string>>();\n private earliestBad = Infinity;\n private rollbackCount = 0;\n private resimulatedFrames = 0;\n private localHashes = new Map<number, string>();\n /** player \u2192 cutoff frame: their inputs are [] from there on (departed). */\n private dropped = new Map<PlayerId, number>();\n private pendingRemoteHashes: Array<{ player: PlayerId; frame: number; hash: string }> = [];\n private hashedThrough = -1;\n private desynced = false;\n private overflowed = false;\n private unsubscribe: () => void;\n\n constructor(opts: RollbackOptions) {\n this.world = opts.world;\n this.transport = opts.transport;\n this.localPlayer = opts.localPlayer;\n this.players = [...opts.players];\n this.config = { ...DEFAULT_SESSION_CONFIG, mode: 'rollback', inputDelay: 0, ...opts.config };\n this.attach = opts.attach;\n this.onDesync = opts.onDesync;\n this.onRollbackOverflow = opts.onRollbackOverflow;\n this.ring = new Array(this.config.maxRollback + 1).fill(null);\n for (const p of this.players) this.buffer.addPlayer(p);\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n get frame(): number {\n return this.world.frame;\n }\n\n /** Highest frame all players' real inputs are known for (inclusive). */\n get confirmedFrame(): number {\n let min = Infinity;\n for (const p of this.players) {\n const cut = this.dropped.get(p);\n let c = this.buffer.contiguousThrough(p);\n // A departed player's inputs are [] forever from the cutoff \u2014 known.\n if (cut !== undefined && c >= cut - 1) c = Infinity;\n min = Math.min(min, c);\n }\n return min === Infinity ? -1 : min;\n }\n\n /** Highest contiguous frame received from `player` \u2014 the drop-cutoff basis. */\n lastKnownFrame(player: PlayerId): number {\n return this.buffer.contiguousThrough(player);\n }\n\n /**\n * A player left (or vanished): their inputs are [] from `atFrame` on, so the\n * session stops waiting on them. All peers must apply the SAME atFrame (the\n * room layer broadcasts it). Frames already simulated with a non-empty\n * prediction for the departed player roll back and re-simulate as usual.\n */\n removePlayer(player: PlayerId, atFrame: number): void {\n if (player === this.localPlayer || this.dropped.has(player)) return;\n this.dropped.set(player, atFrame);\n // Inputs at/after the cutoff must never merge, even if they arrived.\n this.buffer.clearFrom(player, atFrame);\n for (let f = atFrame; f < this.world.frame; f++) {\n const used = this.usedInputs.get(f)?.get(player);\n if (used !== undefined && used !== '[]') this.earliestBad = Math.min(this.earliestBad, f);\n }\n this.settleHashes();\n }\n\n get stats(): { rollbacks: number; resimulatedFrames: number } {\n return { rollbacks: this.rollbackCount, resimulatedFrames: this.resimulatedFrames };\n }\n\n /**\n * Advance one frame: publish local input, apply any pending correction,\n * then step with confirmed-or-predicted inputs. Returns 1 unless the sim\n * has outrun its rollback window (backpressure) or is desynced.\n */\n tick(localActions: readonly string[] = []): number {\n if (this.desynced || this.overflowed) return 0;\n const f = this.world.frame;\n\n // Backpressure: never outrun the ring \u2014 a correction must always land.\n if (f - (this.confirmedFrame + 1) >= this.config.maxRollback) return 0;\n\n this.publishLocal(f, localActions);\n if (!this.resolveCorrections()) return 0;\n\n this.storeSnapshot(f);\n this.stepFrame(f);\n this.settleHashes();\n if (f % 64 === 0) this.pruneOld(f);\n return 1;\n }\n\n /** Feed real elapsed ms; runs the fixed steps the clock grants. */\n advance(realMs: number, localActions: readonly string[] = []): number {\n let stepped = 0;\n const steps = this.world.clock.advance(realMs);\n for (let i = 0; i < steps; i++) {\n if (this.tick(localActions) === 0) break;\n stepped++;\n }\n return stepped;\n }\n\n /** Merged CONFIRMED input log from frame 0 \u2014 replayable ground truth. */\n inputLog(): InputLog {\n const frames: string[][] = [];\n const through = this.confirmedFrame;\n for (let f = 0; f <= through; f++) {\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of this.players) inputs.set(p, this.buffer.get(p, f) ?? []);\n frames.push(mergePlayerFrames(this.players, inputs));\n }\n return { frames };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n\n /** Feed a raw transport message that arrived before this session existed. */\n deliver(data: string): void {\n this.receive(data);\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private publishLocal(frame: number, actions: readonly string[]): void {\n if (!this.buffer.set(this.localPlayer, frame, actions)) return;\n const from = Math.max(0, frame - this.config.redundancy + 1);\n const frames: string[][] = [];\n for (let f = from; f <= frame; f++) frames.push(this.buffer.get(this.localPlayer, f) ?? []);\n this.transport.send(encodeMessage(netMessage({ t: 'input', player: this.localPlayer, from, frames })));\n }\n\n private inputsFor(frame: number): Map<PlayerId, readonly string[]> {\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of this.players) {\n const cut = this.dropped.get(p);\n if (cut !== undefined && frame >= cut) inputs.set(p, []);\n else inputs.set(p, this.buffer.get(p, frame) ?? this.buffer.latestAt(p, frame));\n }\n return inputs;\n }\n\n private stepFrame(frame: number): void {\n const inputs = this.inputsFor(frame);\n const used = new Map<PlayerId, string>();\n for (const p of this.players) used.set(p, JSON.stringify(inputs.get(p)));\n this.usedInputs.set(frame, used);\n this.world.step(mergePlayerFrames(this.players, inputs));\n }\n\n /** Apply pending corrections. False = overflow (fatal). */\n private resolveCorrections(): boolean {\n if (this.earliestBad === Infinity) return true;\n const target = this.world.frame;\n const bad = this.earliestBad;\n this.earliestBad = Infinity;\n\n const entry = this.ring[bad % this.ring.length];\n if (!entry || entry.frame !== bad) {\n this.overflowed = true;\n this.onRollbackOverflow?.(bad);\n return false;\n }\n\n this.rollbackCount++;\n this.world.restore(entry.snap);\n this.attach?.(this.world);\n for (let f = bad; f < target; f++) {\n this.storeSnapshot(f);\n this.stepFrame(f);\n this.resimulatedFrames++;\n }\n return true;\n }\n\n private storeSnapshot(frame: number): void {\n this.ring[frame % this.ring.length] = { frame, snap: this.world.snapshot() };\n }\n\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'input' && msg.player !== this.localPlayer) {\n const cut = this.dropped.get(msg.player);\n for (let i = 0; i < msg.frames.length; i++) {\n const frame = msg.from + i;\n if (cut !== undefined && frame >= cut) continue; // post-cutoff never merges\n if (!this.buffer.set(msg.player, frame, msg.frames[i])) continue;\n // Did we already simulate this frame with a different guess?\n if (frame < this.world.frame) {\n const used = this.usedInputs.get(frame)?.get(msg.player);\n const actual = JSON.stringify([...msg.frames[i]].sort());\n if (used !== undefined && used !== actual) this.earliestBad = Math.min(this.earliestBad, frame);\n }\n }\n this.settleHashes();\n } else if (msg.t === 'hash' && msg.player !== this.localPlayer) {\n this.pendingRemoteHashes.push({ player: msg.player, frame: msg.frame, hash: msg.hash });\n this.compareHashes();\n }\n }\n\n /**\n * Hash exchange runs on CONFIRMED frames only (predicted state is\n * provisional by design). A snapshot has exactly the shape `world.hash()`\n * hashes, so ring entries give us hashes of past frames for free.\n */\n private settleHashes(): void {\n // Frames \u2264 confirmed+? \u2014 state AT frame h is confirmed once every input\n // for frames < h is known and no correction below h is pending.\n const settled = Math.min(this.confirmedFrame + 1, this.world.frame, this.earliestBad === Infinity ? Infinity : this.earliestBad);\n const interval = this.config.hashInterval;\n let h = (Math.floor(this.hashedThrough / interval) + 1) * interval;\n for (; h <= settled; h += interval) {\n const entry = this.ring[h % this.ring.length];\n if (!entry || entry.frame !== h) continue; // already recycled \u2014 skip\n const hash = hashValue(entry.snap);\n this.localHashes.set(h, hash);\n this.hashedThrough = h;\n this.transport.send(encodeMessage(netMessage({ t: 'hash', player: this.localPlayer, frame: h, hash })));\n }\n this.compareHashes();\n }\n\n private compareHashes(): void {\n const still: typeof this.pendingRemoteHashes = [];\n for (const remote of this.pendingRemoteHashes) {\n const local = this.localHashes.get(remote.frame);\n if (local === undefined) {\n if (remote.frame > this.hashedThrough - 512) still.push(remote);\n continue;\n }\n if (local !== remote.hash && !this.desynced) {\n this.desynced = true;\n this.onDesync?.({\n frame: remote.frame,\n player: remote.player,\n localHash: local,\n remoteHash: remote.hash,\n log: this.inputLog(),\n startFrame: 0,\n });\n }\n }\n this.pendingRemoteHashes = still;\n }\n\n private pruneOld(frame: number): void {\n this.buffer.prune(frame - 128);\n for (const f of this.usedInputs.keys()) if (f < frame - 128) this.usedInputs.delete(f);\n for (const f of this.localHashes.keys()) if (f < frame - 512) this.localHashes.delete(f);\n }\n}\n", "// The room layer: who is in the game, what seed it runs, when it starts.\n// Star topology over a bus transport \u2014 one endpoint is the RoomHost (assigns\n// player ids, dictates seed + session config, orchestrates late joins and\n// leaves); everyone else is a RoomClient. Both end up owning the same thing:\n// a World plus a running net session.\n//\n// Late join (lockstep only): the host schedules the newcomer at a future\n// frame, snapshots the world exactly when it reaches that frame, and ships\n// the snapshot; every peer adds the player at the same agreed frame, so all\n// rosters stay identical. Rollback rooms reject late joins \u2014 a joiner would\n// need a *confirmed* snapshot, which is future work.\n\nimport type { World, WorldSnapshot } from '../world';\nimport type { PlayerId } from './players';\nimport {\n DEFAULT_SESSION_CONFIG,\n decodeMessage,\n encodeMessage,\n netMessage,\n type NetMessage,\n type NetSessionConfig,\n} from './protocol';\nimport type { Transport } from './transport';\nimport { LockstepSession, type DesyncInfo } from './lockstep';\nimport { RollbackSession } from './rollback';\n\n/** A live networked game, the same shape on host and client. */\nexport interface NetGame {\n world: World;\n session: LockstepSession | RollbackSession;\n localPlayer: PlayerId;\n /** Roster at the time the game handle was created. */\n players: PlayerId[];\n /** Drive this from the render loop instead of world.advance(). */\n advance(realMs: number, localActions?: readonly string[]): number;\n dispose(): void;\n}\n\nexport interface RoomCallbacks {\n onDesync?: (info: DesyncInfo) => void;\n onPlayerJoin?: (player: PlayerId, atFrame: number) => void;\n onPlayerLeave?: (player: PlayerId, atFrame: number) => void;\n}\n\nfunction makeUid(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction buildSession(\n mode: NetSessionConfig['mode'],\n world: World,\n transport: Transport,\n localPlayer: PlayerId,\n players: PlayerId[],\n startFrame: number,\n config: NetSessionConfig,\n attach: ((world: World) => void) | undefined,\n callbacks: RoomCallbacks,\n): LockstepSession | RollbackSession {\n if (mode === 'rollback') {\n return new RollbackSession({ world, transport, localPlayer, players, config, attach, onDesync: callbacks.onDesync });\n }\n return new LockstepSession({ world, transport, localPlayer, players, startFrame, config, onDesync: callbacks.onDesync });\n}\n\nfunction makeGame(\n world: World,\n session: LockstepSession | RollbackSession,\n localPlayer: PlayerId,\n players: PlayerId[],\n extraDispose?: () => void,\n): NetGame {\n return {\n world,\n session,\n localPlayer,\n players,\n advance: (realMs, localActions = []) => session.advance(realMs, localActions),\n dispose: () => {\n session.dispose();\n extraDispose?.();\n },\n };\n}\n\n// \u2500\u2500 host \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RoomHostOptions extends RoomCallbacks {\n transport: Transport;\n /** Build the deterministic world every peer will run. */\n makeWorld: (seed: number) => World;\n seed?: number;\n config?: Partial<NetSessionConfig>;\n maxPlayers?: number;\n /** Frames between \"a joiner exists\" and their first live frame. */\n joinMargin?: number;\n /** Re-attach behaviors after restore (rollback / late-join snapshot). */\n attach?: (world: World) => void;\n}\n\nexport class RoomHost {\n readonly localPlayer: PlayerId = 'p1';\n readonly seed: number;\n readonly config: NetSessionConfig;\n\n private readonly transport: Transport;\n private readonly makeWorld: (seed: number) => World;\n private readonly maxPlayers: number;\n private readonly joinMargin: number;\n private readonly attach?: (world: World) => void;\n private readonly callbacks: RoomCallbacks;\n\n private players: PlayerId[] = ['p1'];\n private uidToPlayer = new Map<string, PlayerId>();\n private nextPlayerIndex = 2;\n private started = false;\n private game: NetGame | null = null;\n private pendingSnapshots: Array<{ uid: string; player: PlayerId; atFrame: number }> = [];\n private unsubscribe: () => void;\n\n constructor(opts: RoomHostOptions) {\n this.transport = opts.transport;\n this.makeWorld = opts.makeWorld;\n this.seed = opts.seed ?? 1;\n this.config = { ...DEFAULT_SESSION_CONFIG, ...opts.config };\n this.maxPlayers = opts.maxPlayers ?? 4;\n this.joinMargin = opts.joinMargin ?? 30;\n this.attach = opts.attach;\n this.callbacks = opts;\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n /** Players currently in the room (host first). */\n get roster(): PlayerId[] {\n return [...this.players];\n }\n\n get isStarted(): boolean {\n return this.started;\n }\n\n /** Freeze the roster's frame 0 and begin simulating. */\n start(): NetGame {\n if (this.game) return this.game;\n this.started = true;\n const world = this.makeWorld(this.seed);\n const session = buildSession(\n this.config.mode,\n world,\n this.transport,\n this.localPlayer,\n this.players,\n 0,\n this.config,\n this.attach,\n this.callbacks,\n );\n if (session instanceof LockstepSession) {\n session.onAfterStep((frame) => this.serviceSnapshots(frame, world));\n }\n this.transport.send(encodeMessage(netMessage({ t: 'start', players: [...this.players] })));\n this.game = makeGame(world, session, this.localPlayer, this.players, () => this.unsubscribe());\n return this.game;\n }\n\n /** Announce a player's departure (disconnect handling is the app's call). */\n dropPlayer(player: PlayerId): void {\n const session = this.game?.session;\n if (!session) return;\n // Cut at the first frame nobody can have merged yet: one past the last\n // contiguous input everyone received from the departed player. Peers on a\n // reliable bus share the same received set, so the cutoff is consistent.\n // Rollback peers may already have PREDICTED past the cutoff \u2014 that's an\n // ordinary misprediction; removePlayer rolls back and re-simulates.\n const atFrame =\n session instanceof LockstepSession\n ? Math.max(session.frame, session.confirmedFrame + 1)\n : session.lastKnownFrame(player) + 1;\n this.transport.send(encodeMessage(netMessage({ t: 'leave', player, atFrame })));\n session.removePlayer(player, atFrame);\n this.players = this.players.filter((p) => p !== player);\n this.callbacks.onPlayerLeave?.(player, atFrame);\n }\n\n dispose(): void {\n this.unsubscribe();\n this.game?.dispose();\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'hello') this.handleHello(msg);\n else if (msg.t === 'bye') {\n const player = this.uidToPlayer.get(msg.uid);\n if (player && this.started) this.dropPlayer(player);\n else if (player) {\n this.players = this.players.filter((p) => p !== player);\n this.uidToPlayer.delete(msg.uid);\n }\n }\n }\n\n private handleHello(msg: Extract<NetMessage, { t: 'hello' }>): void {\n if (this.uidToPlayer.has(msg.uid)) return; // duplicate hello \u2014 already welcomed\n if (this.players.length >= this.maxPlayers) {\n this.transport.send(encodeMessage(netMessage({ t: 'deny', to: msg.uid, reason: 'room full' })));\n return;\n }\n if (this.started && this.config.mode === 'rollback') {\n this.transport.send(encodeMessage(netMessage({ t: 'deny', to: msg.uid, reason: 'rollback rooms cannot be joined mid-game' })));\n return;\n }\n\n const player: PlayerId = `p${this.nextPlayerIndex++}`;\n this.uidToPlayer.set(msg.uid, player);\n this.players.push(player);\n\n if (!this.started) {\n this.transport.send(\n encodeMessage(\n netMessage({\n t: 'welcome',\n to: msg.uid,\n player,\n players: [...this.players],\n seed: this.seed,\n config: this.config,\n startFrame: 0,\n }),\n ),\n );\n this.callbacks.onPlayerJoin?.(player, 0);\n return;\n }\n\n // Late join: everyone (including us) adds the player at a future frame;\n // the snapshot ships when the host's world actually reaches it.\n const session = this.game!.session as LockstepSession;\n const atFrame = session.frame + this.joinMargin;\n this.transport.send(encodeMessage(netMessage({ t: 'join', player, atFrame })));\n session.addPlayer(player, atFrame);\n this.pendingSnapshots.push({ uid: msg.uid, player, atFrame });\n this.callbacks.onPlayerJoin?.(player, atFrame);\n }\n\n private serviceSnapshots(frame: number, world: World): void {\n if (this.pendingSnapshots.length === 0) return;\n const due = this.pendingSnapshots.filter((p) => p.atFrame === frame);\n if (due.length === 0) return;\n this.pendingSnapshots = this.pendingSnapshots.filter((p) => p.atFrame !== frame);\n const snapshot: WorldSnapshot = world.snapshot();\n for (const join of due) {\n // Joiners scheduled but not yet live go in `joins`, not the roster \u2014\n // the newcomer must add them at THEIR frame, not its own startFrame.\n const stillPending = this.pendingSnapshots.filter((p) => p.player !== join.player);\n const pendingIds = new Set(stillPending.map((p) => p.player));\n this.transport.send(\n encodeMessage(\n netMessage({\n t: 'welcome',\n to: join.uid,\n player: join.player,\n players: this.players.filter((p) => !pendingIds.has(p)),\n seed: this.seed,\n config: this.config,\n startFrame: frame,\n snapshot,\n joins: stillPending.map((p) => ({ player: p.player, atFrame: p.atFrame })),\n }),\n ),\n );\n }\n }\n}\n\n// \u2500\u2500 client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RoomClientOptions extends RoomCallbacks {\n transport: Transport;\n makeWorld: (seed: number) => World;\n attach?: (world: World) => void;\n name?: string;\n}\n\n/**\n * Join a room: send hello, wait for welcome (+start or snapshot), come back\n * with a NetGame. Session-layer messages that arrive while the snapshot is in\n * flight are buffered and replayed so no input is ever missed.\n */\nexport function joinRoom(opts: RoomClientOptions): Promise<NetGame> {\n const uid = makeUid();\n const transport = opts.transport;\n\n return new Promise((resolve, reject) => {\n let welcome: Extract<NetMessage, { t: 'welcome' }> | null = null;\n let started = false;\n /** Final frame-0 roster from `start` (a lobby can grow after our welcome). */\n let startRoster: PlayerId[] | null = null;\n const buffered: string[] = [];\n const pendingRoster: Array<Extract<NetMessage, { t: 'join' } | { t: 'leave' }>> = [];\n\n const finish = () => {\n if (!welcome || !started) return;\n unsub();\n const roster = startRoster ?? welcome.players;\n const world = opts.makeWorld(welcome.seed);\n if (welcome.snapshot) {\n world.restore(welcome.snapshot);\n opts.attach?.(world);\n }\n const session = buildSession(\n welcome.config.mode,\n world,\n transport,\n welcome.player,\n roster,\n welcome.startFrame,\n welcome.config,\n opts.attach,\n opts,\n );\n // Joins the host announced before our welcome (still-pending joiners):\n if (welcome.joins && session instanceof LockstepSession) {\n for (const j of welcome.joins) session.addPlayer(j.player, j.atFrame);\n }\n // Roster changes and inputs that raced past us while restoring:\n for (const m of pendingRoster) {\n if (m.t === 'join' && session instanceof LockstepSession) session.addPlayer(m.player, m.atFrame);\n if (m.t === 'leave') session.removePlayer(m.player, m.atFrame);\n }\n const roomUnsub = transport.onMessage((data) => {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'join' && session instanceof LockstepSession) {\n session.addPlayer(msg.player, msg.atFrame);\n opts.onPlayerJoin?.(msg.player, msg.atFrame);\n } else if (msg.t === 'leave') {\n session.removePlayer(msg.player, msg.atFrame);\n opts.onPlayerLeave?.(msg.player, msg.atFrame);\n }\n });\n const game = makeGame(world, session, welcome.player, roster, () => {\n roomUnsub();\n transport.send(encodeMessage(netMessage({ t: 'bye', uid })));\n });\n // Replay whatever the session missed while the snapshot was in flight.\n for (const data of buffered) session.deliver(data);\n resolve(game);\n };\n\n const unsub = transport.onMessage((data) => {\n const msg = decodeMessage(data);\n if (!msg) return;\n switch (msg.t) {\n case 'welcome':\n if (msg.to === uid) {\n welcome = msg;\n // A snapshot welcome means the game is already running.\n if (msg.snapshot || msg.startFrame > 0) started = true;\n finish();\n }\n break;\n case 'deny':\n if (msg.to === uid) {\n unsub();\n reject(new Error(`hayao-net: join denied \u2014 ${msg.reason}`));\n }\n break;\n case 'start':\n started = true;\n startRoster = msg.players;\n finish();\n break;\n case 'join':\n case 'leave':\n pendingRoster.push(msg);\n break;\n case 'input':\n case 'hash':\n buffered.push(data);\n break;\n }\n });\n\n transport.send(encodeMessage(netMessage({ t: 'hello', uid, name: opts.name })));\n });\n}\n\n/** Create a room host over a transport. Call `start()` when the lobby is set. */\nexport function hostRoom(opts: RoomHostOptions): RoomHost {\n return new RoomHost(opts);\n}\n", "// The World: the deterministic simulation container. Owns the root scene, the\n// rng, the clock, the input state, an event bus, and a resource table. Advancing\n// the world is `step()` \u2014 a pure function of (previous state, input frame).\n\nimport { Clock, type ClockConfig } from './core/clock';\nimport { EventBus } from './core/events';\nimport { hashValue } from './core/hash';\nimport { Rng } from './core/rng';\nimport { InputState } from './input/actions';\nimport { Node, resetNodeIds, type WorldContext } from './scene/node';\nimport { deserializeNode } from './scene/registry';\nimport type { Camera2D } from './scene/nodes';\nimport { IDENTITY, composeTransform, invertTransform, makeTransform, type Transform } from './core/math';\nimport type { DrawCommand } from './render/commands';\n\nexport interface WorldConfig {\n seed?: number;\n clock?: ClockConfig;\n /** Design-space dimensions (default 1280\u00D7720). */\n width?: number;\n height?: number;\n}\n\n/** Default engine event map; games extend it with their own keys. */\nexport interface CoreEvents {\n [key: string]: unknown;\n}\n\nexport class World implements WorldContext {\n readonly rng: Rng;\n readonly clock: Clock;\n readonly input = new InputState();\n readonly events = new EventBus<CoreEvents>();\n readonly resources = new Map<string, unknown>();\n /**\n * Canonical game state that lives OUTSIDE the scene tree (pure-sim structs,\n * controllers). Must be plain JSON-serializable data: it is included in\n * `hash()` and `snapshot()`, so hidden state here cannot escape determinism\n * checks the way ad-hoc module variables can.\n */\n state: Record<string, unknown> = {};\n readonly width: number;\n readonly height: number;\n\n root: Node;\n activeCamera: Camera2D | null = null;\n\n private seed: number;\n private freeQueue: Node[] = [];\n private started = false;\n\n constructor(config: WorldConfig = {}) {\n this.seed = config.seed ?? 1;\n this.rng = new Rng(this.seed);\n this.clock = new Clock(config.clock);\n this.width = config.width ?? 1280;\n this.height = config.height ?? 720;\n this.root = new Node({ name: 'root' });\n }\n\n get time(): number {\n return this.clock.simTimeSec;\n }\n get frame(): number {\n return this.clock.frame;\n }\n\n /** Replace the scene root, entering the tree. */\n setRoot(node: Node): void {\n if (this.root) this.root.exitTree();\n this.root = node;\n this.started = false;\n }\n\n requestFree(node: Node): void {\n this.freeQueue.push(node);\n }\n\n private ensureStarted(): void {\n if (!this.started) {\n this.root.enterTree(this);\n this.started = true;\n }\n }\n\n /**\n * Advance exactly one fixed step with the given actions held down.\n * This is THE deterministic transition \u2014 call it from Node or the browser loop.\n */\n step(actionsDown: Iterable<string> = []): void {\n this.ensureStarted();\n this.input.beginFrame(actionsDown);\n this.root.updateTree(this.clock.dt);\n this.flushFree();\n this.clock.tick();\n }\n\n /** Feed real elapsed ms; runs 0+ fixed steps. Returns steps run. */\n advance(realMs: number, actionsDown: Iterable<string> = []): number {\n const steps = this.clock.advance(realMs);\n for (let i = 0; i < steps; i++) this.step(actionsDown);\n return steps;\n }\n\n private flushFree(): void {\n if (this.freeQueue.length === 0) return;\n const q = this.freeQueue;\n this.freeQueue = [];\n for (const node of q) {\n node.exitTree();\n node.parent?.removeChild(node);\n if (this.activeCamera === node) this.activeCamera = null;\n }\n }\n\n // \u2500\u2500 Rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** The view transform (inverse of the active camera), mapping world \u2192 screen. */\n viewTransform(): Transform {\n if (!this.activeCamera) return IDENTITY;\n const cam = this.activeCamera;\n // Center the camera in design space, apply zoom, then invert.\n const camWorld = cam.worldTransform();\n const centered = composeTransform(makeTransform({ x: this.width / 2, y: this.height / 2 }, 0, { x: cam.zoom, y: cam.zoom }), invertTransform(camWorld));\n return centered;\n }\n\n /** Project the whole scene to a display list (already camera-applied). */\n render(): DrawCommand[] {\n this.ensureStarted();\n const out: DrawCommand[] = [];\n this.root.collectDraw(out, this.viewTransform());\n return out;\n }\n\n // \u2500\u2500 Determinism & saves \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Deterministic structural hash of the whole sim state. */\n hash(): string {\n return hashValue({\n seed: this.seed,\n rng: this.rng.getState(),\n clock: this.clock.getState(),\n input: this.input.getState(),\n state: this.state,\n tree: this.root.serialize(),\n });\n }\n\n /** Compact snapshot for undo/time-travel and saves. */\n snapshot(): WorldSnapshot {\n return {\n seed: this.seed,\n rng: this.rng.getState(),\n clock: this.clock.getState(),\n input: this.input.getState(),\n state: structuredClone(this.state),\n tree: this.root.serialize(),\n };\n }\n\n /** Restore a snapshot. Rebuilds the tree from data (behaviors are re-attached by scene code). */\n restore(snap: WorldSnapshot): void {\n this.seed = snap.seed;\n this.rng.setState(snap.rng);\n this.clock.setState(snap.clock);\n this.input.setState(snap.input);\n this.state = structuredClone(snap.state);\n resetNodeIds(1_000_000); // avoid id collisions with the live session\n this.setRoot(deserializeNode(snap.tree));\n this.ensureStarted();\n }\n\n /** A compact probe snapshot for the verification harness (override-friendly). */\n probe(): Record<string, unknown> {\n return {\n frame: this.frame,\n time: this.time,\n hash: this.hash(),\n nodes: this.root.query('Sprite').length + this.root.query('Text').length,\n };\n }\n}\n\nexport interface WorldSnapshot {\n seed: number;\n rng: ReturnType<Rng['getState']>;\n clock: ReturnType<Clock['getState']>;\n input: ReturnType<InputState['getState']>;\n state: Record<string, unknown>;\n tree: ReturnType<Node['serialize']>;\n}\n", "// The project system. A game is a data definition: dimensions, input map, and a\n// build() that constructs the initial scene tree. `createWorld` turns it into a\n// live deterministic World \u2014 used identically by the browser driver, the headless\n// runner, and every test. That symmetry is the whole point.\n\nimport { World } from '../world';\nimport type { Node } from '../scene/node';\nimport { DEFAULT_INPUT_MAP, type InputLog, type InputMap } from '../input/actions';\nimport type { ClockConfig } from '../core/clock';\n\nexport interface GameDefinition {\n title: string;\n width?: number;\n height?: number;\n seed?: number;\n background?: string;\n clock?: ClockConfig;\n inputMap?: InputMap;\n /** Build the initial scene tree for a fresh world. */\n build(world: World): Node;\n /** Optional compact probe snapshot for verification (defaults to World.probe). */\n probe?(world: World): Record<string, unknown>;\n}\n\n/** Identity + defaults. Kept as a function so games read `export default defineGame({\u2026})`. */\nexport function defineGame(def: GameDefinition): Required<Pick<GameDefinition, 'width' | 'height' | 'seed' | 'inputMap' | 'background'>> & GameDefinition {\n return {\n width: 1280,\n height: 720,\n seed: 1,\n background: '#f3ecdb',\n inputMap: DEFAULT_INPUT_MAP,\n ...def,\n };\n}\n\n/** Build a live, deterministic World from a game definition. No browser needed. */\nexport function createWorld(def: GameDefinition, seedOverride?: number): World {\n const world = new World({\n seed: seedOverride ?? def.seed ?? 1,\n width: def.width ?? 1280,\n height: def.height ?? 720,\n clock: def.clock,\n });\n world.setRoot(def.build(world));\n if (def.probe) {\n // Instance override shadows the prototype method.\n (world as unknown as { probe: () => Record<string, unknown> }).probe = () => def.probe!(world);\n }\n return world;\n}\n\n/** The input map a game uses (with defaults applied). */\nexport function gameInputMap(def: GameDefinition): InputMap {\n return def.inputMap ?? DEFAULT_INPUT_MAP;\n}\n\nexport interface HeadlessResult {\n world: World;\n hash: string;\n steps: number;\n}\n\n/**\n * Run a game to completion in Node with no host \u2014 play an input log (or zero\n * steps) and return the final world + state hash. This is what tests, the CI\n * verifier, and replays call. The browser is never involved.\n */\nexport function runHeadless(def: GameDefinition, inputLog?: InputLog): HeadlessResult {\n const world = createWorld(def);\n const frames = inputLog?.frames ?? [];\n for (const f of frames) world.step(f);\n return { world, hash: world.hash(), steps: frames.length };\n}\n", "// Browser driver for networked games \u2014 the net twin of runBrowser(). Same\n// mount/renderer/input wiring, but the world is created only after the room\n// handshake settles the seed and roster, and the RAF loop drives\n// `session.advance()` (which gates steps on network input) instead of\n// `world.advance()`.\n\nimport type { GameDefinition } from '../app/game';\nimport { createWorld } from '../app/game';\nimport { KeyboardSource } from '../input/source';\nimport { SvgRenderer } from '../render/svg';\nimport { Canvas2DRenderer } from '../render/canvas';\nimport type { Renderer } from '../render/renderer';\nimport { setOverlayHost } from '../ui/overlay';\nimport type { World } from '../world';\nimport type { Transport } from './transport';\nimport type { NetSessionConfig } from './protocol';\nimport type { NetGame, RoomCallbacks } from './room';\nimport { hostRoom, joinRoom, type RoomHost } from './room';\nimport type { PlayerId } from './players';\n\nexport interface NetRunOptions extends RoomCallbacks {\n transport: Transport;\n /** 'host' owns the lobby (first tab); 'join' connects to it. */\n role: 'host' | 'join';\n seed?: number;\n config?: Partial<NetSessionConfig>;\n maxPlayers?: number;\n /** Re-attach behaviors after any restore (rollback / late join). */\n attach?: (world: World) => void;\n renderer?: 'svg' | 'canvas';\n /** Lobby feedback (\"waiting for players\u2026\", \"connected as p2\"). */\n onStatus?: (status: string) => void;\n}\n\nexport interface NetGameHandle {\n /** Host only: freeze the lobby and start the game. No-op for joiners. */\n start(): void;\n /** The live game once running (null while in the lobby). */\n readonly game: NetGame | null;\n readonly localPlayer: PlayerId | null;\n readonly roster: PlayerId[];\n input: KeyboardSource;\n stop(): void;\n}\n\n/**\n * Run a game as a networked session. Host flow: call, wait for peers\n * (onPlayerJoin fires), then `handle.start()`. Join flow: call \u2014 the render\n * loop begins automatically when the host starts (or immediately mid-game\n * via snapshot late join).\n */\nexport function runBrowserNet(def: GameDefinition, mount: HTMLElement, opts: NetRunOptions): NetGameHandle {\n const width = def.width ?? 1280;\n const height = def.height ?? 720;\n const background = def.background ?? '#f3ecdb';\n\n const renderer: Renderer =\n opts.renderer === 'canvas'\n ? new Canvas2DRenderer({ width, height, background })\n : new SvgRenderer({ width, height, background });\n mount.style.position = mount.style.position || 'relative';\n renderer.mount?.(mount);\n setOverlayHost(mount);\n\n const input = new KeyboardSource(def.inputMap ?? {}, document);\n const makeWorld = (seed: number) => createWorld(def, seed);\n\n let game: NetGame | null = null;\n let host: RoomHost | null = null;\n let raf = 0;\n let stopped = false;\n\n const loop = (last: number) => (now: number) => {\n if (!stopped && game) {\n const stepped = game.advance(now - last, input.currentActions());\n if (stepped > 0) input.clearPressed();\n renderer.draw(game.world.render());\n }\n raf = requestAnimationFrame(loop(now));\n };\n\n const begin = (g: NetGame) => {\n game = g;\n opts.onStatus?.(`playing as ${g.localPlayer} (${g.players.length} players)`);\n raf = requestAnimationFrame(loop(performance.now()));\n };\n\n if (opts.role === 'host') {\n host = hostRoom({\n transport: opts.transport,\n makeWorld,\n seed: opts.seed ?? def.seed ?? 1,\n config: opts.config,\n maxPlayers: opts.maxPlayers,\n attach: opts.attach,\n onDesync: opts.onDesync,\n onPlayerJoin: (p, f) => {\n opts.onStatus?.(`${p} joined`);\n opts.onPlayerJoin?.(p, f);\n },\n onPlayerLeave: opts.onPlayerLeave,\n });\n opts.onStatus?.('hosting \u2014 waiting for players');\n } else {\n opts.onStatus?.('joining\u2026');\n joinRoom({\n transport: opts.transport,\n makeWorld,\n attach: opts.attach,\n onDesync: opts.onDesync,\n onPlayerJoin: opts.onPlayerJoin,\n onPlayerLeave: opts.onPlayerLeave,\n })\n .then(begin)\n .catch((err: Error) => opts.onStatus?.(err.message));\n }\n\n return {\n start() {\n if (host && !game) begin(host.start());\n },\n get game() {\n return game;\n },\n get localPlayer() {\n return game?.localPlayer ?? (opts.role === 'host' ? 'p1' : null);\n },\n get roster() {\n return host?.roster ?? game?.players ?? [];\n },\n input,\n stop() {\n stopped = true;\n cancelAnimationFrame(raf);\n game?.dispose();\n host?.dispose();\n input.dispose();\n renderer.dispose?.();\n },\n };\n}\n", "// Browser driver: mounts a renderer, samples real input into the fixed-step\n// kernel, projects to the renderer each frame, and wires audio + the pause shell.\n// Wall-clock only feeds the accumulator (how many steps to run) \u2014 replays use the\n// input log, not wall time, so the sim stays deterministic.\n\nimport type { GameDefinition } from './game';\nimport { createWorld } from './game';\nimport { KeyboardSource } from '../input/source';\nimport { SvgRenderer } from '../render/svg';\nimport { Canvas2DRenderer } from '../render/canvas';\nimport type { Renderer } from '../render/renderer';\nimport { renderToSVGString } from '../render/svgString';\nimport { audio } from '../audio/audio';\nimport { settings } from '../ui/settings';\nimport { setOverlayHost } from '../ui/overlay';\nimport { Shell } from '../ui/shell';\nimport { installCapture, isCaptureMode } from '../verify/capture';\nimport type { World } from '../world';\n\nexport interface RunOptions {\n renderer?: 'svg' | 'canvas';\n /** Start the pause/settings shell (Esc). Default true. */\n shell?: boolean;\n onRestart?: () => void;\n}\n\nexport interface GameHandle {\n world: World;\n renderer: Renderer;\n /** The live input source \u2014 game UI calls input.press('action') for buttons. */\n input: KeyboardSource;\n stop(): void;\n restart(): void;\n}\n\nexport function runBrowser(def: GameDefinition, mount: HTMLElement, opts: RunOptions = {}): GameHandle {\n const width = def.width ?? 1280;\n const height = def.height ?? 720;\n const background = def.background ?? '#f3ecdb';\n\n let world = createWorld(def);\n const renderer: Renderer =\n opts.renderer === 'canvas'\n ? new Canvas2DRenderer({ width, height, background })\n : new SvgRenderer({ width, height, background });\n\n mount.style.position = mount.style.position || 'relative';\n renderer.mount?.(mount);\n setOverlayHost(mount);\n\n const input = new KeyboardSource(def.inputMap ?? {}, document);\n const capture = isCaptureMode();\n\n // Start audio on first user gesture (autoplay policy).\n const startAudio = () => {\n audio.start();\n const s = settings.get();\n audio.setVolumes(s);\n window.removeEventListener('pointerdown', startAudio);\n window.removeEventListener('keydown', startAudio);\n };\n window.addEventListener('pointerdown', startAudio);\n window.addEventListener('keydown', startAudio);\n\n const renderFrame = () => renderer.draw(world.render());\n const restart = () => {\n world = createWorld(def);\n renderFrame();\n };\n\n const shell =\n opts.shell === false\n ? null\n : new Shell({\n title: def.title,\n onRestart: opts.onRestart ?? restart,\n onPause: () => {},\n });\n\n let raf = 0;\n let last = performance.now();\n const loop = (now: number) => {\n const dt = now - last;\n last = now;\n if (!capture && !(shell?.isPaused)) {\n const steps = world.advance(dt, input.currentActions());\n if (steps > 0) input.clearPressed(); // virtual taps held until sampled\n }\n renderFrame();\n raf = requestAnimationFrame(loop);\n };\n raf = requestAnimationFrame(loop);\n\n const handle: GameHandle = {\n get world() {\n return world;\n },\n renderer,\n input,\n stop() {\n cancelAnimationFrame(raf);\n input.dispose();\n shell?.dispose();\n renderer.dispose?.();\n },\n restart,\n };\n\n if (capture) {\n installCapture({\n get world() {\n return world;\n },\n stepOnce: (actions = []) => {\n world.step(actions);\n renderFrame();\n },\n renderSVG: () => renderToSVGString(world.render(), width, height, background),\n setPaused: () => {},\n });\n }\n\n return handle;\n}\n", "// @hayao \u2014 the single public seam. Games and examples import ONLY from here.\n// Everything below the barrel is swappable; this file is the whole API surface,\n// greppable in one place (an AI-first invariant).\n\n// \u2500\u2500 core: the deterministic kernel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './core/math';\nexport * from './core/dmath';\nexport * from './core/rng';\nexport * from './core/clock';\nexport * from './core/events';\nexport * from './core/hash';\n\n// \u2500\u2500 scene: the Godot-style node tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './scene/node';\n// Node2D is an alias for Node \u2014 the base node already carries a 2D transform.\nexport { Node as Node2D } from './scene/node';\nexport * from './scene/nodes';\nexport * from './scene/pool';\nexport * from './scene/tween';\nexport * from './scene/particles';\nexport * from './scene/floatingText';\nexport * from './scene/registry';\n\n// \u2500\u2500 input: actions, sampling, record/replay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './input/actions';\nexport * from './input/source';\n\n// \u2500\u2500 physics: tilemaps, kinematic AABB, character controllers \u2500\u2500\u2500\u2500\nexport * from './physics/tilemap';\nexport * from './physics/aabb';\nexport * from './physics/platformer';\nexport * from './physics/spatialHash';\nexport * from './physics/raycast';\n// \u2500\u2500 physics: rigid-body dynamics (plain-data world \u2192 hash/snapshot free) \u2500\nexport * from './physics/rigidBody';\nexport * from './physics/rigidCollide';\nexport * from './physics/rigidJoints';\nexport * from './physics/rigidStep';\nexport * from './physics/rigidQueries';\n\n// \u2500\u2500 render: display list + backends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './render/commands';\nexport * from './render/renderer';\nexport * from './render/svgString';\nexport * from './render/svg';\nexport * from './render/canvas';\nexport * from './render/headless';\nexport * from './render/nineSlice';\n\n// \u2500\u2500 art: code-as-art helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './art/palette';\nexport * from './art/shapes';\nexport * from './art/texture';\nexport * from './art/font5';\nexport * from './art/bitmapFont';\nexport * from './art/autotile';\n\n// \u2500\u2500 procgen: deterministic generators + stateless scatter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './procgen/grid';\nexport * from './procgen/scatter';\nexport * from './procgen/cave';\nexport * from './procgen/terrain';\nexport * from './procgen/rooms';\n\n// \u2500\u2500 audio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './audio/audio';\n\n// \u2500\u2500 ui: DOM overlays + shell + settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './ui/overlay';\nexport * from './ui/settings';\nexport * from './ui/shell';\nexport * from './ui/transition';\n\n// \u2500\u2500 verify: the AI-first harness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './verify/solver';\nexport * from './verify/determinism';\nexport * from './verify/playthrough';\nexport * from './verify/capture';\nexport * from './verify/driver';\nexport * from './verify/bot';\nexport * from './verify/layout';\nexport * from './verify/feel';\nexport * from './verify/filmstrip';\n\n// \u2500\u2500 logic: pure engine primitives (FSM, weighted tables, graph search) \u2500\nexport * from './logic/fsm';\nexport * from './logic/random';\nexport * from './logic/graph';\nexport * from './logic/history';\n\n// \u2500\u2500 persist: save/load over a pluggable storage adapter + compact codecs \u2500\nexport * from './persist/storage';\nexport * from './persist/codec';\nexport * from './persist/save';\n\n// \u2500\u2500 content: data-driven wave/spawn directors + upgrade trees \u2500\u2500\u2500\nexport * from './content/dsl';\n\n// \u2500\u2500 net: deterministic multiplayer (lockstep / rollback) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './net/players';\nexport * from './net/protocol';\nexport * from './net/transport';\nexport * from './net/inputBuffer';\nexport * from './net/lockstep';\nexport * from './net/rollback';\nexport * from './net/room';\nexport * from './net/browser';\n\n// \u2500\u2500 world + app \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './world';\nexport * from './app/game';\nexport * from './app/browser';\n\n/** Engine version. */\nexport const VERSION = '0.2.0';\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["n", "n", "n", "mix", "n", "n", "at", "at", "dx", "dy", "n", "area", "n", "m", "i", "n", "k", "j", "ex", "ey", "nx", "ny", "vax", "vay", "vbx", "vby", "ix", "iy", "warm", "n", "n", "r", "n", "n", "n", "n", "n", "n", "smoothstep", "n", "hold", "overlaps", "n", "n", "n", "n", "active", "host"]
|
|
3
|
+
"sources": ["../src/core/dmath.ts", "../src/core/math.ts", "../src/core/projection.ts", "../src/core/rng.ts", "../src/core/clock.ts", "../src/core/events.ts", "../src/core/hash.ts", "../src/scene/node.ts", "../src/scene/nodes.ts", "../src/scene/iso.ts", "../src/scene/cameraController.ts", "../src/scene/parallax.ts", "../src/scene/pool.ts", "../src/scene/tween.ts", "../src/scene/particles.ts", "../src/scene/floatingText.ts", "../src/scene/verletChain.ts", "../src/scene/registry.ts", "../src/input/actions.ts", "../src/input/source.ts", "../src/input/gamepad.ts", "../src/physics/tilemap.ts", "../src/physics/aabb.ts", "../src/physics/platformer.ts", "../src/physics/spatialHash.ts", "../src/physics/raycast.ts", "../src/physics/rigidBody.ts", "../src/physics/rigidCollide.ts", "../src/physics/rigidJoints.ts", "../src/physics/rigidStep.ts", "../src/physics/rigidQueries.ts", "../src/render/commands.ts", "../src/render/paint.ts", "../src/render/renderer.ts", "../src/render/svgString.ts", "../src/render/svg.ts", "../src/render/canvas2d-core.ts", "../src/render/canvas.ts", "../src/render/webgl.ts", "../src/render/headless.ts", "../src/render/nineSlice.ts", "../src/art/palette.ts", "../src/art/shapes.ts", "../src/art/texture.ts", "../src/art/font5.ts", "../src/art/bitmapFont.ts", "../src/art/autotile.ts", "../src/procgen/grid.ts", "../src/procgen/scatter.ts", "../src/procgen/cave.ts", "../src/procgen/terrain.ts", "../src/procgen/rooms.ts", "../src/audio/pcm.ts", "../src/audio/synth.ts", "../src/audio/theory.ts", "../src/audio/reverb.ts", "../src/audio/music.ts", "../src/audio/audio.ts", "../src/audio/analysis.ts", "../src/audio/chord.ts", "../src/audio/lint.ts", "../src/audio/match.ts", "../src/audio/adaptive.ts", "../src/audio/quality.ts", "../src/audio/genres.ts", "../src/audio/zzfx.ts", "../src/audio/album.ts", "../src/ui/overlay.ts", "../src/ui/settings.ts", "../src/ui/shell.ts", "../src/ui/touch.ts", "../src/ui/transition.ts", "../src/verify/solver.ts", "../src/verify/determinism.ts", "../src/verify/playthrough.ts", "../src/verify/capture.ts", "../src/verify/driver.ts", "../src/verify/bot.ts", "../src/verify/gates.ts", "../src/verify/layout.ts", "../src/verify/feel.ts", "../src/verify/ramp.ts", "../src/verify/filmstrip.ts", "../src/verify/audioFilmstrip.ts", "../src/world.ts", "../src/app/tuning.ts", "../src/app/game.ts", "../src/studio/session.ts", "../src/verify/ethnography.ts", "../src/app/browser.ts", "../src/verify/dom.ts", "../src/logic/fsm.ts", "../src/logic/coroutine.ts", "../src/logic/random.ts", "../src/logic/graph.ts", "../src/logic/history.ts", "../src/persist/storage.ts", "../src/persist/codec.ts", "../src/persist/save.ts", "../src/content/dsl.ts", "../src/content/level.ts", "../src/content/generate.ts", "../src/content/campaign.ts", "../src/content/worldgraph.ts", "../src/net/players.ts", "../src/net/protocol.ts", "../src/net/transport.ts", "../src/net/inputBuffer.ts", "../src/net/lockstep.ts", "../src/net/rollback.ts", "../src/net/room.ts", "../src/net/browser.ts", "../src/studio/record.ts", "../src/studio/timeline.ts", "../src/studio/run.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["// Deterministic transcendental math. JavaScript guarantees bit-exact results\n// across engines for +, -, *, /, Math.sqrt (IEEE-754 correctly rounded) \u2014 but\n// NOT for Math.sin/cos/atan2/pow/hypot/exp, which are implementation-defined\n// and may differ between V8, JSC, and SpiderMonkey. A cross-machine lockstep\n// game that touches them can desync even with identical input logs.\n//\n// These replacements are built from exactly-rounded ops only (fdlibm-style\n// polynomial kernels), so every engine computes bit-identical values. Sim code\n// MUST use these instead of the Math.* originals (enforced by\n// `npm run invariants`). Accuracy \u2248 1 ulp on game-scale inputs.\n\n// \u2500\u2500 argument reduction constants (\u03C0/2 split for Cody-Waite reduction) \u2500\u2500\nconst INV_PIO2 = 6.36619772367581382433e-1; // 2/\u03C0\nconst PIO2_HI = 1.57079632673412561417e0; // first 33 bits of \u03C0/2\nconst PIO2_LO = 6.07710050650619224932e-11; // \u03C0/2 \u2212 PIO2_HI\n\n// fdlibm kernel coefficients for sin/cos on |r| \u2264 \u03C0/4.\nconst S1 = -1.66666666666666324348e-1;\nconst S2 = 8.33333333332248946124e-3;\nconst S3 = -1.98412698298579493134e-4;\nconst S4 = 2.75573137070700676789e-6;\nconst S5 = -2.50507602534068634195e-8;\nconst S6 = 1.58969099521155010221e-10;\n\nconst C1 = 4.16666666666666019037e-2;\nconst C2 = -1.38888888888741095749e-3;\nconst C3 = 2.48015872894767294178e-5;\nconst C4 = -2.75573143513906633035e-7;\nconst C5 = 2.08757232129817482790e-9;\nconst C6 = -1.13596475577881948265e-11;\n\nfunction kSin(r: number): number {\n const z = r * r;\n return r + r * z * (S1 + z * (S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)))));\n}\n\nfunction kCos(r: number): number {\n const z = r * r;\n return 1 - 0.5 * z + z * z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));\n}\n\n/** Reduce x to r \u2208 [\u2212\u03C0/4, \u03C0/4] and quadrant n. Accurate for |x| \u2272 1e7 (plenty for game angles). */\nfunction reduce(x: number): { n: number; r: number } {\n const n = Math.round(x * INV_PIO2);\n const r = x - n * PIO2_HI - n * PIO2_LO;\n return { n: ((n % 4) + 4) % 4, r };\n}\n\n/** Deterministic sine (bit-identical on every JS engine). */\nexport function dsin(x: number): number {\n if (!Number.isFinite(x)) return NaN;\n const { n, r } = reduce(x);\n switch (n) {\n case 0:\n return kSin(r);\n case 1:\n return kCos(r);\n case 2:\n return -kSin(r);\n default:\n return -kCos(r);\n }\n}\n\n/** Deterministic cosine (bit-identical on every JS engine). */\nexport function dcos(x: number): number {\n if (!Number.isFinite(x)) return NaN;\n const { n, r } = reduce(x);\n switch (n) {\n case 0:\n return kCos(r);\n case 1:\n return -kSin(r);\n case 2:\n return -kCos(r);\n default:\n return kSin(r);\n }\n}\n\n// \u2500\u2500 atan / atan2 (fdlibm port) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ATAN_HI = [4.63647609000806093515e-1, 7.85398163397448278999e-1, 9.82793723247329054082e-1, 1.570796326794896558e0];\nconst ATAN_LO = [2.26987774529616870924e-17, 3.06161699786838301793e-17, 1.39033110312309984516e-17, 6.12323399573676603587e-17];\nconst AT = [\n 3.33333333333329318027e-1, -1.99999999998764832476e-1, 1.42857142725034663711e-1, -1.1111110405462355788e-1,\n 9.09088713343650656196e-2, -7.69187620504482999495e-2, 6.66107313738753120669e-2, -5.83357013379057348645e-2,\n 4.97687799461593236017e-2, -3.6531572744216915527e-2, 1.62858201153657823623e-2,\n];\n\n/** Deterministic arctangent. */\nexport function datan(x: number): number {\n if (Number.isNaN(x)) return NaN;\n if (!Number.isFinite(x)) return x > 0 ? ATAN_HI[3] : -ATAN_HI[3];\n const sign = x < 0 || Object.is(x, -0) ? -1 : 1;\n let ax = Math.abs(x);\n if (ax >= 1e19) return sign * (ATAN_HI[3] + ATAN_LO[3]);\n\n let id = -1;\n if (ax < 0.4375) {\n if (ax < 1e-9) return x; // tiny: atan(x) \u2248 x\n } else if (ax < 0.6875) {\n id = 0;\n ax = (2 * ax - 1) / (2 + ax);\n } else if (ax < 1.1875) {\n id = 1;\n ax = (ax - 1) / (ax + 1);\n } else if (ax < 2.4375) {\n id = 2;\n ax = (ax - 1.5) / (1 + 1.5 * ax);\n } else {\n id = 3;\n ax = -1 / ax;\n }\n\n const z = ax * ax;\n const w = z * z;\n const s1 = z * (AT[0] + w * (AT[2] + w * (AT[4] + w * (AT[6] + w * (AT[8] + w * AT[10])))));\n const s2 = w * (AT[1] + w * (AT[3] + w * (AT[5] + w * (AT[7] + w * AT[9]))));\n if (id < 0) return sign * (ax - ax * (s1 + s2));\n const r = ATAN_HI[id] - (ax * (s1 + s2) - ATAN_LO[id] - ax);\n return sign * r;\n}\n\nconst PI = 3.141592653589793;\n\n/** Deterministic atan2(y, x) with standard quadrant conventions. */\nexport function datan2(y: number, x: number): number {\n if (Number.isNaN(x) || Number.isNaN(y)) return NaN;\n if (y === 0 && x === 0) return Object.is(x, -0) ? (Object.is(y, -0) ? -PI : PI) : Object.is(y, -0) ? -0 : 0;\n if (x === 0 || (!Number.isFinite(y) && Number.isFinite(x))) return y > 0 ? PI / 2 : -PI / 2;\n if (!Number.isFinite(x)) {\n if (!Number.isFinite(y)) {\n const q = x > 0 ? PI / 4 : (3 * PI) / 4;\n return y > 0 ? q : -q;\n }\n return x > 0 ? (y < 0 || Object.is(y, -0) ? -0 : 0) : y < 0 || Object.is(y, -0) ? -PI : PI;\n }\n const a = datan(y / x);\n if (x > 0) return a;\n return y < 0 || Object.is(y, -0) ? a - PI : a + PI;\n}\n\n// \u2500\u2500 exp2 (for easing curves and decay) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst LN2 = 6.93147180559945286227e-1;\n\n/** Deterministic 2^x via Taylor series on the reduced argument. */\nexport function dexp2(x: number): number {\n if (Number.isNaN(x)) return NaN;\n if (x >= 1024) return Infinity;\n if (x <= -1075) return 0;\n const k = Math.round(x);\n const y = (x - k) * LN2; // |y| \u2264 ln2/2 \u2248 0.347\n let term = 1;\n let sum = 1;\n for (let i = 1; i <= 13; i++) {\n term = (term * y) / i;\n sum += term;\n }\n return sum * 2 ** k; // 2^integer is exact in every engine\n}\n\n/** Deterministic natural exponential e\u02E3. Routes through dexp2 (e\u02E3 = 2^(x/ln2)). */\nexport function dexp(x: number): number {\n return dexp2(x * INV_LN2);\n}\n\n/** Deterministic hypotenuse: sqrt is IEEE-correctly-rounded, hypot is not. */\nexport function dhypot(x: number, y: number): number {\n return Math.sqrt(x * x + y * y);\n}\n\n// \u2500\u2500 logarithms \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Decompose x = m\u00B72^e with the exponent read straight from the float bits\n// (bit-exact everywhere), then ln(m) on m \u2208 [\u221A\u00BD\u00B72, \u221A2) via the atanh series\n// ln(m) = 2\u00B7atanh((m\u22121)/(m+1)) \u2014 only exactly-rounded ops.\nconst logView = new DataView(new ArrayBuffer(8));\nconst LN2_HI = 6.93147180369123816490e-1;\nconst LN2_LO = 1.90821492927058770002e-10;\n\n/** Deterministic natural logarithm. */\nexport function dlog(x: number): number {\n if (Number.isNaN(x) || x < 0) return NaN;\n if (x === 0) return -Infinity;\n if (!Number.isFinite(x)) return Infinity;\n logView.setFloat64(0, x);\n let e = ((logView.getUint32(0) >>> 20) & 0x7ff) - 1023;\n if (e === -1023) {\n // subnormal: scale up by 2^54 (exact) and correct the exponent\n logView.setFloat64(0, x * 18014398509481984);\n e = ((logView.getUint32(0) >>> 20) & 0x7ff) - 1023 - 54;\n }\n // mantissa m \u2208 [1, 2); shift to [\u221A\u00BD\u00B72, \u221A2) so |s| stays small\n logView.setUint32(0, (logView.getUint32(0) & 0xfffff) | (1023 << 20));\n let m = logView.getFloat64(0);\n if (m > 1.4142135623730951) {\n m *= 0.5;\n e += 1;\n }\n const s = (m - 1) / (m + 1);\n const z = s * s;\n // 2\u00B7atanh(s) = 2s\u00B7(1 + z/3 + z\u00B2/5 + \u2026) \u2014 terms through z\u2079/19 keep the\n // truncation below 1 ulp for |s| \u2264 0.172\n const p =\n 1 +\n z *\n (0.3333333333333333 +\n z *\n (0.2 +\n z *\n (0.14285714285714285 +\n z *\n (0.1111111111111111 +\n z *\n (0.09090909090909091 +\n z * (0.07692307692307693 + z * (0.06666666666666667 + z * (0.058823529411764705 + z * 0.05263157894736842))))))));\n return e * LN2_HI + (2 * s * p + e * LN2_LO);\n}\n\nconst INV_LN10 = 4.34294481903251816668e-1; // 1/ln(10)\nconst INV_LN2 = 1.44269504088896338700e0; // 1/ln(2)\n\n/** Deterministic base-10 logarithm. */\nexport const dlog10 = (x: number): number => dlog(x) * INV_LN10;\n/** Deterministic base-2 logarithm. */\nexport const dlog2 = (x: number): number => dlog(x) * INV_LN2;\n\n// \u2500\u2500 power \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Math.pow is implementation-defined and banned in the sim. This is the one\n// sanctioned replacement (four subsystems used to hand-roll it privately).\n// Integer exponents run an exact multiply chain \u2014 bit-identical everywhere and\n// valid for negative bases; other cases route through dexp2(exp\u00B7dlog2(base)).\n\n/** Deterministic base^exp (bit-identical across JS engines). */\nexport function dpow(base: number, exp: number): number {\n if (Number.isNaN(base) || Number.isNaN(exp)) return NaN;\n if (exp === 0) return 1; // includes 0^0 = 1, matching Math.pow\n if (exp === 1) return base;\n // Exact path for integer exponents: repeated squaring on |exp|, bit-exact and\n // the only route that stays valid for a negative base.\n if (Number.isInteger(exp) && Math.abs(exp) <= 1024) {\n let n = Math.abs(exp);\n let b = base;\n let r = 1;\n while (n > 0) {\n if (n & 1) r *= b;\n n >>= 1;\n if (n > 0) b *= b;\n }\n return exp < 0 ? 1 / r : r;\n }\n if (base > 0) return dexp2(exp * dlog2(base));\n if (base === 0) return exp > 0 ? 0 : Infinity;\n return NaN; // negative base, non-integer exponent \u2192 complex \u2192 NaN (like Math.pow)\n}\n", "// Deterministic 2D math. Plain data + pure functions (no classes with hidden\n// state) so everything serializes and hashes cleanly. Trig/hypot route through\n// dmath so results are bit-identical across JS engines (netplay-safe).\n\nimport { dcos, dhypot, dsin } from './dmath';\n\nexport interface Vec2 {\n x: number;\n y: number;\n}\n\nexport const vec2 = (x = 0, y = 0): Vec2 => ({ x, y });\nexport const vadd = (a: Vec2, b: Vec2): Vec2 => ({ x: a.x + b.x, y: a.y + b.y });\nexport const vsub = (a: Vec2, b: Vec2): Vec2 => ({ x: a.x - b.x, y: a.y - b.y });\nexport const vscale = (a: Vec2, s: number): Vec2 => ({ x: a.x * s, y: a.y * s });\nexport const vdot = (a: Vec2, b: Vec2): number => a.x * b.x + a.y * b.y;\nexport const vlen = (a: Vec2): number => dhypot(a.x, a.y);\nexport const vdist = (a: Vec2, b: Vec2): number => dhypot(a.x - b.x, a.y - b.y);\nexport function vnorm(a: Vec2): Vec2 {\n const l = vlen(a);\n return l === 0 ? { x: 0, y: 0 } : { x: a.x / l, y: a.y / l };\n}\n\nexport const clamp = (v: number, lo: number, hi: number): number => (v < lo ? lo : v > hi ? hi : v);\nexport const lerp = (a: number, b: number, t: number): number => a + (b - a) * t;\nexport const invLerp = (a: number, b: number, v: number): number => (a === b ? 0 : (v - a) / (b - a));\nexport const remap = (v: number, a0: number, a1: number, b0: number, b1: number): number =>\n lerp(b0, b1, invLerp(a0, a1, v));\n\n/** Hermite smoothstep: 0 below `edge0`, 1 above `edge1`, eased in between. */\nexport const smoothstep = (edge0: number, edge1: number, v: number): number => {\n const t = clamp(edge0 === edge1 ? (v < edge0 ? 0 : 1) : invLerp(edge0, edge1, v), 0, 1);\n return t * t * (3 - 2 * t);\n};\n\nexport const TAU = Math.PI * 2;\nexport const deg2rad = (d: number): number => (d * Math.PI) / 180;\nexport const rad2deg = (r: number): number => (r * 180) / Math.PI;\n\n/** Axis-aligned rectangle. */\nexport interface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport function rectContains(r: Rect, p: Vec2): boolean {\n return p.x >= r.x && p.x <= r.x + r.w && p.y >= r.y && p.y <= r.y + r.h;\n}\n\nexport function rectsOverlap(a: Rect, b: Rect): boolean {\n return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n}\n\n/** 2D affine transform as a 6-value matrix [a b c d e f] (like SVG/Canvas). */\nexport interface Transform {\n a: number;\n b: number;\n c: number;\n d: number;\n e: number;\n f: number;\n}\n\nexport const IDENTITY: Transform = { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };\n\nexport function composeTransform(m: Transform, n: Transform): Transform {\n return {\n a: m.a * n.a + m.c * n.b,\n b: m.b * n.a + m.d * n.b,\n c: m.a * n.c + m.c * n.d,\n d: m.b * n.c + m.d * n.d,\n e: m.a * n.e + m.c * n.f + m.e,\n f: m.b * n.e + m.d * n.f + m.f,\n };\n}\n\n/** Build a transform from position, rotation (radians), scale. */\nexport function makeTransform(pos: Vec2, rotation: number, scale: Vec2): Transform {\n const cos = dcos(rotation);\n const sin = dsin(rotation);\n return {\n a: cos * scale.x,\n b: sin * scale.x,\n c: -sin * scale.y,\n d: cos * scale.y,\n e: pos.x,\n f: pos.y,\n };\n}\n\nexport function applyTransform(m: Transform, p: Vec2): Vec2 {\n return { x: m.a * p.x + m.c * p.y + m.e, y: m.b * p.x + m.d * p.y + m.f };\n}\n\n/** Invert an affine transform (returns identity if singular). */\nexport function invertTransform(m: Transform): Transform {\n const det = m.a * m.d - m.b * m.c;\n if (det === 0) return { ...IDENTITY };\n const id = 1 / det;\n return {\n a: m.d * id,\n b: -m.b * id,\n c: -m.c * id,\n d: m.a * id,\n e: (m.c * m.f - m.d * m.e) * id,\n f: (m.b * m.e - m.a * m.f) * id,\n };\n}\n", "// Lattice projections: turn integer grid coordinates into screen positions and\n// back. Plain data + pure functions (house style) and fully linear \u2014 no trig \u2014\n// so the forward/inverse maps are bit-exact and hash-safe if used in the sim.\n//\n// The 2.5D corpus kept re-deriving the 2:1 iso forward map and, worse, its\n// inverse (needed to turn a pointer into a tile coord). `World.screenToWorld()`\n// only inverts the camera affine; it has no notion of a tile lattice. `iso()`\n// owns that lattice math in one deterministic place.\n\nimport type { Vec2 } from './math';\n\nexport interface IsoConfig {\n /** Full width of a tile diamond in screen px (the horizontal diagonal). */\n tileW: number;\n /** Full height of a tile diamond in screen px (the vertical diagonal). 2:1 iso \u21D2 tileW/2. */\n tileH: number;\n /** Screen px where grid cell (0,0)'s CENTER lands. Default (0,0). */\n origin?: Vec2;\n /** Screen px a tile rises per unit of elevation. Default tileH (one tile-height per level). */\n elevStep?: number;\n}\n\n/**\n * A parameterised grid\u2194screen projection. `toScreen` places a (possibly raised)\n * cell centre; `toGrid` inverts the ground plane (elev 0) to FRACTIONAL grid\n * coordinates \u2014 floor them for the containing tile. Round-trips exactly for\n * every integer cell. Covers 2:1 iso (tileH = tileW/2), true dimetric, and\n * top-down/oblique (tileH = tileW) by choice of tile size.\n */\nexport interface IsoProjection {\n readonly tileW: number;\n readonly tileH: number;\n readonly origin: Vec2;\n readonly elevStep: number;\n /** Grid cell \u2192 screen-space centre. `elev` shifts the point up by `elevStep` per unit. */\n toScreen(gx: number, gy: number, elev?: number): Vec2;\n /** Screen point \u2192 fractional grid coords on the ground plane (floor for the tile). */\n toGrid(sx: number, sy: number): Vec2;\n}\n\n/**\n * Build an isometric/dimetric/oblique projection. Diamond lattice:\n * screenX = origin.x + (gx - gy) \u00B7 tileW/2\n * screenY = origin.y + (gx + gy) \u00B7 tileH/2 \u2212 elev \u00B7 elevStep\n * The inverse solves the 2\u00D72 system directly, so `toGrid(toScreen(g)) === g` for\n * all integer cells (no accumulated float drift).\n */\nexport function iso(cfg: IsoConfig): IsoProjection {\n const { tileW, tileH } = cfg;\n const origin: Vec2 = cfg.origin ? { x: cfg.origin.x, y: cfg.origin.y } : { x: 0, y: 0 };\n const elevStep = cfg.elevStep ?? tileH;\n const hw = tileW / 2;\n const hh = tileH / 2;\n return {\n tileW,\n tileH,\n origin,\n elevStep,\n toScreen(gx, gy, elev = 0) {\n return {\n x: origin.x + (gx - gy) * hw,\n y: origin.y + (gx + gy) * hh - elev * elevStep,\n };\n },\n toGrid(sx, sy) {\n const dx = (sx - origin.x) / hw; // = gx - gy\n const dy = (sy - origin.y) / hh; // = gx + gy\n return { x: (dx + dy) / 2, y: (dy - dx) / 2 };\n },\n };\n}\n", "// Deterministic, seedable, splittable RNG. SplitMix64 for seeding, xoshiro128**\n// for the stream \u2014 fast, good distribution, trivially reproducible.\n// Every random draw in a game MUST flow through here (never Math.random()).\n\nfunction splitmix32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x9e3779b9) >>> 0;\n let t = a;\n t = Math.imul(t ^ (t >>> 16), 0x21f0aaad);\n t = Math.imul(t ^ (t >>> 15), 0x735a2d97);\n return (t ^ (t >>> 15)) >>> 0;\n };\n}\n\nexport interface RngState {\n s: [number, number, number, number];\n}\n\nexport class Rng {\n private s0: number;\n private s1: number;\n private s2: number;\n private s3: number;\n\n constructor(seed: number | RngState = 0) {\n if (typeof seed === 'number') {\n const sm = splitmix32(seed === 0 ? 0x1234abcd : seed);\n this.s0 = sm();\n this.s1 = sm();\n this.s2 = sm();\n this.s3 = sm();\n } else {\n [this.s0, this.s1, this.s2, this.s3] = seed.s;\n }\n }\n\n /** Raw 32-bit unsigned integer. */\n private next(): number {\n const result = (Math.imul(this.rotl(Math.imul(this.s1, 5), 7), 9) >>> 0);\n const t = (this.s1 << 9) >>> 0;\n this.s2 ^= this.s0;\n this.s3 ^= this.s1;\n this.s1 ^= this.s2;\n this.s0 ^= this.s3;\n this.s2 = (this.s2 ^ t) >>> 0;\n this.s3 = this.rotl(this.s3, 11);\n return result >>> 0;\n }\n\n private rotl(x: number, k: number): number {\n return (((x << k) | (x >>> (32 - k))) >>> 0);\n }\n\n /** Float in [0, 1). */\n float(): number {\n return this.next() / 4294967296;\n }\n\n /** Float in [lo, hi). */\n range(lo: number, hi: number): number {\n return lo + this.float() * (hi - lo);\n }\n\n /** Integer in [0, n). */\n int(n: number): number {\n return Math.floor(this.float() * n);\n }\n\n /** Integer in [lo, hi] inclusive. */\n intRange(lo: number, hi: number): number {\n return lo + this.int(hi - lo + 1);\n }\n\n /** True with probability p. */\n chance(p: number): boolean {\n return this.float() < p;\n }\n\n /** Uniform element of an array. */\n pick<T>(arr: readonly T[]): T {\n return arr[this.int(arr.length)];\n }\n\n /** In-place Fisher\u2013Yates shuffle (deterministic). */\n shuffle<T>(arr: T[]): T[] {\n for (let i = arr.length - 1; i > 0; i--) {\n const j = this.int(i + 1);\n [arr[i], arr[j]] = [arr[j], arr[i]];\n }\n return arr;\n }\n\n /**\n * Derive an independent child stream. Same parent state + same key always\n * yields the same child \u2014 so subsystems (enemy AI, loot, terrain) get stable,\n * decorrelated randomness without threading one generator through everything.\n */\n split(key = 0): Rng {\n const mix = (this.s0 ^ Math.imul(key + 1, 0x9e3779b9)) >>> 0;\n const child = new Rng(mix ^ this.s3);\n // Advance parent so repeated splits differ.\n this.next();\n return child;\n }\n\n /** Serialize / restore for saves and replay. */\n getState(): RngState {\n return { s: [this.s0, this.s1, this.s2, this.s3] };\n }\n setState(state: RngState): void {\n [this.s0, this.s1, this.s2, this.s3] = state.s;\n }\n}\n\n// Scratch view for hashNoise: lets us hash the exact float bits (not a lossy\n// truncation), so 0.1 and 0.100001 land on different values. Write-before-read\n// every call, so it carries no state.\nconst __noiseBits = new DataView(new ArrayBuffer(8));\n\n/**\n * Stateless deterministic noise: hash any mix of numbers to a float in [0,1).\n * Same inputs ALWAYS give the same output and no stream is consumed, so it is\n * safe to call from `draw()` for per-entity cosmetic variation (jitter, phase\n * offsets, hue nudges) \u2014 `hashNoise(entity.id, ctx.frame)` never touches\n * `world.rng` and cannot desync a replay. Mixes the full float bits of each\n * value through a strong integer hash (murmur3-style avalanche).\n */\nexport function hashNoise(...values: number[]): number {\n let h = 0x9e3779b9 >>> 0;\n for (const v of values) {\n __noiseBits.setFloat64(0, v);\n h = Math.imul(h ^ __noiseBits.getUint32(0), 0x85ebca6b) >>> 0;\n h = (h ^ (h >>> 13)) >>> 0;\n h = Math.imul(h ^ __noiseBits.getUint32(4), 0xc2b2ae35) >>> 0;\n h = (h ^ (h >>> 16)) >>> 0;\n }\n // Final avalanche so short inputs still spread across the whole range.\n h = Math.imul(h ^ (h >>> 16), 0x85ebca6b) >>> 0;\n h = Math.imul(h ^ (h >>> 13), 0xc2b2ae35) >>> 0;\n h = (h ^ (h >>> 16)) >>> 0;\n return h / 4294967296;\n}\n\n/** Deterministic 32-bit FNV-1a hash of a string \u2014 handy for stable ids/seeds. */\nexport function hashString(str: string): number {\n let h = 2166136261 >>> 0;\n for (let i = 0; i < str.length; i++) {\n h ^= str.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return h >>> 0;\n}\n", "// Fixed-timestep clock. Real elapsed milliseconds go in; whole fixed steps come\n// out. This is what makes the sim frame-rate independent AND exactly reproducible:\n// the same input log always yields the same number of steps.\n\nexport interface ClockConfig {\n /** Simulation rate in Hz (steps per second). Default 60. */\n hz?: number;\n /** Max real ms consumed per advance, to avoid a spiral of death. Default 250. */\n maxFrameMs?: number;\n}\n\nexport class Clock {\n readonly stepMs: number;\n readonly dt: number; // fixed delta in seconds, for game logic\n readonly maxFrameMs: number;\n private accumulator = 0;\n private _frame = 0;\n private _simTimeMs = 0;\n\n constructor(config: ClockConfig = {}) {\n const hz = config.hz ?? 60;\n this.stepMs = 1000 / hz;\n this.dt = 1 / hz;\n this.maxFrameMs = config.maxFrameMs ?? 250;\n }\n\n /**\n * Feed real elapsed ms; returns how many fixed steps to run now.\n * Caller runs the sim exactly that many times.\n */\n advance(realMs: number): number {\n this.accumulator += Math.min(realMs, this.maxFrameMs);\n let steps = 0;\n while (this.accumulator >= this.stepMs) {\n this.accumulator -= this.stepMs;\n steps++;\n }\n return steps;\n }\n\n /** Called by the World once per executed step to keep counters honest. */\n tick(): void {\n this._frame++;\n this._simTimeMs += this.stepMs;\n }\n\n /** Interpolation alpha in [0,1) for smooth rendering between fixed steps. */\n get alpha(): number {\n return this.accumulator / this.stepMs;\n }\n\n get frame(): number {\n return this._frame;\n }\n get simTimeMs(): number {\n return this._simTimeMs;\n }\n get simTimeSec(): number {\n return this._simTimeMs / 1000;\n }\n\n getState() {\n return { accumulator: this.accumulator, frame: this._frame, simTimeMs: this._simTimeMs };\n }\n setState(s: { accumulator: number; frame: number; simTimeMs: number }): void {\n this.accumulator = s.accumulator;\n this._frame = s.frame;\n this._simTimeMs = s.simTimeMs;\n }\n}\n", "// Synchronous typed signal bus (Godot-style signals). Deterministic: listeners\n// fire in connection order, synchronously, within the current step.\n\nexport type Listener<T> = (payload: T) => void;\n\nexport class Signal<T = void> {\n private listeners: Listener<T>[] = [];\n\n connect(fn: Listener<T>): () => void {\n this.listeners.push(fn);\n return () => this.disconnect(fn);\n }\n\n once(fn: Listener<T>): () => void {\n const off = this.connect((p) => {\n off();\n fn(p);\n });\n return off;\n }\n\n disconnect(fn: Listener<T>): void {\n const i = this.listeners.indexOf(fn);\n if (i >= 0) this.listeners.splice(i, 1);\n }\n\n emit(payload: T): void {\n // Copy so a listener disconnecting mid-emit doesn't skip its neighbor.\n for (const fn of this.listeners.slice()) fn(payload);\n }\n\n get count(): number {\n return this.listeners.length;\n }\n\n clear(): void {\n this.listeners.length = 0;\n }\n}\n\n/**\n * A named event bus for cross-cutting game events, keyed by an event map so\n * payloads are typed. Prefer node-local Signals for local wiring; use the bus\n * for global concerns (score changed, level complete, sound cue).\n */\nexport class EventBus<Events extends Record<string, unknown>> {\n private signals = new Map<keyof Events, Signal<unknown>>();\n\n private signalFor<K extends keyof Events>(key: K): Signal<Events[K]> {\n let s = this.signals.get(key);\n if (!s) {\n s = new Signal<unknown>();\n this.signals.set(key, s);\n }\n return s as unknown as Signal<Events[K]>;\n }\n\n on<K extends keyof Events>(key: K, fn: Listener<Events[K]>): () => void {\n return this.signalFor(key).connect(fn);\n }\n\n once<K extends keyof Events>(key: K, fn: Listener<Events[K]>): () => void {\n return this.signalFor(key).once(fn);\n }\n\n emit<K extends keyof Events>(key: K, payload: Events[K]): void {\n this.signalFor(key).emit(payload);\n }\n\n clear(): void {\n this.signals.clear();\n }\n}\n", "// Deterministic structural hash of any JSON-like value. The spine of replay\n// verification: two runs are identical iff their state hashes match.\n\nfunction canonicalNumber(n: number): string {\n if (Number.isNaN(n)) return 'NaN';\n if (n === Infinity) return 'Inf';\n if (n === -Infinity) return '-Inf';\n if (n === 0) return '0'; // collapse -0 and 0\n return n.toString();\n}\n\n/**\n * Walk a value in a canonical order (object keys sorted) and fold it into a\n * 64-bit-ish FNV-1a hash represented as an 8-char hex string. Stable across runs\n * for structurally identical data.\n */\nexport function hashValue(value: unknown): string {\n let h1 = 2166136261 >>> 0;\n let h2 = 0x811c9dc5 >>> 0;\n const push = (s: string) => {\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i);\n h1 = Math.imul(h1 ^ c, 16777619) >>> 0;\n h2 = Math.imul(h2 ^ ((c << 3) | (c >>> 5)), 2246822519) >>> 0;\n }\n };\n\n const walk = (v: unknown): void => {\n if (v === null) return push('n');\n if (v === undefined) return push('u');\n switch (typeof v) {\n case 'number':\n return push('#' + canonicalNumber(v));\n case 'boolean':\n return push(v ? 't' : 'f');\n case 'string':\n return push('\"' + v);\n case 'object': {\n if (Array.isArray(v)) {\n push('[');\n for (const el of v) walk(el);\n push(']');\n return;\n }\n const obj = v as Record<string, unknown>;\n // Omit undefined-valued keys: JSON has no `undefined`, so `{a: undefined}`\n // and `{}` serialize identically. Counting the key would make hash()\n // disagree with the value after a save/load JSON round-trip (a Sprite's\n // unset paint fields are the canonical case). JSON-stable = the guarantee\n // persistence needs.\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort();\n push('{');\n for (const k of keys) {\n push(k + ':');\n walk(obj[k]);\n }\n push('}');\n return;\n }\n default:\n push('?');\n }\n };\n\n walk(value);\n const hex = (n: number) => n.toString(16).padStart(8, '0');\n return hex(h1) + hex(h2);\n}\n", "// The scene node: a Godot-style tree element with a transform, lifecycle,\n// children, local signals, and attachable behaviors. Updates run in fixed tree\n// order (depth-first, child-index order) which keeps the whole tree deterministic.\n\nimport type { Rng } from '../core/rng';\nimport type { Clock } from '../core/clock';\nimport type { InputState } from '../input/actions';\nimport { Signal, type EventBus } from '../core/events';\nimport {\n IDENTITY,\n composeTransform,\n makeTransform,\n type Transform,\n type Vec2,\n} from '../core/math';\nimport type { DrawCommand } from '../render/commands';\n\n/**\n * What a live node can see of its host world. The World implements this \u2014 it is\n * exactly the read-only context handed to update callbacks, so a behaviour can\n * reach input/rng/clock/time WITHOUT closing over the `world` from build(). That\n * closure-free property is what lets a node be lifted out and reused verbatim.\n */\nexport interface WorldContext {\n readonly rng: Rng;\n readonly clock: Clock;\n /** Sampled input for this step \u2014 `ctx.input.isDown('jump')`, `ctx.input.axis('pointer.x')`. */\n readonly input: InputState;\n /** Queue a node to be freed at the end of the current step (safe during iteration). */\n requestFree(node: Node): void;\n /** Seconds elapsed in sim time. */\n readonly time: number;\n /**\n * Canonical out-of-tree game state (hashed + snapshotted) \u2014 the same object\n * as `world.state`, so behaviours read/write shared sim data without closing\n * over the world or stashing it in module variables.\n */\n readonly state: Record<string, unknown>;\n /** The world event bus \u2014 emit/subscribe without a `world` closure. */\n readonly events: EventBus<Record<string, unknown>>;\n /** Design-space dimensions (what the camera letterboxes to). */\n readonly width: number;\n readonly height: number;\n /** True while the world is paused (only `pauseMode: 'always'` subtrees update). */\n readonly paused: boolean;\n /** Sim-time multiplier (1 = realtime); `'always'` subtrees receive unscaled dt. */\n readonly timeScale: number;\n /**\n * The active camera's world position + zoom, or null when none is current.\n * Structural (no Camera2D import needed) \u2014 enough for parallax, culling, and\n * screen-edge logic without a sibling search through the tree.\n */\n camera(): { pos: { x: number; y: number }; zoom: number } | null;\n}\n\n/** A composable update unit attached to a node (favour over deep inheritance). */\nexport interface Behavior {\n ready?(node: Node): void;\n /** `ctx` is the host world (input/rng/clock/time) \u2014 self-contained, no closure needed. */\n update?(node: Node, dt: number, ctx: WorldContext): void;\n exit?(node: Node): void;\n /** Optional tag for lookup/serialization. */\n readonly kind?: string;\n}\n\n/**\n * How a node behaves while the world is paused. `'inherit'` (default) takes the\n * parent's effective mode (the root default is pausable), `'always'` keeps its\n * subtree updating through a pause (pause menus, transitions), `'stopped'`\n * halts its subtree even when the world is running.\n */\nexport type PauseMode = 'inherit' | 'always' | 'stopped';\n\n/** A resolved pause mode \u2014 what 'inherit' collapses to as it flows down the tree. */\ntype EffectivePauseMode = 'pausable' | 'always' | 'stopped';\n\nlet __idCounter = 0;\n/** Deterministic id source \u2014 reset by the World on load so ids are reproducible. */\nexport function resetNodeIds(start = 0): void {\n __idCounter = start;\n}\n\nexport interface NodeConfig {\n name?: string;\n pos?: Vec2;\n rotation?: number;\n scale?: Vec2;\n z?: number;\n visible?: boolean;\n}\n\nexport class Node {\n readonly id: string;\n name: string;\n /** Type tag for serialization; subclasses override. */\n readonly type: string = 'Node';\n\n pos: Vec2;\n rotation: number;\n scale: Vec2;\n z: number;\n visible: boolean;\n /**\n * Cosmetic nodes are pure *view* (derived from game state, rebuildable) and are\n * excluded from serialize()/snapshot()/hash(). Mark a container cosmetic when it\n * only renders state that lives elsewhere \u2014 so transient display (move counters,\n * particles, tweened positions) never pollutes the canonical, verifiable state.\n */\n cosmetic = false;\n /**\n * Pause behaviour for this subtree (see PauseMode). Serialized only when\n * non-default, so existing trees keep their pinned hashes.\n */\n pauseMode: PauseMode = 'inherit';\n /**\n * Screen-space overlay: this subtree ignores the camera \u2014 its transforms\n * compose from IDENTITY (design-space coordinates) \u2014 and every command it\n * emits is tagged `layer: 1` so HUD/overlay content always paints above the\n * world, whatever the z values. Serialized only when true.\n */\n screenSpace = false;\n /**\n * Optional local anchor: when set, rotation/scale pivot around this point in\n * local space instead of the node origin (the local transform gains a\n * trailing translation of \u2212pivot). Serialized only when set.\n */\n pivot?: Vec2;\n\n parent: Node | null = null;\n readonly children: Node[] = [];\n world: WorldContext | null = null;\n\n /**\n * Optional inline update without subclassing. The third argument is the host\n * world context (input/rng/clock/time), so the callback is self-contained \u2014\n * `node.onUpdate = (n, dt, ctx) => { if (ctx.input.isDown('jump')) \u2026 }`.\n */\n onUpdate?: (node: Node, dt: number, ctx: WorldContext) => void;\n\n private behaviors: Behavior[] = [];\n private signals = new Map<string, Signal<unknown>>();\n private _ready = false;\n private _freed = false;\n\n constructor(config: NodeConfig = {}) {\n this.id = `n${__idCounter++}`;\n this.name = config.name ?? this.constructor.name;\n this.pos = config.pos ? { ...config.pos } : { x: 0, y: 0 };\n this.rotation = config.rotation ?? 0;\n this.scale = config.scale ? { ...config.scale } : { x: 1, y: 1 };\n this.z = config.z ?? 0;\n this.visible = config.visible ?? true;\n }\n\n // \u2500\u2500 Convenience accessors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Shorthand for `pos.x` \u2014 reads and writes the same vector. */\n get x(): number {\n return this.pos.x;\n }\n set x(v: number) {\n this.pos.x = v;\n }\n /** Shorthand for `pos.y` \u2014 reads and writes the same vector. */\n get y(): number {\n return this.pos.y;\n }\n set y(v: number) {\n this.pos.y = v;\n }\n\n // \u2500\u2500 Tree structure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n addChild<T extends Node>(child: T): T {\n child.parent = this;\n this.children.push(child);\n if (this.world && this._ready) child.enterTree(this.world);\n return child;\n }\n\n removeChild(child: Node): void {\n const i = this.children.indexOf(child);\n if (i >= 0) {\n this.children.splice(i, 1);\n child.parent = null;\n }\n }\n\n /** Deferred free: runs exit hooks and detaches at the end of the step. */\n free(): void {\n this.world?.requestFree(this);\n }\n\n /**\n * Immediately exit + detach ALL children. Unlike `free()` this is NOT\n * deferred \u2014 the children are gone when the call returns (safe here because\n * it iterates a snapshot of the array). Use it to rebuild a container's\n * contents wholesale; prefer `free()` for removals during an update.\n */\n clearChildren(): void {\n for (const c of this.children.slice()) {\n c.exitTree();\n this.removeChild(c);\n }\n }\n\n /** Depth-first find by name. */\n find(name: string): Node | null {\n if (this.name === name) return this;\n for (const c of this.children) {\n const r = c.find(name);\n if (r) return r;\n }\n return null;\n }\n\n /** Depth-first find of the first node (self included) that is an instance of `ctor` \u2014 typed. */\n findOfType<T extends Node>(ctor: new (...args: never[]) => T): T | null {\n if (this instanceof ctor) return this as unknown as T;\n for (const c of this.children) {\n const r = c.findOfType(ctor);\n if (r) return r;\n }\n return null;\n }\n\n /** All descendants (and self) of a given type tag. */\n query(type: string, out: Node[] = []): Node[] {\n if (this.type === type) out.push(this);\n for (const c of this.children) c.query(type, out);\n return out;\n }\n\n // \u2500\u2500 Behaviors \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n addBehavior(b: Behavior): this {\n this.behaviors.push(b);\n if (this._ready) b.ready?.(this);\n return this;\n }\n\n // \u2500\u2500 Signals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n signal<T = void>(name: string): Signal<T> {\n let s = this.signals.get(name);\n if (!s) {\n s = new Signal<unknown>();\n this.signals.set(name, s);\n }\n return s as unknown as Signal<T>;\n }\n emit<T>(name: string, payload: T): void {\n this.signals.get(name)?.emit(payload);\n }\n\n // \u2500\u2500 Lifecycle (engine-called) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n enterTree(world: WorldContext): void {\n this.world = world;\n if (!this._ready) {\n this._ready = true;\n this.onReady();\n for (const b of this.behaviors) b.ready?.(this);\n }\n for (const c of this.children) c.enterTree(world);\n }\n\n /**\n * Advance this subtree. `dt` is the (time-scaled) step delta; `unscaledDt`\n * and `paused` come from the world, and `parentMode` is the effective pause\n * mode flowing down the tree. The walk always descends \u2014 a paused node just\n * skips its callbacks \u2014 so an `'always'` descendant (pause menu, transition)\n * keeps running inside a paused parent.\n */\n updateTree(dt: number, unscaledDt: number = dt, parentMode: EffectivePauseMode = 'pausable', paused = false): void {\n if (this._freed) return;\n const mode: EffectivePauseMode = this.pauseMode === 'inherit' ? parentMode : this.pauseMode;\n const running = mode === 'always' || (mode === 'pausable' && !paused);\n if (running) {\n const ctx = this.world as WorldContext; // set once in-tree (updateTree runs after enterTree)\n // 'always' subtrees animate through pause AND slow-mo: they get real-step dt.\n const useDt = mode === 'always' ? unscaledDt : dt;\n for (const b of this.behaviors) b.update?.(this, useDt, ctx);\n this.onUpdate?.(this, useDt, ctx);\n this.onProcess(useDt);\n }\n // Copy children so structural changes during update are safe.\n for (const c of this.children.slice()) c.updateTree(dt, unscaledDt, mode, paused);\n }\n\n exitTree(): void {\n for (const b of this.behaviors) b.exit?.(this);\n this.onExit();\n for (const c of this.children.slice()) c.exitTree();\n this._freed = true;\n }\n\n get isFreed(): boolean {\n return this._freed;\n }\n\n // \u2500\u2500 Transforms \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n localTransform(): Transform {\n const t = makeTransform(this.pos, this.rotation, this.scale);\n // Pivot: rotate/scale around a local anchor point instead of the origin.\n return this.pivot ? composeTransform(t, makeTransform({ x: -this.pivot.x, y: -this.pivot.y }, 0, { x: 1, y: 1 })) : t;\n }\n\n worldTransform(): Transform {\n const local = this.localTransform();\n return this.parent ? composeTransform(this.parent.worldTransform(), local) : local;\n }\n\n // \u2500\u2500 Rendering (projection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Walk the subtree, appending draw commands with computed world transforms. */\n collectDraw(out: DrawCommand[], parentWorld: Transform = IDENTITY): void {\n if (!this.visible) return;\n // screenSpace: drop the camera \u2014 compose from IDENTITY so coordinates are design-space.\n const world = composeTransform(this.screenSpace ? IDENTITY : parentWorld, this.localTransform());\n const start = out.length;\n this.draw(out, world);\n for (const c of this.children) c.collectDraw(out, world);\n if (this.screenSpace) {\n // Tag the subtree's commands for the overlay pass (unless already higher).\n for (let i = start; i < out.length; i++) {\n const cmd = out[i];\n if ((cmd.layer ?? 0) < 1) cmd.layer = 1;\n }\n }\n }\n\n /** Subclasses emit their own commands here. Base draws nothing. */\n protected draw(_out: DrawCommand[], _world: Transform): void {}\n\n // \u2500\u2500 Overridable hooks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n protected onReady(): void {}\n protected onProcess(_dt: number): void {}\n protected onExit(): void {}\n\n // \u2500\u2500 Serialization (data only; behaviors/closures are re-attached by scene code) \u2500\u2500\n serialize(): SerializedNode {\n return {\n type: this.type,\n name: this.name,\n pos: { ...this.pos },\n rotation: this.rotation,\n scale: { ...this.scale },\n z: this.z,\n visible: this.visible,\n // New base fields only when non-default, so pinned hashes survive.\n ...(this.pivot ? { pivot: { ...this.pivot } } : {}),\n props: {\n ...this.serializeProps(),\n ...(this.pauseMode !== 'inherit' ? { pauseMode: this.pauseMode } : {}),\n ...(this.screenSpace ? { screenSpace: true } : {}),\n },\n children: this.children.filter((c) => !c.cosmetic).map((c) => c.serialize()),\n };\n }\n /** Subclasses persist their own fields here. */\n protected serializeProps(): Record<string, unknown> {\n return {};\n }\n /** Subclasses restore their own fields here. */\n applyProps(_props: Record<string, unknown>): void {}\n}\n\nexport interface SerializedNode {\n type: string;\n name: string;\n pos: Vec2;\n rotation: number;\n scale: Vec2;\n z: number;\n visible: boolean;\n /** Local rotation/scale anchor (absent when unset). */\n pivot?: Vec2;\n props: Record<string, unknown>;\n children: SerializedNode[];\n}\n", "// Concrete node types built on Node. Code-as-art: a Sprite is a vector shape or\n// glyph, never a bitmap. Text is a DOM-quality label. Camera2D drives the view.\n// Timer is a deterministic countdown that emits a signal.\n\nimport type { Transform } from '../core/math';\nimport { dcos, dsin } from '../core/dmath';\nimport { TAU } from '../core/math';\nimport type { DrawCommand, Paint, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig, type WorldContext } from './node';\n\n// \u2500\u2500 Sprite \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * A Sprite's shape. ORIGIN CONVENTIONS differ per kind \u2014 a Sprite's `pos` is the\n * node origin, and each shape places itself relative to it:\n * - `rect` \u2192 CENTER-anchored by default: drawn from (-w/2,-h/2), so `pos` is its\n * middle. Pass `anchor: 'topLeft'` to place `pos` at the top-left\n * corner instead (the canvas mental model) \u2014 no half-size offset.\n * - `circle` \u2192 CENTER-anchored: `pos` is the center.\n * - `ellipse`\u2192 CENTER-anchored: `pos` is the center; `rx`/`ry` are the semi-axes.\n * - `arc` \u2192 CENTER-anchored: `pos` is the arc's center. Radians, clockwise\n * from +x (y-down screen convention), running `start` \u2192 `end`.\n * `sector: true` closes through the center (a pie slice).\n * - `glyph` \u2192 CENTER-anchored (align 'center').\n * - `poly` \u2192 LOCAL coordinates: `points` are relative to `pos` as-is (put your\n * own 0,0 wherever you like).\n * - `path` \u2192 LOCAL coordinates: `d` is drawn relative to `pos`.\n * - `diamond`\u2192 CENTER-anchored: a `w\u00D7h` rhombus (iso tile). `pos` is its middle.\n * - `regularPoly` \u2192 CENTER-anchored: `sides`-gon of circumradius `r`. `rotation`\n * (radians) turns it; 0 puts the first vertex straight up.\n * (`Text` is anchored by its `align`, not centered \u2014 see the Text node.)\n *\n * `diamond` and `regularPoly` are pure sugar over `poly` (resolved at draw time,\n * no renderer change) \u2014 they exist so an iso tile or a hex reads as intent, not\n * as four hand-typed corner numbers.\n */\nexport type Shape =\n | { kind: 'rect'; w: number; h: number; r?: number; anchor?: 'center' | 'topLeft' }\n | { kind: 'circle'; radius: number }\n | { kind: 'ellipse'; rx: number; ry: number }\n | { kind: 'arc'; radius: number; start: number; end: number; sector?: boolean }\n | { kind: 'poly'; points: number[]; closed?: boolean }\n | { kind: 'path'; d: string }\n | { kind: 'glyph'; char: string; size: number }\n | { kind: 'diamond'; w: number; h: number }\n | { kind: 'regularPoly'; sides: number; r: number; rotation?: number };\n\n/** Local poly points for a center-anchored `w\u00D7h` diamond (top, right, bottom, left). */\nexport function diamondPoints(w: number, h: number): number[] {\n return [0, -h / 2, w / 2, 0, 0, h / 2, -w / 2, 0];\n}\n\n/** Local poly points for a center-anchored regular `sides`-gon of circumradius `r`. */\nexport function regularPolyPoints(sides: number, r: number, rotation = 0): number[] {\n const pts: number[] = [];\n // Start at the top (\u221290\u00B0) so an unturned polygon points up, then go clockwise.\n for (let i = 0; i < sides; i++) {\n const a = rotation - TAU / 4 + (TAU * i) / sides;\n pts.push(dcos(a) * r, dsin(a) * r);\n }\n return pts;\n}\n\nexport interface SpriteConfig extends NodeConfig, Paint {\n shape: Shape;\n}\n\nexport class Sprite extends Node {\n override readonly type = 'Sprite';\n shape: Shape;\n paint: Paint;\n\n constructor(config: SpriteConfig) {\n super(config);\n this.shape = config.shape;\n this.paint = {\n fill: config.fill,\n stroke: config.stroke,\n strokeWidth: config.strokeWidth,\n opacity: config.opacity,\n round: config.round,\n gradient: config.gradient,\n shadow: config.shadow,\n lineDash: config.lineDash,\n };\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const p = this.paint;\n const base = { transform: world, z: this.z, ...p };\n switch (this.shape.kind) {\n case 'rect': {\n const tl = this.shape.anchor === 'topLeft';\n out.push({ kind: 'rect', x: tl ? 0 : -this.shape.w / 2, y: tl ? 0 : -this.shape.h / 2, w: this.shape.w, h: this.shape.h, r: this.shape.r, ...base });\n break;\n }\n case 'circle':\n out.push({ kind: 'circle', cx: 0, cy: 0, radius: this.shape.radius, ...base });\n break;\n case 'ellipse':\n out.push({ kind: 'ellipse', cx: 0, cy: 0, rx: this.shape.rx, ry: this.shape.ry, ...base });\n break;\n case 'arc':\n out.push({ kind: 'arc', cx: 0, cy: 0, radius: this.shape.radius, start: this.shape.start, end: this.shape.end, sector: this.shape.sector, ...base });\n break;\n case 'poly':\n out.push({ kind: 'poly', points: this.shape.points, closed: this.shape.closed ?? true, ...base });\n break;\n case 'path':\n out.push({ kind: 'path', d: this.shape.d, ...base });\n break;\n case 'glyph':\n out.push({ kind: 'text', text: this.shape.char, x: 0, y: 0, size: this.shape.size, align: 'center', ...base });\n break;\n case 'diamond':\n out.push({ kind: 'poly', points: diamondPoints(this.shape.w, this.shape.h), closed: true, ...base });\n break;\n case 'regularPoly':\n out.push({ kind: 'poly', points: regularPolyPoints(this.shape.sides, this.shape.r, this.shape.rotation ?? 0), closed: true, ...base });\n break;\n }\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { shape: this.shape, paint: this.paint };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (props.shape) this.shape = props.shape as Shape;\n if (props.paint) this.paint = props.paint as Paint;\n }\n}\n\n// \u2500\u2500 Text \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface TextConfig extends NodeConfig, Paint {\n text: string;\n size?: number;\n font?: string;\n align?: TextAlign;\n weight?: number;\n}\n\nexport class Text extends Node {\n override readonly type = 'Text';\n text: string;\n size: number;\n font?: string;\n align: TextAlign;\n weight?: number;\n paint: Paint;\n\n constructor(config: TextConfig) {\n super(config);\n this.text = config.text;\n this.size = config.size ?? 24;\n this.font = config.font;\n this.align = config.align ?? 'left';\n this.weight = config.weight;\n this.paint = { fill: config.fill ?? '#000', stroke: config.stroke, strokeWidth: config.strokeWidth, opacity: config.opacity };\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n out.push({\n kind: 'text', text: this.text, x: 0, y: 0, size: this.size, font: this.font,\n align: this.align, weight: this.weight, transform: world, z: this.z, ...this.paint,\n });\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { text: this.text, size: this.size, align: this.align, paint: this.paint };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.text === 'string') this.text = props.text;\n if (typeof props.size === 'number') this.size = props.size;\n if (props.align) this.align = props.align as TextAlign;\n if (props.paint) this.paint = props.paint as Paint;\n }\n}\n\n// \u2500\u2500 Camera2D \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface CameraConfig extends NodeConfig {\n zoom?: number;\n /** Make this the active camera on ready. */\n current?: boolean;\n}\n\nexport class Camera2D extends Node {\n override readonly type = 'Camera2D';\n zoom: number;\n current: boolean;\n\n constructor(config: CameraConfig = {}) {\n super(config);\n this.zoom = config.zoom ?? 1;\n this.current = config.current ?? true;\n }\n\n protected override onReady(): void {\n if (this.current) (this.world as WorldContext & { activeCamera?: Camera2D }).activeCamera = this;\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { zoom: this.zoom, current: this.current };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.zoom === 'number') this.zoom = props.zoom;\n if (typeof props.current === 'boolean') this.current = props.current;\n }\n}\n\n// \u2500\u2500 Timer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface TimerConfig extends NodeConfig {\n duration: number; // seconds\n autostart?: boolean;\n oneShot?: boolean;\n}\n\nexport class Timer extends Node {\n override readonly type = 'Timer';\n duration: number;\n oneShot: boolean;\n private remaining: number;\n private running: boolean;\n\n constructor(config: TimerConfig) {\n super(config);\n this.duration = config.duration;\n this.oneShot = config.oneShot ?? true;\n this.remaining = config.duration;\n this.running = config.autostart ?? true;\n }\n\n start(duration?: number): void {\n if (duration !== undefined) this.duration = duration;\n this.remaining = this.duration;\n this.running = true;\n }\n stop(): void {\n this.running = false;\n }\n\n get timeLeft(): number {\n return this.remaining;\n }\n\n protected override onProcess(dt: number): void {\n if (!this.running) return;\n this.remaining -= dt;\n if (this.remaining <= 0) {\n this.emit('timeout', undefined);\n if (this.oneShot) this.running = false;\n else this.remaining += this.duration;\n }\n }\n\n /** Signal emitted when the countdown reaches zero. */\n get timeout() {\n return this.signal('timeout');\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { duration: this.duration, oneShot: this.oneShot, remaining: this.remaining, running: this.running };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.duration === 'number') this.duration = props.duration;\n if (typeof props.oneShot === 'boolean') this.oneShot = props.oneShot;\n if (typeof props.remaining === 'number') this.remaining = props.remaining;\n if (typeof props.running === 'boolean') this.running = props.running;\n }\n}\n", "// 2.5D view nodes. These are pure VIEW sugar built on the same DrawCommand\n// vocabulary \u2014 no renderer change, no sim state. They collapse the two chores a\n// 2.5D game hand-rolls per frame: drawing a raised tile as three shaded faces\n// (IsoPrism) and re-deriving painter `z` from a depth axis (DepthSort).\n\nimport type { Transform } from '../core/math';\nimport type { DrawCommand, Paint } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\nimport { diamondPoints } from './nodes';\n\n// \u2500\u2500 IsoPrism \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * A raised isometric tile = a cube: a top diamond + a front-left and front-right\n * parallelogram. `pos` is the GROUND cell centre (where an elev-0 diamond would\n * sit); the block rises `height` screen-px toward \u2212y. Give it a base `fill` and\n * the two side faces auto-shade (left darkest, right mid) \u2014 or override any face\n * with `top` / `left` / `right`. Emits the three faces in back-to-front order so\n * the top always paints over the sides within the prism.\n */\nexport interface IsoPrismConfig extends NodeConfig {\n /** Footprint diamond width (horizontal diagonal) in screen px. */\n tileW: number;\n /** Footprint diamond height (vertical diagonal) in screen px. */\n tileH: number;\n /** Block height in screen px (0 = a flat tile: only the top diamond). */\n height: number;\n /** Base colour; side faces derive from it unless overridden. */\n fill: string;\n /** Explicit face paints (override the auto-shade). */\n top?: Paint;\n left?: Paint;\n right?: Paint;\n /** Shared stroke for all faces (seams between tiles). */\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n}\n\n/** Multiply a #rgb / #rrggbb colour's channels by `f` (clamped) for face shading. */\nexport function shadeHex(hex: string, f: number): string {\n let h = hex.replace('#', '');\n if (h.length === 3) h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n if (h.length !== 6) return hex; // non-hex (named/rgb()) \u2014 leave as-is\n const ch = (i: number) => {\n const v = Math.round(Math.min(255, Math.max(0, parseInt(h.slice(i, i + 2), 16) * f)));\n return v.toString(16).padStart(2, '0');\n };\n return `#${ch(0)}${ch(2)}${ch(4)}`;\n}\n\nexport class IsoPrism extends Node {\n override readonly type = 'IsoPrism';\n tileW: number;\n tileH: number;\n height: number;\n fill: string;\n topPaint?: Paint;\n leftPaint?: Paint;\n rightPaint?: Paint;\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n\n constructor(config: IsoPrismConfig) {\n super(config);\n this.tileW = config.tileW;\n this.tileH = config.tileH;\n this.height = config.height;\n this.fill = config.fill;\n this.topPaint = config.top;\n this.leftPaint = config.left;\n this.rightPaint = config.right;\n this.stroke = config.stroke;\n this.strokeWidth = config.strokeWidth;\n this.opacity = config.opacity;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const w = this.tileW;\n const h = this.tileH;\n const H = this.height;\n const seam: Paint = { stroke: this.stroke, strokeWidth: this.strokeWidth, opacity: this.opacity };\n const top: Paint = this.topPaint ?? { fill: this.fill };\n const left: Paint = this.leftPaint ?? { fill: shadeHex(this.fill, 0.65) };\n const right: Paint = this.rightPaint ?? { fill: shadeHex(this.fill, 0.85) };\n const base = { transform: world, z: this.z };\n if (H > 0) {\n // Front-left face: ground L\u2192B up to top B'\u2192L'.\n out.push({ kind: 'poly', closed: true, points: [-w / 2, 0, 0, h / 2, 0, h / 2 - H, -w / 2, -H], ...seam, ...left, ...base });\n // Front-right face: ground B\u2192R up to top R'\u2192B'.\n out.push({ kind: 'poly', closed: true, points: [0, h / 2, w / 2, 0, w / 2, -H, 0, h / 2 - H], ...seam, ...right, ...base });\n }\n // Top diamond, raised by H (drawn last so it wins ties within the prism).\n const tp = diamondPoints(w, h).map((v, i) => (i % 2 === 1 ? v - H : v));\n out.push({ kind: 'poly', closed: true, points: tp, ...seam, ...top, ...base });\n }\n\n protected override serializeProps(): Record<string, unknown> {\n return { tileW: this.tileW, tileH: this.tileH, height: this.height, fill: this.fill };\n }\n override applyProps(props: Record<string, unknown>): void {\n if (typeof props.tileW === 'number') this.tileW = props.tileW;\n if (typeof props.tileH === 'number') this.tileH = props.tileH;\n if (typeof props.height === 'number') this.height = props.height;\n if (typeof props.fill === 'string') this.fill = props.fill;\n }\n}\n\n// \u2500\u2500 DepthSort \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * A container that auto-assigns each child's painter `z` from a depth accessor,\n * so overlapping sprites stack correctly without every mover re-setting `z` in\n * its own update. The key is read at DRAW time (positions are final for the\n * frame), integrating these children into the same global z-order as the rest of\n * the scene. Godot's `YSort`, generalised to any axis:\n * new DepthSort({ key: (n) => n.pos.y }) // top-down overlap\n * new DepthSort({ key: (n) => n.userDepth }) // iso gx+gy\n * See docs/CONVENTIONS.md \u00A7Depth for the z-from-depth convention.\n */\nexport interface DepthSortConfig extends NodeConfig {\n /** Depth of a child \u2192 its `z`. Larger = drawn on top (painter's order). */\n key: (n: Node) => number;\n /** Multiplier applied to the key before it becomes `z` (default 1). */\n depthScale?: number;\n}\n\nexport class DepthSort extends Node {\n override readonly type = 'DepthSort';\n key: (n: Node) => number;\n depthScale: number;\n /** DepthSort is a pure ordering container \u2014 its z assignments are view-only. */\n override cosmetic = true;\n\n constructor(config: DepthSortConfig) {\n super(config);\n this.key = config.key;\n this.depthScale = config.depthScale ?? 1;\n }\n\n override collectDraw(out: DrawCommand[], parentWorld?: Transform): void {\n for (const c of this.children) c.z = this.key(c) * this.depthScale;\n super.collectDraw(out, parentWorld);\n }\n}\n", "// CameraController \u2014 a follow behavior for Camera2D. Chases a target node with\n// an optional deadzone (slack box the target roams before the camera moves),\n// smooth lerp, and world-bounds clamping so the view never shows past the edges\n// of a level larger than the screen. This is the ergonomic layer on top of the\n// raw view transform (World.viewTransform / World.screenToWorld).\n//\n// DETERMINISM: a follow camera is usually pure *view* \u2014 its smoothed position is\n// derived from the target and would only add float drift to world.hash(). Mark\n// the camera (and this controller) `cosmetic = true` unless the camera position\n// is genuinely gameplay-meaningful (e.g. offscreen == death). This class does\n// NOT set cosmetic on the camera it drives; that policy belongs to the game.\n\nimport { Node, type NodeConfig, type WorldContext } from './node';\nimport { clamp, lerp, type Vec2 } from '../core/math';\nimport type { Camera2D } from './nodes';\n\n/** World-space rectangle the camera CENTER is kept inside (before viewport inset). */\nexport interface CameraBounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface CameraControllerConfig extends NodeConfig {\n /** Node to follow. May be set later via `follow()`. */\n target?: Node;\n /** Camera to drive. Defaults to the world's active camera each step. */\n camera?: Camera2D;\n /** Half-extents of a slack box the target may roam before the camera chases. */\n deadzone?: number | Vec2;\n /** Per-step chase factor in [0,1]; 1 snaps, lower trails. Default 0.15. */\n smooth?: number;\n /** Clamp the view to a world rectangle (the level bounds) so no void shows. */\n bounds?: CameraBounds;\n}\n\ntype CameraHost = WorldContext & {\n width: number;\n height: number;\n activeCamera: Camera2D | null;\n};\n\nexport class CameraController extends Node {\n override readonly type = 'CameraController';\n // Follow is view-only by default: keep the smoothed chase out of world.hash().\n override cosmetic = true;\n\n target: Node | null;\n private cameraRef: Camera2D | null;\n deadzone: Vec2;\n smooth: number;\n bounds: CameraBounds | null;\n\n constructor(config: CameraControllerConfig = {}) {\n super(config);\n this.target = config.target ?? null;\n this.cameraRef = config.camera ?? null;\n const dz = config.deadzone ?? 0;\n this.deadzone = typeof dz === 'number' ? { x: dz, y: dz } : { ...dz };\n this.smooth = config.smooth ?? 0.15;\n this.bounds = config.bounds ? { ...config.bounds } : null;\n }\n\n /** Point the controller at a node to follow. */\n follow(target: Node): this {\n this.target = target;\n return this;\n }\n\n private host(): CameraHost | null {\n return (this.world as CameraHost | null) ?? null;\n }\n\n private camera(): Camera2D | null {\n return this.cameraRef ?? this.host()?.activeCamera ?? null;\n }\n\n /** Where the camera wants to sit: the target position, clamped to bounds. */\n private desired(cam: Camera2D): Vec2 {\n const host = this.host()!;\n const tw = this.target!.worldTransform();\n let x = cam.pos.x;\n let y = cam.pos.y;\n // Deadzone: only chase the axis once the target leaves the slack box.\n const dx = tw.e - cam.pos.x;\n const dy = tw.f - cam.pos.y;\n if (Math.abs(dx) > this.deadzone.x) x = tw.e - Math.sign(dx) * this.deadzone.x;\n if (Math.abs(dy) > this.deadzone.y) y = tw.f - Math.sign(dy) * this.deadzone.y;\n if (this.bounds) {\n // Inset by half the visible extent (which grows as you zoom out) so the\n // view rectangle stays wholly inside the world. If the world is smaller\n // than the view on an axis, centre on it instead of fighting the clamp.\n const zoom = cam.zoom || 1;\n const halfW = host.width / 2 / zoom;\n const halfH = host.height / 2 / zoom;\n const loX = this.bounds.minX + halfW;\n const hiX = this.bounds.maxX - halfW;\n const loY = this.bounds.minY + halfH;\n const hiY = this.bounds.maxY - halfH;\n x = loX > hiX ? (this.bounds.minX + this.bounds.maxX) / 2 : clamp(x, loX, hiX);\n y = loY > hiY ? (this.bounds.minY + this.bounds.maxY) / 2 : clamp(y, loY, hiY);\n }\n return { x, y };\n }\n\n /** Jump the camera straight to its desired position (no smoothing). */\n snap(): void {\n const cam = this.camera();\n if (!cam || !this.target || !this.host()) return;\n const d = this.desired(cam);\n cam.pos.x = d.x;\n cam.pos.y = d.y;\n }\n\n protected override onReady(): void {\n // Start framed so frame 0 is already centered \u2014 no lurch from the origin.\n this.snap();\n }\n\n protected override onProcess(): void {\n const cam = this.camera();\n if (!cam || !this.target || !this.host()) return;\n const d = this.desired(cam);\n const s = clamp(this.smooth, 0, 1);\n cam.pos.x = lerp(cam.pos.x, d.x, s);\n cam.pos.y = lerp(cam.pos.y, d.y, s);\n }\n}\n", "// ParallaxLayer \u2014 a depth layer that scrolls at a fraction of the camera's\n// motion, so far scenery (mountains, sky, moon) drifts slower than near scenery\n// (reeds, foreground). Place world-space children under it and give it a\n// `factor`: 0 pins the layer to the screen (infinitely far), 1 scrolls it fully\n// with the world (foreground). Anything between is a middle plane.\n//\n// It works by tracking the active camera: setting its own position to\n// `camPos\u00B7(1\u2212factor)` cancels part of the view's scroll, leaving an effective\n// scroll of exactly `factor`. Pure view \u2014 cosmetic, so it never enters\n// world.hash(); it reads the camera (itself cosmetic) and touches only its own\n// transform. No wall-clock, no randomness.\n\nimport { Node, type NodeConfig, type WorldContext } from './node';\nimport type { Camera2D } from './nodes';\n\ntype CameraHost = WorldContext & { activeCamera: Camera2D | null };\n\nexport interface ParallaxLayerConfig extends NodeConfig {\n /** Scroll fraction: 0 = pinned to screen (far), 1 = full world scroll (near). */\n factor: number;\n}\n\nexport class ParallaxLayer extends Node {\n override readonly type = 'ParallaxLayer';\n // A parallax layer is pure view \u2014 keep its drift out of world.hash().\n override cosmetic = true;\n factor: number;\n\n constructor(config: ParallaxLayerConfig) {\n super(config);\n this.factor = config.factor;\n }\n\n /** Re-sync to the current camera; called each process tick (and on demand). */\n sync(): void {\n const cam = (this.world as CameraHost | null)?.activeCamera;\n if (!cam) return;\n this.pos.x = cam.pos.x * (1 - this.factor);\n this.pos.y = cam.pos.y * (1 - this.factor);\n }\n\n protected override onReady(): void {\n this.sync();\n }\n\n protected override onProcess(): void {\n this.sync();\n }\n}\n", "// Frame-scoped node pool: hide/show instead of create/destroy, for views that\n// redraw a whole entity set every frame (hordes, bullets, tiles, HP bars).\n// Usage per frame: begin() \u2192 get() once per live entity \u2192 end(). Nodes are\n// created on demand, reused in stable order, and surplus nodes are hidden \u2014\n// never removed \u2014 so the scene tree stays allocation-quiet at peak load.\n//\n// Pooled nodes are pure view: parent them to a `cosmetic = true` layer so the\n// pool's grow-only node set never enters world.hash().\n// (Promoted from six near-identical per-game copies \u2014 see docs/LESSONS.md.)\n\nimport type { Node } from './node';\n\nexport class NodePool<T extends Node = Node> {\n private items: T[] = [];\n private used = 0;\n\n constructor(\n private parent: Node,\n private make: () => T,\n ) {}\n\n /** Start a frame: every pooled node is up for reuse. */\n begin(): void {\n this.used = 0;\n }\n\n /** Claim the next node (created and parented on first use), made visible. */\n get(): T {\n if (this.used === this.items.length) this.items.push(this.parent.addChild(this.make()));\n const n = this.items[this.used++];\n n.visible = true;\n return n;\n }\n\n /** End a frame: hide every node not claimed since begin(). */\n end(): void {\n for (let i = this.used; i < this.items.length; i++) this.items[i].visible = false;\n }\n\n /** Nodes claimed this frame (call after the get() loop). */\n get liveCount(): number {\n return this.used;\n }\n}\n", "// Deterministic tweening. Tweens advance by the fixed dt, so animations are\n// exactly reproducible. Tweens animate via setter closures (transient visual\n// polish \u2014 not part of the hashed logic state), Godot AnimationPlayer-style.\n\nimport { clamp, lerp } from '../core/math';\nimport { dcos, dexp, dexp2, dsin } from '../core/dmath';\nimport { Node } from './node';\n\nexport type Easing = (t: number) => number;\n\n// \u2500\u2500 Framerate-independent smoothing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// The naive `x += (target - x) * k` follows a target, but its stiffness scales\n// with frame count: halving dt halves the approach per step. These helpers fold\n// dt into an exponential so the same real-time response falls out of any fixed\n// step. Feed the FIXED clock dt (never a variable rAF delta) or a lockstep sim\n// desyncs. All pure + deterministic (exp routes through dmath), so they are safe\n// to use on hashed values as well as cosmetic ones.\n\n/**\n * Exponentially damp `current` toward `target`, framerate-independent.\n * `lambda` is the decay rate (1/s): larger = snappier. Reaches ~63% of the way\n * to the target after 1/lambda seconds regardless of how dt is subdivided.\n */\nexport const lerpDamp = (current: number, target: number, lambda: number, dt: number): number =>\n lerp(target, current, dexp(-lambda * dt));\n\n/** A critically-damped spring value: rides toward a target with no overshoot. */\nexport interface SpringState {\n value: number;\n vel: number;\n}\n\n/** Make a spring at rest on `value`. */\nexport const spring = (value = 0): SpringState => ({ value, vel: 0 });\n\n/**\n * Advance a critically-damped spring one fixed step toward `target`. `omega` is\n * the angular frequency (rad/s) \u2014 higher snaps faster. Critical damping means it\n * settles as fast as possible without oscillating. Mutates and returns the state.\n * Uses the closed-form solution so it is stable at any dt (no stiffness blow-up).\n */\nexport function springStep(s: SpringState, target: number, omega: number, dt: number): SpringState {\n const decay = dexp(-omega * dt);\n const d = s.value - target; // displacement from rest\n const c = s.vel + omega * d; // integration constant for x(t) = (d + c\u00B7t)\u00B7e^(\u2212\u03C9t)\n s.value = target + (d + c * dt) * decay;\n s.vel = (s.vel - c * omega * dt) * decay;\n return s;\n}\n\n/**\n * One-liner critically-damped follow that owns its own velocity in a closure \u2014\n * for camera/value chase where you don't want to thread a SpringState around.\n * `settle` is the approximate time (s) to arrive. Returns a `(target, dt) \u2192 value`.\n */\nexport function makeReach(start = 0, settle = 0.25): (target: number, dt: number) => number {\n // omega \u2248 4/settle puts ~98% of the move inside `settle` seconds.\n const omega = 4 / Math.max(1e-4, settle);\n const s = spring(start);\n return (target: number, dt: number) => springStep(s, target, omega, dt).value;\n}\n\n// Integer powers are spelled out as multiplication and 2^x routes through\n// dexp2: Math.pow is implementation-defined, and eased values land in hashed\n// node props, so easings must be bit-identical across engines.\nconst sq = (x: number) => x * x;\nconst cube = (x: number) => x * x * x;\nexport const EASINGS: Record<string, Easing> = {\n linear: (t) => t,\n quadIn: (t) => t * t,\n quadOut: (t) => 1 - (1 - t) * (1 - t),\n quadInOut: (t) => (t < 0.5 ? 2 * t * t : 1 - sq(-2 * t + 2) / 2),\n cubicIn: (t) => t * t * t,\n cubicOut: (t) => 1 - cube(1 - t),\n cubicInOut: (t) => (t < 0.5 ? 4 * t * t * t : 1 - cube(-2 * t + 2) / 2),\n sineIn: (t) => 1 - dcos((t * Math.PI) / 2),\n sineOut: (t) => dsin((t * Math.PI) / 2),\n sineInOut: (t) => -(dcos(Math.PI * t) - 1) / 2,\n backOut: (t) => {\n const c1 = 1.70158;\n const c3 = c1 + 1;\n return 1 + c3 * cube(t - 1) + c1 * sq(t - 1);\n },\n elasticOut: (t) => {\n const c4 = (2 * Math.PI) / 3;\n return t === 0 ? 0 : t === 1 ? 1 : dexp2(-10 * t) * dsin((t * 10 - 0.75) * c4) + 1;\n },\n bounceOut: (t) => {\n const n1 = 7.5625;\n const d1 = 2.75;\n if (t < 1 / d1) return n1 * t * t;\n if (t < 2 / d1) return n1 * (t -= 1.5 / d1) * t + 0.75;\n if (t < 2.5 / d1) return n1 * (t -= 2.25 / d1) * t + 0.9375;\n return n1 * (t -= 2.625 / d1) * t + 0.984375;\n },\n};\n\ninterface Track {\n apply: (v: number) => void;\n from: number;\n to: number;\n duration: number;\n elapsed: number;\n ease: Easing;\n onDone?: () => void;\n delay: number;\n}\n\n/** A node that runs one or more property tweens and reports when they finish. */\nexport class AnimationPlayer extends Node {\n override readonly type = 'AnimationPlayer';\n private tracks: Track[] = [];\n\n /**\n * Animate a value from \u2192 to over `duration` seconds via `apply(value)`.\n * Returns this for chaining.\n */\n to(\n apply: (v: number) => void,\n from: number,\n to: number,\n duration: number,\n ease: keyof typeof EASINGS | Easing = 'cubicOut',\n opts: { delay?: number; onDone?: () => void } = {},\n ): this {\n this.tracks.push({\n apply,\n from,\n to,\n duration: Math.max(1e-6, duration),\n elapsed: 0,\n ease: typeof ease === 'function' ? ease : EASINGS[ease] ?? EASINGS.linear,\n delay: opts.delay ?? 0,\n onDone: opts.onDone,\n });\n return this;\n }\n\n get active(): boolean {\n return this.tracks.length > 0;\n }\n\n /** Signal emitted when all tracks complete. */\n get finished() {\n return this.signal('finished');\n }\n\n protected override onProcess(dt: number): void {\n if (this.tracks.length === 0) return;\n for (let i = this.tracks.length - 1; i >= 0; i--) {\n const tk = this.tracks[i];\n if (tk.delay > 0) {\n tk.delay -= dt;\n continue;\n }\n tk.elapsed += dt;\n const t = clamp(tk.elapsed / tk.duration, 0, 1);\n tk.apply(tk.from + (tk.to - tk.from) * tk.ease(t));\n if (t >= 1) {\n tk.onDone?.();\n this.tracks.splice(i, 1);\n }\n }\n if (this.tracks.length === 0) this.emit('finished', undefined);\n }\n}\n", "// Particles + screen shake: the juice kit. Both are COSMETIC by construction \u2014\n// they carry their own tiny Rng stream (never the world's), are excluded from\n// hashing/serialization, and can be deleted without changing any game outcome.\n// Emission is driven by sim events (jumped, landed, hit\u2026), so replays produce\n// identical visuals, but no canonical state ever depends on them.\n\nimport { dcos, dsin } from '../core/dmath';\nimport { Rng } from '../core/rng';\nimport { smoothstep, TAU, type Transform, type Vec2 } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\n\nexport interface ParticleStyle {\n /** Colors drawn from at random per particle. */\n colors: string[];\n /** Particle radius range (px). */\n sizeMin: number;\n sizeMax: number;\n /** Initial speed range (px/s). */\n speedMin: number;\n speedMax: number;\n /** Emission arc: center angle + spread (radians). Default: full circle. */\n angle?: number;\n spread?: number;\n /** Lifetime range (s). */\n lifeMin: number;\n lifeMax: number;\n /** Gravity applied to particles (px/s\u00B2, +y is down). */\n gravity?: number;\n /** Velocity damping per second (0 = none, 5 = strong). */\n drag?: number;\n /** Shrink to zero over life (default true; also fades opacity). */\n shrink?: boolean;\n}\n\ninterface Particle {\n x: number;\n y: number;\n vx: number;\n vy: number;\n life: number;\n maxLife: number;\n size: number;\n color: string;\n}\n\n/**\n * A pooled particle emitter node. Call `burst(n, at, style)` from game code in\n * response to feel events. Always cosmetic; safe to add anywhere in the tree.\n */\nexport class Particles extends Node {\n override readonly type: string = 'Particles';\n private pool: Particle[] = [];\n private rng: Rng;\n /** Cap on live particles (oldest are recycled first). */\n maxParticles: number;\n\n constructor(config: NodeConfig & { seed?: number; maxParticles?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 7);\n this.maxParticles = config.maxParticles ?? 512;\n }\n\n /** Emit a burst at a position (in this node's local space). */\n burst(count: number, at: Vec2, style: ParticleStyle): void {\n const r = this.rng;\n for (let i = 0; i < count; i++) {\n const angle = style.angle !== undefined ? style.angle + (r.float() - 0.5) * (style.spread ?? 0.6) : r.float() * TAU;\n const speed = style.speedMin + r.float() * (style.speedMax - style.speedMin);\n const p: Particle = {\n x: at.x,\n y: at.y,\n vx: dcos(angle) * speed,\n vy: dsin(angle) * speed,\n life: 0,\n maxLife: style.lifeMin + r.float() * (style.lifeMax - style.lifeMin),\n size: style.sizeMin + r.float() * (style.sizeMax - style.sizeMin),\n color: style.colors[r.int(style.colors.length)],\n };\n if (this.pool.length >= this.maxParticles) this.pool.shift();\n this.pool.push(p);\n }\n // Stash style scalars on the instance for update (single-style emitters are\n // the common case; per-particle style costs memory for no visible gain).\n this.gravity = style.gravity ?? 0;\n this.drag = style.drag ?? 0;\n this.shrink = style.shrink ?? true;\n }\n\n private gravity = 0;\n private drag = 0;\n private shrink = true;\n\n // \u2500\u2500 Continuous emission \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // A steady stream (torch smoke, thruster exhaust) on top of the one-shot\n // burst(): a fractional accumulator over sim dt spawns whole particles\n // through the same private-Rng burst path, so it stays deterministic and\n // cosmetic by the same construction.\n private emitRate = 0;\n private emitAcc = 0;\n private emitStyle: ParticleStyle | null = null;\n private emitOrigin: Vec2 = { x: 0, y: 0 };\n\n /**\n * Start (or retune) continuous emission at `ratePerSec` particles per second.\n * `style.at` sets the node-local origin (default 0,0); the rest styles\n * particles exactly like `burst()`. Omitting `style` keeps the previous\n * emitter style (falling back to the `burst` preset if none was ever set).\n *\n * The signal form `emit(name, payload)` inherited from Node still works \u2014\n * the overload dispatches on the first argument's type.\n */\n override emit(ratePerSec: number, style?: ParticleStyle & { at?: Vec2 }): void;\n override emit<T>(name: string, payload: T): void;\n override emit(rateOrName: number | string, styleOrPayload?: unknown): void {\n if (typeof rateOrName === 'string') {\n super.emit(rateOrName, styleOrPayload);\n return;\n }\n this.emitRate = rateOrName;\n this.emitAcc = 0;\n const style = styleOrPayload as (ParticleStyle & { at?: Vec2 }) | undefined;\n if (style) {\n const { at, ...rest } = style;\n this.emitStyle = rest;\n this.emitOrigin = at ? { x: at.x, y: at.y } : { x: 0, y: 0 };\n } else if (!this.emitStyle) {\n this.emitStyle = PARTICLE_PRESETS.burst();\n }\n }\n\n /** Stop continuous emission. Live particles finish their lives naturally. */\n stopEmit(): void {\n this.emitRate = 0;\n this.emitAcc = 0;\n }\n\n protected override onProcess(dt: number): void {\n const drag = Math.max(0, 1 - this.drag * dt);\n let write = 0;\n for (const p of this.pool) {\n p.life += dt;\n if (p.life >= p.maxLife) continue;\n p.vy += this.gravity * dt;\n p.vx *= drag;\n p.vy *= drag;\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n this.pool[write++] = p;\n }\n this.pool.length = write;\n // Spawn AFTER the update so a particle emitted this tick behaves exactly\n // like a burst() issued this tick (integrated from the next tick on).\n if (this.emitRate > 0 && this.emitStyle) {\n this.emitAcc += this.emitRate * dt;\n const spawn = Math.floor(this.emitAcc);\n if (spawn > 0) {\n this.emitAcc -= spawn;\n this.burst(spawn, this.emitOrigin, this.emitStyle);\n }\n }\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n for (const p of this.pool) {\n const t = 1 - p.life / p.maxLife;\n out.push({\n kind: 'circle',\n cx: p.x,\n cy: p.y,\n radius: this.shrink ? p.size * t : p.size,\n fill: p.color,\n opacity: Math.min(1, t * 2),\n transform: world,\n z: this.z,\n transient: true,\n });\n }\n }\n\n get liveCount(): number {\n return this.pool.length;\n }\n}\n\n/** Ready-made styles for the common feel moments. */\nexport const PARTICLE_PRESETS = {\n dust: (colors = ['#c8c2b6', '#a09a8c']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 4, speedMin: 30, speedMax: 90, lifeMin: 0.2, lifeMax: 0.45, gravity: 300, drag: 3, shrink: true }),\n burst: (colors = ['#ffd75e', '#ff9d47', '#fff2c9']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 5, speedMin: 120, speedMax: 320, lifeMin: 0.25, lifeMax: 0.6, drag: 4, shrink: true }),\n hit: (colors = ['#ff5e5e', '#ffd0d0']): ParticleStyle => ({ colors, sizeMin: 2, sizeMax: 4, speedMin: 160, speedMax: 380, lifeMin: 0.15, lifeMax: 0.35, drag: 6, shrink: true }),\n sparkle: (colors = ['#9ef7ff', '#e8fdff', '#4ed8e8']): ParticleStyle => ({ colors, sizeMin: 1.5, sizeMax: 3.5, speedMin: 20, speedMax: 70, lifeMin: 0.4, lifeMax: 0.9, gravity: -40, drag: 2, shrink: true }),\n} as const;\n\n// \u2500\u2500 Ambient particle field (snow / rain / weather) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A distinct preset family from the burst emitters above: instead of one-shot\n// `burst()` events, an AmbientField seeds a FIXED set of particles across a\n// screen-sized region and drifts them continuously, wrapping at the edges so the\n// field is effectively infinite. Fully cosmetic \u2014 its own Rng, out of the hash.\n// Weather intensity is a smoothstep envelope over SIM time (fixed `dt` from the\n// clock), never wall-clock, so replays and peers see the same storm.\n\nexport interface AmbientStyle {\n /** Colors drawn from at random per particle. */\n colors: string[];\n /** Particle radius range (px). */\n sizeMin: number;\n sizeMax: number;\n /** Steady horizontal wind (px/s). */\n windX?: number;\n /** Fall speed (px/s, +y down). Snow \u2248 40, rain \u2248 600. */\n fallY: number;\n /** Horizontal sway amplitude (px) and frequency (Hz) \u2014 gives snow its wobble. */\n swayAmp?: number;\n swayFreq?: number;\n /** Draw vertical streaks instead of dots (rain). */\n streak?: boolean;\n /** Streak length (px) in streak mode. Default = fallY * 0.03. */\n streakLen?: number;\n}\n\n/** A single weather keyframe: `intensity` (0..1) reached at sim `time` (s). */\nexport interface WeatherKey {\n time: number;\n intensity: number;\n}\n\n/**\n * Smoothstep-interpolated weather intensity at sim time `t` over an ordered list\n * of keyframes. Before the first / after the last key it holds that key's value.\n * Pure \u2014 drive it with `world.time`, never wall-clock.\n */\nexport function weatherEnvelope(t: number, keys: readonly WeatherKey[]): number {\n if (keys.length === 0) return 1;\n if (t <= keys[0].time) return keys[0].intensity;\n for (let i = 1; i < keys.length; i++) {\n if (t <= keys[i].time) {\n const a = keys[i - 1];\n const b = keys[i];\n return a.intensity + (b.intensity - a.intensity) * smoothstep(a.time, b.time, t);\n }\n }\n return keys[keys.length - 1].intensity;\n}\n\ninterface AmbientParticle {\n x: number;\n y: number;\n size: number;\n color: string;\n /** Sway phase offset so particles don't wobble in lockstep. */\n phase: number;\n /** Per-particle fall-speed multiplier (parallax depth). */\n depth: number;\n}\n\n/**\n * A screen-wrapping ambient field for snow, rain, dust, or ash. Seed once with a\n * region size; it fills itself and drifts forever. Set `.envelope` to fade the\n * weather in/out over sim time. Always cosmetic.\n */\nexport class AmbientField extends Node {\n override readonly type: string = 'AmbientField';\n private rng: Rng;\n private field: AmbientParticle[] = [];\n private time = 0;\n private style: AmbientStyle;\n /** Field region (px). Particles wrap within [0,width] \u00D7 [0,height]. */\n width: number;\n height: number;\n /** Optional weather intensity schedule; scales count/opacity. */\n envelope?: WeatherKey[];\n\n constructor(\n config: NodeConfig & {\n seed?: number;\n count?: number;\n width: number;\n height: number;\n style: AmbientStyle;\n envelope?: WeatherKey[];\n },\n ) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 11);\n this.width = config.width;\n this.height = config.height;\n this.style = config.style;\n this.envelope = config.envelope;\n const count = config.count ?? 120;\n const s = this.style;\n for (let i = 0; i < count; i++) {\n this.field.push({\n x: this.rng.float() * this.width,\n y: this.rng.float() * this.height,\n size: s.sizeMin + this.rng.float() * (s.sizeMax - s.sizeMin),\n color: s.colors[this.rng.int(s.colors.length)],\n phase: this.rng.float() * TAU,\n depth: 0.5 + this.rng.float() * 0.5,\n });\n }\n }\n\n private intensity(): number {\n return this.envelope ? weatherEnvelope(this.time, this.envelope) : 1;\n }\n\n protected override onProcess(dt: number): void {\n this.time += dt;\n const s = this.style;\n const wind = s.windX ?? 0;\n const w = this.width;\n const h = this.height;\n for (const p of this.field) {\n p.y += s.fallY * p.depth * dt;\n p.x += wind * dt;\n // Wrap toroidally so the field never empties.\n if (p.y > h) p.y -= h;\n else if (p.y < 0) p.y += h;\n if (p.x > w) p.x -= w;\n else if (p.x < 0) p.x += w;\n }\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const s = this.style;\n const intensity = this.intensity();\n if (intensity <= 0) return;\n // Envelope thins the field: draw only the first `intensity` fraction.\n const shown = Math.round(this.field.length * intensity);\n const swayAmp = s.swayAmp ?? 0;\n const swayFreq = s.swayFreq ?? 0;\n for (let i = 0; i < shown; i++) {\n const p = this.field[i];\n const sway = swayAmp !== 0 ? dsin(this.time * swayFreq * TAU + p.phase) * swayAmp : 0;\n const x = p.x + sway;\n if (s.streak) {\n const len = s.streakLen ?? s.fallY * 0.03;\n out.push({\n kind: 'poly',\n points: [x, p.y, x, p.y + len],\n closed: false,\n stroke: p.color,\n strokeWidth: p.size,\n opacity: intensity,\n transform: world,\n z: this.z,\n transient: true,\n });\n } else {\n out.push({\n kind: 'circle',\n cx: x,\n cy: p.y,\n radius: p.size,\n fill: p.color,\n opacity: intensity,\n transform: world,\n z: this.z,\n transient: true,\n });\n }\n }\n }\n\n get liveCount(): number {\n return this.field.length;\n }\n}\n\n/** Ready-made ambient weather styles (pair with `AmbientField`). */\nexport const AMBIENT_PRESETS = {\n snow: (colors = ['#ffffff', '#e8f0f8', '#cdd9e6']): AmbientStyle => ({ colors, sizeMin: 1.5, sizeMax: 3.5, windX: 8, fallY: 42, swayAmp: 14, swayFreq: 0.25 }),\n rain: (colors = ['#9fb4c8', '#c3d2e0']): AmbientStyle => ({ colors, sizeMin: 1, sizeMax: 1.8, windX: -40, fallY: 620, streak: true, streakLen: 16 }),\n ash: (colors = ['#6b6b6b', '#8a8580', '#3d3a36']): AmbientStyle => ({ colors, sizeMin: 1, sizeMax: 2.5, windX: 14, fallY: 26, swayAmp: 20, swayFreq: 0.18 }),\n} as const;\n\n/**\n * Screen shake as a cosmetic camera offset with its own Rng and exponential\n * decay. Attach to whatever node the camera follows and read `offset` into the\n * camera's position AFTER canonical follow logic \u2014 or simpler, add the shaker\n * as the camera's parent so the offset composes for free.\n */\nexport class Shaker extends Node {\n override readonly type: string = 'Shaker';\n private rng: Rng;\n private trauma = 0;\n /** Max offset in px at full trauma. */\n amplitude: number;\n /** Trauma decay per second. */\n decay: number;\n\n constructor(config: NodeConfig & { seed?: number; amplitude?: number; decay?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 99);\n this.amplitude = config.amplitude ?? 14;\n this.decay = config.decay ?? 2.6;\n }\n\n /** Add shake (0..1). Stacks, clamped to 1. Quadratic falloff feels right. */\n addTrauma(amount: number): void {\n this.trauma = Math.min(1, this.trauma + amount);\n }\n\n protected override onProcess(dt: number): void {\n this.trauma = Math.max(0, this.trauma - this.decay * dt);\n const s = this.trauma * this.trauma * this.amplitude;\n this.pos.x = (this.rng.float() * 2 - 1) * s;\n this.pos.y = (this.rng.float() * 2 - 1) * s;\n }\n}\n", "// Floating combat text: pooled rise-and-fade numbers/labels \u2014 the damage popups\n// every action/survivors/RPG game leans on. Cosmetic by construction, exactly\n// like Particles/Shaker: its own tiny Rng stream (never the world's, so deleting\n// it changes no game outcome), excluded from hashing, driven by the fixed dt.\n// Emission is triggered by sim events (hit for 12, healed, crit!), so replays\n// reproduce identical popups without any canonical state depending on them.\n\nimport { clamp } from '../core/math';\nimport { Rng } from '../core/rng';\nimport type { Transform, Vec2 } from '../core/math';\nimport type { DrawCommand, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\n\nexport interface FloatStyle {\n /** Text colour. */\n color: string;\n /** Font size in px. */\n size?: number;\n font?: string;\n weight?: number;\n align?: TextAlign;\n /** Upward speed in px/s (screen +y is down, so this is negated internally). */\n rise?: number;\n /** Gravity pulling the rise back down (px/s\u00B2) \u2014 arcs the pop. */\n gravity?: number;\n /** Lifetime in seconds. */\n life?: number;\n /** Random horizontal spread of the launch (px/s). */\n jitter?: number;\n /** Fraction of life spent fading out at the end (0..1, default 0.4). */\n fade?: number;\n}\n\ninterface Popup {\n x: number;\n y: number;\n vx: number;\n vy: number;\n life: number;\n maxLife: number;\n text: string;\n color: string;\n size: number;\n font?: string;\n weight?: number;\n align: TextAlign;\n fade: number;\n}\n\n/**\n * A pooled floating-text emitter. Call `pop(text, at, style)` from game code in\n * response to feel events. Always cosmetic; add it wherever the numbers should\n * live in the tree (usually the world layer, so pops ride the camera).\n */\nexport class FloatingText extends Node {\n override readonly type: string = 'FloatingText';\n private pool: Popup[] = [];\n private rng: Rng;\n /** Cap on live popups (oldest recycled first). */\n maxPopups: number;\n\n constructor(config: NodeConfig & { seed?: number; maxPopups?: number } = {}) {\n super(config);\n this.cosmetic = true;\n this.rng = new Rng(config.seed ?? 31);\n this.maxPopups = config.maxPopups ?? 128;\n }\n\n /** Spawn one popup at `at` (in this node's local space). */\n pop(text: string, at: Vec2, style: FloatStyle): void {\n const jitter = style.jitter ?? 0;\n const p: Popup = {\n x: at.x + (this.rng.float() - 0.5) * jitter * 0.1,\n y: at.y,\n vx: (this.rng.float() - 0.5) * jitter,\n vy: -(style.rise ?? 60),\n life: 0,\n maxLife: Math.max(0.05, style.life ?? 0.9),\n text,\n color: style.color,\n size: style.size ?? 20,\n font: style.font,\n weight: style.weight,\n align: style.align ?? 'center',\n fade: clamp(style.fade ?? 0.4, 0, 1),\n };\n // Stash the shared gravity for the update step (single-style is the common case).\n this.gravity = style.gravity ?? 0;\n if (this.pool.length >= this.maxPopups) this.pool.shift();\n this.pool.push(p);\n }\n\n private gravity = 0;\n\n protected override onProcess(dt: number): void {\n let write = 0;\n for (const p of this.pool) {\n p.life += dt;\n if (p.life >= p.maxLife) continue;\n p.vy += this.gravity * dt;\n p.x += p.vx * dt;\n p.y += p.vy * dt;\n this.pool[write++] = p;\n }\n this.pool.length = write;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n for (const p of this.pool) {\n const t = p.life / p.maxLife; // 0..1 through life\n const fadeStart = 1 - p.fade;\n const opacity = t < fadeStart ? 1 : clamp(1 - (t - fadeStart) / Math.max(1e-4, p.fade), 0, 1);\n out.push({\n kind: 'text',\n text: p.text,\n x: p.x,\n y: p.y,\n size: p.size,\n font: p.font,\n weight: p.weight,\n align: p.align,\n fill: p.color,\n opacity,\n transform: world,\n z: this.z,\n transient: true, // drifting popup \u2014 layout lints skip it (see verify/layout)\n });\n }\n }\n\n get liveCount(): number {\n return this.pool.length;\n }\n}\n\n/** Ready-made popup looks for the common combat moments. */\nexport const FLOAT_PRESETS = {\n damage: (color = '#e14b4b'): FloatStyle => ({ color, size: 22, weight: 700, rise: 70, gravity: 120, life: 0.8, jitter: 40, fade: 0.4 }),\n crit: (color = '#ffb020'): FloatStyle => ({ color, size: 32, weight: 800, rise: 100, gravity: 160, life: 1.0, jitter: 60, fade: 0.35 }),\n heal: (color = '#4bb06a'): FloatStyle => ({ color, size: 20, weight: 700, rise: 55, gravity: 40, life: 1.0, jitter: 20, fade: 0.5 }),\n label: (color = '#3d3323'): FloatStyle => ({ color, size: 18, weight: 600, rise: 40, gravity: 0, life: 1.2, jitter: 0, fade: 0.5 }),\n} as const;\n", "// VerletChain \u2014 an N-segment verlet rope/streamer node for character\n// appendages (tails, scarves), ropes, and banners. The head is pinned to the\n// node's own position, so parenting it to a character makes the chain trail\n// and flick as the character moves; an optional tail pin turns it into a\n// hanging banner. COSMETIC by default: the chain is pure view (springy motion\n// derived from where the node went), so it stays out of world.hash() and can\n// be deleted without changing any game outcome. The simulation itself is\n// deterministic \u2014 plain loops on fixed dt, no rng, allocation-free hot path \u2014\n// so replays wave the same flag the same way.\n\nimport { datan2 } from '../core/dmath';\nimport { invertTransform, type Transform, type Vec2 } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { Node, type NodeConfig } from './node';\n\nexport interface VerletChainConfig extends NodeConfig {\n /** Number of segments (points = segments + 1). */\n segments: number;\n /** Total rest length of the chain, px. */\n length: number;\n /** Acceleration applied to free points, px/s\u00B2 in WORLD space (+y is down). */\n gravity?: Vec2;\n /** Per-step velocity retention 0..1 (1 = undamped). Default 0.985. */\n damping?: number;\n /** Constraint-relaxation passes per step. Default 3. */\n iterations?: number;\n /** Pin the tail too (set `tailTarget` for where). Default false. */\n pinTail?: boolean;\n /** Stroke color for draw(). Default '#333'. */\n stroke?: string;\n /** Stroke width at the head, px. Default 3. */\n strokeWidth?: number;\n /** Taper the stroke toward the tail (draws per-segment polys). Default false. */\n taper?: boolean;\n}\n\n/**\n * The rope node. Read `points` (node-local) to attach child sprites along the\n * chain, `segmentAngle(i)` to orient them, and call `impulse(v)` to flick it.\n */\nexport class VerletChain extends Node {\n override readonly type: string = 'VerletChain';\n\n gravity: Vec2;\n damping: number;\n iterations: number;\n pinTail: boolean;\n stroke: string;\n strokeWidth: number;\n taper: boolean;\n /**\n * Where the tail is pinned when `pinTail` is true, in NODE-LOCAL space\n * (same space as `points`). null leaves the tail free even with pinTail set.\n */\n tailTarget: Vec2 | null = null;\n\n readonly segments: number;\n /** Rest length of one segment. */\n readonly segmentLength: number;\n\n // World-space simulation state (flat arrays: allocation-free hot path).\n private px: Float64Array;\n private py: Float64Array;\n private prevx: Float64Array;\n private prevy: Float64Array;\n /** Node-local mirror of the sim points, updated after each step. */\n private readonly local: Vec2[];\n private initialized = false;\n // Pending impulse (world px/s), applied to free points on the next step.\n private impX = 0;\n private impY = 0;\n\n constructor(config: VerletChainConfig) {\n super(config);\n this.cosmetic = true;\n this.segments = Math.max(1, Math.floor(config.segments));\n this.segmentLength = config.length / this.segments;\n this.gravity = config.gravity ? { ...config.gravity } : { x: 0, y: 600 };\n this.damping = config.damping ?? 0.985;\n this.iterations = Math.max(1, config.iterations ?? 3);\n this.pinTail = config.pinTail ?? false;\n this.stroke = config.stroke ?? '#333';\n this.strokeWidth = config.strokeWidth ?? 3;\n this.taper = config.taper ?? false;\n const n = this.segments + 1;\n this.px = new Float64Array(n);\n this.py = new Float64Array(n);\n this.prevx = new Float64Array(n);\n this.prevy = new Float64Array(n);\n this.local = [];\n for (let i = 0; i < n; i++) this.local.push({ x: 0, y: i * this.segmentLength });\n }\n\n /**\n * Chain points in NODE-LOCAL space, head first (`points[0]` \u2248 {0,0}).\n * The Vec2 objects are reused across steps \u2014 read, don't retain copies-by-ref.\n */\n get points(): readonly Vec2[] {\n return this.local;\n }\n\n /**\n * Direction of segment i (0..segments-1) in node-local space, radians\n * (0 = +x, y-down screen convention). Map child sprites to segments with\n * `sprite.pos = chain.points[i]; sprite.rotation = chain.segmentAngle(i)`.\n */\n segmentAngle(i: number): number {\n const a = this.local[i];\n const b = this.local[i + 1];\n return datan2(b.y - a.y, b.x - a.x);\n }\n\n /** Flick the chain: add a velocity (world px/s) to every free point next step. */\n impulse(v: Vec2): void {\n this.impX += v.x;\n this.impY += v.y;\n }\n\n protected override onProcess(dt: number): void {\n const wt = this.worldTransform();\n const headX = wt.e;\n const headY = wt.f;\n const n = this.segments + 1;\n const px = this.px;\n const py = this.py;\n const prevx = this.prevx;\n const prevy = this.prevy;\n\n if (!this.initialized) {\n // Lay the chain out from the head along +y (world), at rest.\n for (let i = 0; i < n; i++) {\n px[i] = headX;\n py[i] = headY + i * this.segmentLength;\n prevx[i] = px[i];\n prevy[i] = py[i];\n }\n this.initialized = true;\n }\n\n // Tail pin target in world space (tailTarget is node-local).\n const tailPinned = this.pinTail && this.tailTarget !== null;\n let tailX = 0;\n let tailY = 0;\n if (tailPinned) {\n const t = this.tailTarget as Vec2;\n tailX = wt.a * t.x + wt.c * t.y + wt.e;\n tailY = wt.b * t.x + wt.d * t.y + wt.f;\n }\n\n // Verlet integration (free points only; head \u2014 and pinned tail \u2014 are set).\n const gdt2x = this.gravity.x * dt * dt;\n const gdt2y = this.gravity.y * dt * dt;\n const impDx = this.impX * dt;\n const impDy = this.impY * dt;\n const damp = this.damping;\n const last = n - 1;\n for (let i = 1; i < n; i++) {\n if (tailPinned && i === last) continue;\n const x = px[i];\n const y = py[i];\n px[i] = x + (x - prevx[i]) * damp + gdt2x + impDx;\n py[i] = y + (y - prevy[i]) * damp + gdt2y + impDy;\n prevx[i] = x;\n prevy[i] = y;\n }\n this.impX = 0;\n this.impY = 0;\n\n // Constraint relaxation: pin ends, then enforce segment rest lengths.\n const rest = this.segmentLength;\n for (let k = 0; k < this.iterations; k++) {\n px[0] = headX;\n py[0] = headY;\n if (tailPinned) {\n px[last] = tailX;\n py[last] = tailY;\n }\n for (let i = 0; i < last; i++) {\n const dx = px[i + 1] - px[i];\n const dy = py[i + 1] - py[i];\n const d = Math.sqrt(dx * dx + dy * dy);\n if (d === 0) continue;\n const diff = (d - rest) / d;\n // Head never moves; pinned tail never moves; otherwise split the error.\n const aFixed = i === 0;\n const bFixed = tailPinned && i + 1 === last;\n if (aFixed && bFixed) continue;\n const wA = aFixed ? 0 : bFixed ? 1 : 0.5;\n const wB = bFixed ? 0 : aFixed ? 1 : 0.5;\n px[i] += dx * diff * wA;\n py[i] += dy * diff * wA;\n px[i + 1] -= dx * diff * wB;\n py[i + 1] -= dy * diff * wB;\n }\n }\n px[0] = headX;\n py[0] = headY;\n if (tailPinned) {\n px[last] = tailX;\n py[last] = tailY;\n }\n\n // Mirror into node-local space (mutate the reusable Vec2s \u2014 no allocs).\n const inv = invertTransform(wt);\n for (let i = 0; i < n; i++) {\n const p = this.local[i];\n const wx = px[i];\n const wy = py[i];\n p.x = inv.a * wx + inv.c * wy + inv.e;\n p.y = inv.b * wx + inv.d * wy + inv.f;\n }\n }\n\n /**\n * Stroked open poly of the chain. `points` are node-local and `world` is the\n * self-inclusive world transform handed to draw(), so commands emit with it\n * directly. With `taper`, each segment is its own 2-point poly at a linearly\n * decreasing width (segments are few, so this stays cheap); otherwise one poly.\n */\n protected override draw(out: DrawCommand[], world: Transform): void {\n const n = this.local.length;\n if (n < 2) return;\n if (this.taper) {\n for (let i = 0; i < n - 1; i++) {\n const a = this.local[i];\n const b = this.local[i + 1];\n const t = 1 - i / (n - 1); // 1 at the head \u2192 thin at the tail\n out.push({\n kind: 'poly',\n points: [a.x, a.y, b.x, b.y],\n closed: false,\n stroke: this.stroke,\n strokeWidth: Math.max(0.5, this.strokeWidth * t),\n round: true,\n transform: world,\n z: this.z,\n transient: true,\n });\n }\n return;\n }\n const pts: number[] = [];\n for (const p of this.local) pts.push(p.x, p.y);\n out.push({\n kind: 'poly',\n points: pts,\n closed: false,\n stroke: this.stroke,\n strokeWidth: this.strokeWidth,\n round: true,\n transform: world,\n z: this.z,\n transient: true,\n });\n }\n}\n", "// Node type registry \u2192 lets a serialized tree (save file / prefab / snapshot)\n// be rebuilt into live nodes. Built-in types register here; games can register\n// custom node types the same way.\n\nimport { Node, type SerializedNode } from './node';\nimport { Sprite, Text, Camera2D, Timer } from './nodes';\nimport { AnimationPlayer } from './tween';\n\nexport type NodeFactory = () => Node;\n\nconst registry = new Map<string, NodeFactory>();\n\nexport function registerNode(type: string, factory: NodeFactory): void {\n registry.set(type, factory);\n}\n\n// Built-ins. Sprite/Text/Timer need required config, so provide safe defaults\n// that applyProps() immediately overwrites during deserialization.\nregisterNode('Node', () => new Node());\nregisterNode('Sprite', () => new Sprite({ shape: { kind: 'rect', w: 1, h: 1 } }));\nregisterNode('Text', () => new Text({ text: '' }));\nregisterNode('Camera2D', () => new Camera2D());\nregisterNode('Timer', () => new Timer({ duration: 1 }));\nregisterNode('AnimationPlayer', () => new AnimationPlayer());\n\n/** Rebuild a live node tree from serialized data. */\nexport function deserializeNode(data: SerializedNode): Node {\n const factory = registry.get(data.type);\n if (!factory) throw new Error(`hayao: unknown node type \"${data.type}\" (register it first)`);\n const node = factory();\n node.name = data.name;\n node.pos = { ...data.pos };\n node.rotation = data.rotation;\n node.scale = { ...data.scale };\n node.z = data.z;\n node.visible = data.visible;\n if (data.pivot) node.pivot = { ...data.pivot };\n // Base flags travel in props (only when non-default) \u2014 restore before subclass props.\n if (data.props.pauseMode === 'always' || data.props.pauseMode === 'stopped') node.pauseMode = data.props.pauseMode;\n if (data.props.screenSpace === true) node.screenSpace = true;\n node.applyProps(data.props);\n for (const child of data.children) node.addChild(deserializeNode(child));\n return node;\n}\n", "// Input as ACTIONS, not keys. Game logic asks \"is 'jump' down?\", never \"is 'KeyZ'\n// down?\". Input is sampled once per fixed step, so a run is a pure function of its\n// input log \u2014 which is what makes replay and scripted playthroughs exact.\n\n/**\n * action name \u2192 physical bindings (KeyboardEvent.code strings, or pointer\n * buttons `mouse.left` / `mouse.right` / `mouse.middle`). Readonly on both\n * levels so `as const` maps type-check without casts.\n */\nexport type InputMap = Readonly<Record<string, readonly string[]>>;\n\n/** Per-frame analog axis values (already quantized). Recorded into the log + hash. */\nexport type AxisFrame = Record<string, number>;\n\nexport class InputState {\n private down = new Set<string>();\n private prev = new Set<string>();\n /**\n * Analog axes (e.g. from pointer or gamepad), sampled per step. By default\n * these are LIVE host samples \u2014 NOT hashed or logged (see PointerSource).\n * Axes passed to `beginFrame`'s second argument are the exception: they are\n * *logged* (enter `getState()` \u2192 hash, and the input log), so quantized analog\n * aim replays bit-exactly. Both live and logged values read back via `axis()`.\n */\n readonly axes = new Map<string, number>();\n /** The subset of axes that are part of the deterministic log + hash this frame. */\n private logged = new Map<string, number>();\n /**\n * Action names some source has declared it can produce (null until the first\n * declareActions call). Headless worlds with no sources never declare, so\n * they never warn \u2014 the typo guard only arms once a host wires real input.\n */\n private declared: Set<string> | null = null;\n /** Unknown names already warned about (warn ONCE per name). */\n private warned = new Set<string>();\n\n /**\n * Register action names a source (or input map) can produce. The browser\n * driver declares the keyboard map's actions and the pointer's `mouse.*`\n * buttons; custom sources should declare theirs too. Once at least one\n * declaration has happened, querying an undeclared action name via\n * `isDown`/`justPressed`/`justReleased` logs a console.warn ONCE per name \u2014\n * catching `isDown('jmup')` typos that would otherwise fail silently.\n */\n declareActions(names: Iterable<string>): void {\n this.declared ??= new Set();\n for (const n of names) this.declared.add(n);\n }\n\n /** Warn-once guard for querying an action no source has declared. O(1). */\n private checkDeclared(action: string): void {\n if (this.declared === null || this.declared.has(action) || this.warned.has(action)) return;\n this.warned.add(action);\n console.warn(\n `hayao: input action \"${action}\" is not declared by any input source \u2014 ` +\n `declared actions: ${[...this.declared].sort().join(', ') || '(none)'}`\n );\n }\n\n /**\n * Engine: set which actions are down this step (from live input or replay).\n * `axes` (optional) are QUANTIZED analog values that become part of the log\n * and hash for this frame \u2014 use `snapAxis`/`quantizeAngle` at the host edge so\n * replay and lockstep netplay reproduce analog aim exactly.\n */\n beginFrame(actionsDown: Iterable<string>, axes?: AxisFrame): void {\n this.prev = new Set(this.down);\n this.down = new Set(actionsDown);\n // Any action a frame actually delivers is by definition producible \u2014 count\n // it as declared so virtual taps (input.press('fire')) never false-warn.\n // Typos in QUERIES never appear here, so the guard still catches them.\n if (this.declared !== null) for (const a of this.down) this.declared.add(a);\n this.logged.clear();\n if (axes) {\n for (const k in axes) {\n this.logged.set(k, axes[k]);\n this.axes.set(k, axes[k]);\n }\n }\n }\n\n isDown(action: string): boolean {\n this.checkDeclared(action);\n return this.down.has(action);\n }\n justPressed(action: string): boolean {\n this.checkDeclared(action);\n return this.down.has(action) && !this.prev.has(action);\n }\n justReleased(action: string): boolean {\n this.checkDeclared(action);\n return !this.down.has(action) && this.prev.has(action);\n }\n axis(name: string): number {\n return this.axes.get(name) ?? 0;\n }\n\n /** The current down-set as a stable sorted array (for recording). */\n snapshot(): string[] {\n return [...this.down].sort();\n }\n\n getState(): { down: string[]; prev: string[]; axes?: Array<[string, number]> } {\n const s: { down: string[]; prev: string[]; axes?: Array<[string, number]> } = {\n down: [...this.down].sort(),\n prev: [...this.prev].sort(),\n };\n // Only emit axes when present, so games that never use logged axes keep their\n // pinned hashes byte-for-byte.\n if (this.logged.size > 0) s.axes = [...this.logged].sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n return s;\n }\n setState(s: { down: string[]; prev: string[]; axes?: Array<[string, number]> }): void {\n this.down = new Set(s.down);\n this.prev = new Set(s.prev);\n this.logged.clear();\n if (s.axes) for (const [k, v] of s.axes) {\n this.logged.set(k, v);\n this.axes.set(k, v);\n }\n }\n}\n\n/**\n * Quantize an analog value into `buckets` levels across `[min,max]` and return\n * the SNAPPED value (deterministic \u2014 same input \u2192 same output on every engine).\n * Feed the result through `beginFrame`'s axes so analog input is replay-exact.\n */\nexport function snapAxis(value: number, buckets: number, min = -1, max = 1): number {\n if (buckets < 2 || max === min) return value;\n const t = Math.min(1, Math.max(0, (value - min) / (max - min)));\n const b = Math.round(t * (buckets - 1));\n return min + (b / (buckets - 1)) * (max - min);\n}\n\n/** Snap an angle (radians) to the nearest of `buckets` evenly-spaced headings. */\nexport function quantizeAngle(radians: number, buckets: number): number {\n const step = (Math.PI * 2) / buckets;\n return Math.round(radians / step) * step;\n}\n\n/** Map a set of raw key codes to the set of actions they trigger. */\nexport function keysToActions(map: InputMap, keysDown: Set<string>): string[] {\n const actions: string[] = [];\n for (const action in map) {\n if (map[action].some((k) => keysDown.has(k))) actions.push(action);\n }\n return actions.sort();\n}\n\n/** Records the per-frame action-down sets \u2192 a compact, replayable input log. */\nexport class InputRecorder {\n private frames: string[][] = [];\n private axes: Array<AxisFrame | undefined> = [];\n private anyAxes = false;\n\n record(actionsDown: string[], axes?: AxisFrame): void {\n this.frames.push(actionsDown.slice().sort());\n if (axes && Object.keys(axes).length > 0) {\n this.axes.push({ ...axes });\n this.anyAxes = true;\n } else {\n this.axes.push(undefined);\n }\n }\n\n get length(): number {\n return this.frames.length;\n }\n\n toLog(): InputLog {\n const log: InputLog = { frames: this.frames.map((f) => f.slice()) };\n // Only carry the axes track when at least one frame had logged axes.\n if (this.anyAxes) log.axes = this.axes.map((a) => (a ? { ...a } : undefined));\n return log;\n }\n}\n\nexport interface InputLog {\n frames: string[][];\n /** Optional per-frame quantized analog axes, aligned to `frames` (absent = none). */\n axes?: Array<AxisFrame | undefined>;\n}\n\n/** Replays a recorded log: returns the action set for frame index i. */\nexport function frameActions(log: InputLog, i: number): string[] {\n return log.frames[i] ?? [];\n}\n\n/** The logged analog axes for frame index i, or undefined if none were recorded. */\nexport function frameAxes(log: InputLog, i: number): AxisFrame | undefined {\n return log.axes?.[i];\n}\n\n/** A default set of common bindings games can start from. */\nexport const DEFAULT_INPUT_MAP: InputMap = {\n up: ['ArrowUp', 'KeyW'],\n down: ['ArrowDown', 'KeyS'],\n left: ['ArrowLeft', 'KeyA'],\n right: ['ArrowRight', 'KeyD'],\n confirm: ['Enter', 'Space'],\n cancel: ['Escape', 'Backspace'],\n action: ['KeyZ', 'KeyJ'],\n action2: ['KeyX', 'KeyK'],\n undo: ['KeyU'],\n restart: ['KeyR'],\n};\n", "// Browser input source: tracks physical keys and maps them to actions each step.\n// Kept separate from InputState so the pure sim never imports DOM.\n//\n// The INPUT-SOURCE CONTRACT (for custom sources like GamepadSource):\n// - Implement sample(input: InputState): void \u2014 called once per fixed step,\n// BEFORE world.advance(), to write quantized values into input.axes.\n// - Optionally implement dispose(): void \u2014 called when the source is removed.\n// - Axis key naming: dotted namespace, e.g. \"gamepad.lx\", \"pointer.x\".\n// - QUANTIZE at the host edge (snapAxis / quantizeAngle) before writing axes\n// so recorded logs replay bit-exactly on any machine.\n// - For discrete input (button press \u2192 action), call keyboard.setHeld(action)\n// so presses enter the same deterministic action log as keys.\n// - Axes written by sample() are NOT part of world.hash() by default. To make\n// analog input hash/replay-exact, pass the quantized axes as the second arg\n// to world.step(actions, axes) \u2014 they then enter getState() and the log.\n// See docs/CONVENTIONS.md \u00A7\"Custom input sources\" for full details.\n\nimport { keysToActions, type InputMap, type InputState } from './actions';\n\n/**\n * Minimal contract for a host-side input source. Implement this to feed any\n * hardware (gamepad, MIDI, accelerometer, on-screen controls) into the sim's\n * InputState.axes without touching the engine internals.\n *\n * The engine samples each registered source once per fixed step, BEFORE\n * world.advance(). Register via RunOptions.sources or GameHandle.addSource().\n */\nexport interface InputSource {\n /** Write quantized values into input.axes. Called before each world.advance(). */\n sample(input: InputState): void;\n /** Optional cleanup (remove listeners, release held actions). */\n dispose?(): void;\n}\nimport type { Vec2 } from '../core/math';\n\nexport class KeyboardSource {\n private keysDown = new Set<string>();\n /** Virtual action taps (from DOM buttons etc.) pending consumption by a step. */\n private pressed = new Set<string>();\n /** Sustained virtual actions (held on-screen controls) \u2014 persist until released. */\n private held = new Set<string>();\n private map: InputMap;\n private target: Document | HTMLElement;\n private onDown: (e: KeyboardEvent) => void;\n private onUp: (e: KeyboardEvent) => void;\n private onBlur: () => void;\n\n constructor(map: InputMap, target: Document | HTMLElement = document) {\n this.map = map;\n this.target = target;\n this.onDown = (e) => {\n this.keysDown.add(e.code);\n // Prevent scroll on arrows/space during play.\n if (e.code.startsWith('Arrow') || e.code === 'Space') e.preventDefault();\n };\n this.onUp = (e) => this.keysDown.delete(e.code);\n this.onBlur = () => this.keysDown.clear();\n target.addEventListener('keydown', this.onDown as EventListener);\n target.addEventListener('keyup', this.onUp as EventListener);\n globalThis.addEventListener?.('blur', this.onBlur);\n }\n\n /** The actions currently held down, as a stable sorted array. */\n currentActions(): string[] {\n // Held entries double as binding codes: PointerSource holds `mouse.right`\n // etc., so a map binding like `shield: ['mouse.right']` resolves exactly\n // like a key code. Held names also pass through as actions themselves.\n const codes = this.held.size === 0 ? this.keysDown : new Set([...this.keysDown, ...this.held]);\n const acts = keysToActions(this.map, codes);\n if (this.pressed.size === 0 && this.held.size === 0) return acts;\n const merged = new Set(acts);\n for (const a of this.pressed) merged.add(a);\n for (const a of this.held) merged.add(a);\n return [...merged].sort();\n }\n\n /** The action names this source's map can produce (for InputState.declareActions). */\n actionNames(): string[] {\n return Object.keys(this.map);\n }\n\n /**\n * Virtually tap an action (DOM button, touch control). The tap is held until\n * at least one fixed step has sampled it \u2014 the driver calls clearPressed()\n * after a successful advance \u2014 so UI clicks enter the SAME deterministic\n * input log as keys, and record/replay covers them.\n */\n press(action: string): void {\n this.pressed.add(action);\n }\n\n /** Consume pending virtual taps (driver-called after \u22651 step ran). */\n clearPressed(): void {\n this.pressed.clear();\n }\n\n /**\n * Sustain an action for as long as an on-screen control is held. Unlike\n * `press()` (an edge-shaped tap cleared after one step), a held action models\n * STATE: it stays in `currentActions()` every step until `setHeld(action,\n * false)` / `releaseHeld(action)`. This is what a virtual joystick or\n * hold-to-fire button wants \u2014 set it on drag-start, clear it on release, no\n * re-press-per-frame. Held actions still flow through the same deterministic\n * action set as keys.\n */\n setHeld(action: string, on = true): void {\n if (on) this.held.add(action);\n else this.held.delete(action);\n }\n\n /** Release a sustained action (sugar for `setHeld(action, false)`). */\n releaseHeld(action: string): void {\n this.held.delete(action);\n }\n\n /** Drop all sustained actions (e.g. on blur / control teardown). */\n clearHeld(): void {\n this.held.clear();\n }\n\n setMap(map: InputMap): void {\n this.map = map;\n }\n\n dispose(): void {\n this.target.removeEventListener('keydown', this.onDown as EventListener);\n this.target.removeEventListener('keyup', this.onUp as EventListener);\n globalThis.removeEventListener?.('blur', this.onBlur);\n }\n}\n\n/** A live pointer reading, in DESIGN space (already un-letterboxed). */\nexport interface PointerReadout {\n /** Design-space x. Falls outside 0..width when the pointer leaves the letterbox. */\n x: number;\n y: number;\n /** Is the primary pointer/finger currently pressed? */\n down: boolean;\n /** Has the pointer ever produced an event (else x/y are a neutral 0,0)? */\n active: boolean;\n /** Stable per-touch id (from PointerEvent.pointerId). Absent on the primary hover readout. */\n id?: number;\n}\n\n/** What a PointerSource needs from a renderer: the DOM node + the design mapper. */\nexport interface PointerTarget {\n readonly element?: HTMLElement | SVGElement;\n toDesign?(clientX: number, clientY: number): Vec2;\n}\n\nexport interface PointerSourceOptions {\n /**\n * Allow the browser's context menu on the attached element. Default false \u2014\n * the menu is suppressed (preventDefault on 'contextmenu') so right-click is\n * usable as game input.\n */\n contextMenu?: boolean;\n /**\n * Route pointer buttons into the deterministic action pipeline: while a\n * button is held, `sample()` calls `keyboard.setHeld('mouse.left' |\n * 'mouse.right' | 'mouse.middle')` so buttons enter the SAME actionsDown log\n * as keys \u2014 `justPressed('mouse.right')` works, replays stay exact, and an\n * inputMap can bind them (`shield: ['mouse.right']`). The browser driver\n * wires this to the GameHandle's KeyboardSource automatically.\n */\n keyboard?: KeyboardSource;\n}\n\n/** The pointer-button action names PointerSource can hold (via its keyboard). */\nexport const MOUSE_ACTIONS = ['mouse.left', 'mouse.right', 'mouse.middle'] as const;\n\n/**\n * Continuous pointer / touch input \u2014 the sibling of KeyboardSource for games\n * driven by *where* the cursor is (slice, aim, drag, point-and-click, placement).\n * It listens on the renderer's canvas, converts every event to DESIGN space via\n * `renderer.toDesign`, and each fixed step writes the sample into InputState's\n * analog axes: `pointer.x`, `pointer.y`, `pointer.down` (1/0), plus\n * `pointer.right` / `pointer.middle` (1/0) for the secondary mouse buttons\n * (the context menu is suppressed by default so right-click is usable \u2014 see\n * PointerSourceOptions). Sim code then reads `world.input.axis('pointer.x')`\n * \u2014 no out-of-engine letterbox glue. With `keyboard` wired, buttons also enter\n * the action pipeline as `mouse.left/right/middle` (bindable in an inputMap,\n * `justPressed`-able, replay-exact).\n *\n * Determinism note: axes are host-sampled live input and are NOT part of the\n * string input log or the world hash. `sample()` QUANTIZES design coords to a\n * 1/8-px grid so a recorded axes log (Studio sessions) replays bit-exactly \u2014\n * the sim only ever sees the quantized values, live or replayed. For lockstep\n * netplay, still prefer discrete actions (map a tap to a key via\n * KeyboardSource.press, or snap position to a grid cell). See docs/CONVENTIONS.md.\n *\n * Multitouch: `read()`/`sample()` describe the PRIMARY pointer (mouse or the\n * most-recent finger) and are byte-identical to the single-pointer past. For\n * dual-stick / multi-finger schemes, read every live touch via `readAll()` \u2014\n * each carries its stable `id` so you can tell which finger is which.\n */\nexport class PointerSource {\n private clientX = 0;\n private clientY = 0;\n private isDown = false;\n private rightDown = false;\n private middleDown = false;\n private seen = false;\n /** Live touches by pointerId (a pressed finger/button); excludes hover-only mouse. */\n private touches = new Map<number, { clientX: number; clientY: number }>();\n private target: PointerTarget;\n private el: EventTarget | undefined;\n private keyboard: KeyboardSource | undefined;\n private onMove: (e: PointerEvent) => void;\n private onDown: (e: PointerEvent) => void;\n private onUp: (e: PointerEvent) => void;\n private onCtx: (e: Event) => void;\n\n constructor(target: PointerTarget, opts: PointerSourceOptions = {}) {\n this.target = target;\n this.el = target.element;\n this.keyboard = opts.keyboard;\n // Chorded button changes (right pressed while left held) arrive as\n // pointermove per the Pointer Events spec, so every handler reads the\n // `buttons` bitmask (1=left/touch, 2=right, 4=middle) when present.\n const readButtons = (e: PointerEvent): boolean => {\n if (typeof e.buttons !== 'number') return false;\n this.isDown = (e.buttons & 1) !== 0;\n this.rightDown = (e.buttons & 2) !== 0;\n this.middleDown = (e.buttons & 4) !== 0;\n return true;\n };\n this.onMove = (e) => {\n this.clientX = e.clientX;\n this.clientY = e.clientY;\n this.seen = true;\n // Hover-only moves carry buttons=0 and must not clear a press tracked\n // from pointerdown \u2014 only chorded changes (some button held) apply.\n if (typeof e.buttons === 'number' && e.buttons !== 0) readButtons(e);\n const t = this.touches.get(e.pointerId);\n if (t) {\n t.clientX = e.clientX;\n t.clientY = e.clientY;\n }\n };\n this.onDown = (e) => {\n this.clientX = e.clientX;\n this.clientY = e.clientY;\n this.seen = true;\n if (!readButtons(e)) {\n // No bitmask (stub events in tests): fall back to the changed button.\n if (e.button === 2) this.rightDown = true;\n else if (e.button === 1) this.middleDown = true;\n else this.isDown = true;\n }\n this.touches.set(e.pointerId, { clientX: e.clientX, clientY: e.clientY });\n };\n this.onUp = (e) => {\n if (!readButtons(e)) {\n this.isDown = false;\n if (e.button === 2) this.rightDown = false;\n else if (e.button === 1) this.middleDown = false;\n else {\n this.rightDown = false;\n this.middleDown = false;\n }\n }\n this.touches.delete((e as PointerEvent)?.pointerId);\n };\n // Right-click is game input: suppress the context menu unless opted back in.\n this.onCtx = (e) => e.preventDefault();\n this.el?.addEventListener('pointermove', this.onMove as EventListener);\n this.el?.addEventListener('pointerdown', this.onDown as EventListener);\n // A finger lifted on the canvas ends its own touch\u2026\n this.el?.addEventListener('pointerup', this.onUp as EventListener);\n this.el?.addEventListener('pointercancel', this.onUp as EventListener);\n if (!opts.contextMenu) this.el?.addEventListener('contextmenu', this.onCtx);\n // \u2026and release anywhere counts too \u2014 lifted off the canvas still ends the press.\n globalThis.addEventListener?.('pointerup', this.onUp as EventListener);\n globalThis.addEventListener?.('pointercancel', this.onUp as EventListener);\n }\n\n /** The current pointer position in design space + press state. */\n read(): PointerReadout {\n const p = this.target.toDesign?.(this.clientX, this.clientY) ?? { x: 0, y: 0 };\n return { x: p.x, y: p.y, down: this.isDown, active: this.seen };\n }\n\n /**\n * Every live (pressed) touch in DESIGN space, ordered by ascending id so the\n * array is stable to iterate. Empty when nothing is pressed. This is the\n * multitouch channel \u2014 a dual-stick game reads `left = touches[0]`, etc., or\n * partitions by screen half.\n */\n readAll(): PointerReadout[] {\n const ids = [...this.touches.keys()].sort((a, b) => a - b);\n return ids.map((id) => {\n const t = this.touches.get(id)!;\n const p = this.target.toDesign?.(t.clientX, t.clientY) ?? { x: 0, y: 0 };\n return { x: p.x, y: p.y, down: true, active: true, id };\n });\n }\n\n /**\n * Write the current sample into an InputState's axes as pointer.x / pointer.y /\n * pointer.down, plus pointer.right / pointer.middle (0/1) for the secondary\n * buttons. Call once per step (the browser driver does this before advance).\n *\n * When a keyboard is wired (PointerSourceOptions.keyboard), buttons are ALSO\n * held as actions `mouse.left` / `mouse.right` / `mouse.middle` so they flow\n * through the same deterministic actionsDown log as keys.\n */\n sample(input: InputState): void {\n const r = this.read();\n // 1/8-px grid: sub-pixel precision no game needs, exact float replay for free.\n const q = (v: number) => Math.round(v * 8) / 8;\n input.axes.set('pointer.x', q(r.x));\n input.axes.set('pointer.y', q(r.y));\n input.axes.set('pointer.down', r.down ? 1 : 0);\n input.axes.set('pointer.right', this.rightDown ? 1 : 0);\n input.axes.set('pointer.middle', this.middleDown ? 1 : 0);\n if (this.keyboard) {\n input.declareActions(MOUSE_ACTIONS);\n this.keyboard.setHeld('mouse.left', this.isDown);\n this.keyboard.setHeld('mouse.right', this.rightDown);\n this.keyboard.setHeld('mouse.middle', this.middleDown);\n }\n }\n\n dispose(): void {\n if (this.keyboard) for (const a of MOUSE_ACTIONS) this.keyboard.releaseHeld(a);\n this.el?.removeEventListener('pointermove', this.onMove as EventListener);\n this.el?.removeEventListener('pointerdown', this.onDown as EventListener);\n this.el?.removeEventListener('pointerup', this.onUp as EventListener);\n this.el?.removeEventListener('pointercancel', this.onUp as EventListener);\n this.el?.removeEventListener('contextmenu', this.onCtx);\n globalThis.removeEventListener?.('pointerup', this.onUp as EventListener);\n globalThis.removeEventListener?.('pointercancel', this.onUp as EventListener);\n }\n}\n", "// Gamepad input source \u2014 polls navigator.getGamepads() each step, writes\n// quantized analog axes into InputState.axes, and routes digital buttons\n// through a KeyboardSource so they enter the same deterministic action log\n// as keys (record/replay + lockstep netplay for free).\n//\n// Mirrors the PointerSource contract: implement sample(input) + dispose().\n\nimport { dhypot } from '../core/dmath';\nimport { snapAxis, type InputState } from './actions';\nimport type { KeyboardSource } from './source';\n\n/** A mapping from Gamepad.buttons indices to action names. */\nexport type GamepadMap = Record<number, string>;\n\nexport interface GamepadSourceOptions {\n /**\n * Gamepad index (0\u20133). Default 0.\n * Tip: listen for the 'gamepadconnected' event to discover the right index;\n * the first connected controller is always index 0.\n */\n index?: number;\n /**\n * Bucket count for quantizing analog stick values (\u00B11 range).\n * Higher = finer precision, larger axes log. Default 128 (~0.016 resolution).\n */\n stickBuckets?: number;\n /**\n * Bucket count for quantizing trigger values (0..1 range).\n * Default 64 (~0.016 resolution).\n */\n triggerBuckets?: number;\n /**\n * Deadzone magnitude radius (0..1) applied to each stick independently before\n * quantization. Values below this threshold are snapped to zero; above it the\n * range is remapped to 0..1 so the output always uses the full scale.\n * Default 0.12 (typical hardware drift).\n */\n deadzone?: number;\n /**\n * Gamepad button index \u2192 action name. Pressed buttons call\n * `keyboard.setHeld(action, on)` so they enter the SAME deterministic action\n * log as keys and are covered by record/replay + netplay.\n * Defaults to DEFAULT_GAMEPAD_MAP (face buttons + d-pad mapped to common actions).\n */\n buttonMap?: GamepadMap;\n /**\n * The KeyboardSource to drive actions through. Required for button\u2192action\n * routing. Typically `handle.input` from the GameHandle returned by runBrowser.\n */\n keyboard?: KeyboardSource;\n}\n\n/**\n * Axis keys written each step:\n *\n * gamepad.lx / gamepad.ly \u2014 left stick, \u00B11 (after deadzone + quantize)\n * gamepad.rx / gamepad.ry \u2014 right stick, \u00B11\n * gamepad.lt / gamepad.rt \u2014 left / right trigger, 0..1\n * gamepad.dpad.x \u2014 d-pad horizontal, \u22121 / 0 / +1\n * gamepad.dpad.y \u2014 d-pad vertical, \u22121 / 0 / +1 (\u22121 = up)\n *\n * Read them in the sim with `world.input.axis('gamepad.lx')`.\n *\n * Determinism note: axes written by sample() are live host samples and are NOT\n * part of the string input log or world.hash() by default. Buttons routed\n * through a KeyboardSource DO enter the log. For bit-exact analog replay, pass\n * quantized axes as the second argument to world.step(actions, axes) \u2014 they\n * then enter getState() \u2192 hash and InputRecorder.\n */\nexport class GamepadSource {\n private index: number;\n private stickBuckets: number;\n private triggerBuckets: number;\n private deadzone: number;\n private buttonMap: GamepadMap;\n private keyboard: KeyboardSource | undefined;\n /** Track which buttons were pressed last frame to detect edge transitions. */\n private prevPressed = new Map<number, boolean>();\n\n constructor(opts: GamepadSourceOptions = {}) {\n this.index = opts.index ?? 0;\n this.stickBuckets = opts.stickBuckets ?? 128;\n this.triggerBuckets = opts.triggerBuckets ?? 64;\n this.deadzone = opts.deadzone ?? 0.12;\n this.buttonMap = opts.buttonMap ?? DEFAULT_GAMEPAD_MAP;\n this.keyboard = opts.keyboard;\n }\n\n /**\n * Write the current gamepad state into InputState axes (quantized). Call once\n * per fixed step, before world.advance() \u2014 the browser driver does this via\n * the `sources` option in RunOptions. See also: runBrowser, GameHandle.\n */\n sample(input: InputState): void {\n const pad = navigator.getGamepads?.()[this.index] ?? null;\n if (!pad) return;\n\n // -- Analog sticks (with circular deadzone) --------------------------------\n const applyDeadzone = (x: number, y: number): { x: number; y: number } => {\n const mag = dhypot(x, y);\n if (mag < this.deadzone) return { x: 0, y: 0 };\n const scale = (mag - this.deadzone) / (1 - this.deadzone);\n const clampedMag = Math.min(scale, 1);\n return { x: (x / mag) * clampedMag, y: (y / mag) * clampedMag };\n };\n\n const ls = applyDeadzone(pad.axes[0] ?? 0, pad.axes[1] ?? 0);\n const rs = applyDeadzone(pad.axes[2] ?? 0, pad.axes[3] ?? 0);\n\n const qs = (v: number) => snapAxis(v, this.stickBuckets, -1, 1);\n const qt = (v: number) => snapAxis(v, this.triggerBuckets, 0, 1);\n\n input.axes.set('gamepad.lx', qs(ls.x));\n input.axes.set('gamepad.ly', qs(ls.y));\n input.axes.set('gamepad.rx', qs(rs.x));\n input.axes.set('gamepad.ry', qs(rs.y));\n\n // -- Triggers (standard layout: index 6 = LT, 7 = RT) ---------------------\n input.axes.set('gamepad.lt', qt(pad.buttons[6]?.value ?? 0));\n input.axes.set('gamepad.rt', qt(pad.buttons[7]?.value ?? 0));\n\n // -- D-pad as axes (standard layout: 12=up 13=down 14=left 15=right) ------\n const du = pad.buttons[12]?.pressed ? 1 : 0;\n const dd = pad.buttons[13]?.pressed ? 1 : 0;\n const dl = pad.buttons[14]?.pressed ? 1 : 0;\n const dr = pad.buttons[15]?.pressed ? 1 : 0;\n input.axes.set('gamepad.dpad.x', dr - dl);\n input.axes.set('gamepad.dpad.y', dd - du);\n\n // -- Buttons \u2192 deterministic action log (via KeyboardSource.setHeld) -------\n if (this.keyboard) {\n for (const [btnStr, action] of Object.entries(this.buttonMap)) {\n const idx = Number(btnStr);\n const pressed = pad.buttons[idx]?.pressed ?? false;\n this.keyboard.setHeld(action, pressed);\n this.prevPressed.set(idx, pressed);\n }\n }\n }\n\n /**\n * Release all held actions and clean up. Call when removing the source or\n * switching gamepads.\n */\n dispose(): void {\n if (this.keyboard) {\n for (const action of Object.values(this.buttonMap)) {\n this.keyboard.releaseHeld(action);\n }\n }\n this.prevPressed.clear();\n }\n}\n\n/**\n * Standard Gamepad API button mapping for a \"Standard Gamepad\" layout\n * (Xbox / PlayStation / Switch Pro controllers).\n *\n * Index Xbox PlayStation Action\n * 0 A Cross confirm\n * 1 B Circle cancel\n * 2 X Square action2\n * 3 Y Triangle action\n * 8 Select/View Share restart (hold to restart)\n * 9 Start/Menu Options confirm (pause menu OK)\n * 12 D-pad up up\n * 13 D-pad down down\n * 14 D-pad left left\n * 15 D-pad right right\n *\n * Triggers (6/7) and bumpers (4/5) are intentionally omitted \u2014 their analog\n * values are exposed as gamepad.lt / gamepad.rt axes instead, and games can\n * add them to a custom map if they want discrete actions.\n */\nexport const DEFAULT_GAMEPAD_MAP: GamepadMap = {\n 0: 'confirm',\n 1: 'cancel',\n 2: 'action2',\n 3: 'action',\n 9: 'confirm',\n 12: 'up',\n 13: 'down',\n 14: 'left',\n 15: 'right',\n};\n", "// Tilemaps: grid collision geometry authored as ASCII. Plain data + pure\n// functions (house style) so maps serialize, hash, and diff cleanly.\n//\n// ORTHOGONAL ONLY. Every helper here \u2014 `tileAtPoint`, `mapWidth` \u2014 assumes a\n// square, axis-aligned lattice (`x/tileSize`). It is NOT iso-aware: on an\n// isometric map, use `iso()` from core for point\u2192cell picking (`toGrid` then\n// floor) and keep the tilemap grid as your logical collision layer, indexing it\n// with the cell coords iso() returns. See docs/CONVENTIONS.md \u00A7Depth.\n\nexport const TILE = {\n EMPTY: 0,\n SOLID: 1,\n /** Passable from below/sides; solid only when landing on its top edge. */\n ONEWAY: 2,\n HAZARD: 3,\n} as const;\nexport type TileId = (typeof TILE)[keyof typeof TILE];\n\nexport interface TilemapData {\n /** Size in tiles. */\n cols: number;\n rows: number;\n /** Tile edge in design-space px. */\n tileSize: number;\n /** Row-major tile ids, length cols*rows. */\n tiles: number[];\n}\n\n/** Default ASCII vocabulary: `#` solid, `-` one-way, `^` hazard, else empty. */\nexport const DEFAULT_TILE_CHARS: Record<string, TileId> = {\n '#': TILE.SOLID,\n '-': TILE.ONEWAY,\n '^': TILE.HAZARD,\n};\n\n/**\n * Build a tilemap from ASCII rows. Unknown characters are EMPTY, so level\n * strings can carry entity markers (`@` spawn, `*` shard\u2026) for game code to\n * read separately via `asciiEntities`.\n */\nexport function tilemapFromAscii(rowsAscii: string[], tileSize = 32, chars: Record<string, TileId> = DEFAULT_TILE_CHARS): TilemapData {\n const rows = rowsAscii.length;\n const cols = Math.max(...rowsAscii.map((r) => r.length));\n const tiles = new Array<number>(cols * rows).fill(TILE.EMPTY);\n rowsAscii.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) tiles[ty * cols + tx] = chars[row[tx]] ?? TILE.EMPTY;\n });\n return { cols, rows, tileSize, tiles };\n}\n\n/** Extract entity markers (any char not in the tile vocabulary, not space/dot). */\nexport function asciiEntities(rowsAscii: string[], tileSize = 32, chars: Record<string, TileId> = DEFAULT_TILE_CHARS): { char: string; tx: number; ty: number; x: number; y: number }[] {\n const out: { char: string; tx: number; ty: number; x: number; y: number }[] = [];\n rowsAscii.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) {\n const c = row[tx];\n if (c === ' ' || c === '.' || chars[c] !== undefined) continue;\n out.push({ char: c, tx, ty, x: (tx + 0.5) * tileSize, y: (ty + 0.5) * tileSize });\n }\n });\n return out;\n}\n\n/** Tile id at tile coords; out-of-bounds reads as SOLID (levels are sealed). */\nexport function tileAt(map: TilemapData, tx: number, ty: number): number {\n if (tx < 0 || ty < 0 || tx >= map.cols || ty >= map.rows) return TILE.SOLID;\n return map.tiles[ty * map.cols + tx];\n}\n\nexport function tileAtPoint(map: TilemapData, x: number, y: number): number {\n return tileAt(map, Math.floor(x / map.tileSize), Math.floor(y / map.tileSize));\n}\n\nexport const mapWidth = (map: TilemapData): number => map.cols * map.tileSize;\nexport const mapHeight = (map: TilemapData): number => map.rows * map.tileSize;\n", "// Kinematic AABB movement against a tilemap plus extra solid rects (moving\n// platforms). Axis-separated, analytically clamped to obstacle edges \u2014 no\n// tunneling, exact and deterministic. Pure functions over plain data.\n\nimport type { Rect } from '../core/math';\nimport { TILE, tileAt, type TilemapData } from './tilemap';\n\nconst EPS = 1e-6;\n\n/** An extra solid the body collides with (moving platform, door, crate\u2026). */\nexport interface SolidRect extends Rect {\n /** Solid only when landing on its top (jump-through platform). */\n oneway?: boolean;\n}\n\nexport interface MoveResult {\n x: number;\n y: number;\n hitX: boolean;\n hitY: boolean;\n onFloor: boolean;\n onCeiling: boolean;\n onWallLeft: boolean;\n onWallRight: boolean;\n /** Final rect overlaps a HAZARD tile (with a small forgiveness inset). */\n hazard: boolean;\n /** Index into `solids` of the rect the body stands on, or -1. */\n floorSolid: number;\n}\n\nconst spanTiles = (lo: number, hi: number, ts: number): [number, number] => [Math.floor(lo / ts), Math.floor((hi - EPS) / ts)];\n\nexport interface MoveOpts {\n solids?: SolidRect[];\n /** Pass true while the player holds \"down\" to drop through one-way platforms. */\n dropThrough?: boolean;\n}\n\n/** Would a rect at (x, y) overlap any solid geometry? (Used for corner-correction probes.) */\nexport function rectBlocked(map: TilemapData, x: number, y: number, w: number, h: number, solids: SolidRect[] = []): boolean {\n const ts = map.tileSize;\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n const [ty0, ty1] = spanTiles(y, y + h, ts);\n for (let ty = ty0; ty <= ty1; ty++)\n for (let tx = tx0; tx <= tx1; tx++) if (tileAt(map, tx, ty) === TILE.SOLID) return true;\n for (const s of solids) {\n if (s.oneway) continue;\n if (x < s.x + s.w - EPS && x + w > s.x + EPS && y < s.y + s.h - EPS && y + h > s.y + EPS) return true;\n }\n return false;\n}\n\n/**\n * Move a rect by (dx, dy) with axis-separated collision: X first, then Y.\n * One-way surfaces block only downward motion that starts at-or-above their top.\n */\nexport function moveRect(map: TilemapData, rect: Rect, dx: number, dy: number, opts: MoveOpts = {}): MoveResult {\n const ts = map.tileSize;\n const solids = opts.solids ?? [];\n let { x, y } = rect;\n const { w, h } = rect;\n let hitX = false;\n let hitY = false;\n let onWallLeft = false;\n let onWallRight = false;\n\n // \u2500\u2500 X axis \u2500\u2500\n if (dx !== 0) {\n const [ty0, ty1] = spanTiles(y, y + h, ts);\n if (dx > 0) {\n let limit = x + dx; // furthest allowed left-edge position\n const [c0, c1] = [Math.floor((x + w) / ts), Math.floor((x + w + dx - EPS) / ts)];\n for (let tx = c0; tx <= c1; tx++)\n for (let ty = ty0; ty <= ty1; ty++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.min(limit, tx * ts - w);\n for (const s of solids)\n if (!s.oneway && s.y < y + h - EPS && s.y + s.h > y + EPS && s.x >= x + w - EPS) limit = Math.min(limit, s.x - w);\n if (limit < x + dx - EPS) {\n hitX = true;\n onWallRight = true;\n }\n x = Math.min(x + dx, limit);\n } else {\n let limit = x + dx;\n const [c0, c1] = [Math.floor((x - EPS) / ts), Math.floor((x + dx) / ts)];\n for (let tx = c0; tx >= c1; tx--)\n for (let ty = ty0; ty <= ty1; ty++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.max(limit, (tx + 1) * ts);\n for (const s of solids)\n if (!s.oneway && s.y < y + h - EPS && s.y + s.h > y + EPS && s.x + s.w <= x + EPS) limit = Math.max(limit, s.x + s.w);\n if (limit > x + dx + EPS) {\n hitX = true;\n onWallLeft = true;\n }\n x = Math.max(x + dx, limit);\n }\n }\n\n // \u2500\u2500 Y axis \u2500\u2500\n const prevBottom = y + h;\n let onFloor = false;\n let onCeiling = false;\n let floorSolid = -1;\n if (dy !== 0) {\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n if (dy > 0) {\n let limit = y + dy; // furthest allowed top position\n const [r0, r1] = [Math.floor(prevBottom / ts), Math.floor((prevBottom + dy - EPS) / ts)];\n for (let ty = r0; ty <= r1; ty++)\n for (let tx = tx0; tx <= tx1; tx++) {\n const t = tileAt(map, tx, ty);\n const blocks = t === TILE.SOLID || (t === TILE.ONEWAY && !opts.dropThrough && prevBottom <= ty * ts + EPS);\n if (blocks) limit = Math.min(limit, ty * ts - h);\n }\n for (let i = 0; i < solids.length; i++) {\n const s = solids[i];\n const inX = s.x < x + w - EPS && s.x + s.w > x + EPS;\n if (!inX || s.y < prevBottom - EPS) continue;\n if (s.oneway && (opts.dropThrough || prevBottom > s.y + EPS)) continue;\n if (s.y - h < limit) {\n limit = s.y - h;\n floorSolid = i;\n }\n }\n if (limit < y + dy - EPS) {\n hitY = true;\n onFloor = true;\n } else floorSolid = -1;\n y = Math.min(y + dy, limit);\n } else {\n let limit = y + dy;\n const [r0, r1] = [Math.floor((y - EPS) / ts), Math.floor((y + dy) / ts)];\n for (let ty = r0; ty >= r1; ty--)\n for (let tx = tx0; tx <= tx1; tx++)\n if (tileAt(map, tx, ty) === TILE.SOLID) limit = Math.max(limit, (ty + 1) * ts);\n for (const s of solids)\n if (!s.oneway && s.x < x + w - EPS && s.x + s.w > x + EPS && s.y + s.h <= y + EPS) limit = Math.max(limit, s.y + s.h);\n if (limit > y + dy + EPS) {\n hitY = true;\n onCeiling = true;\n }\n y = Math.max(y + dy, limit);\n }\n }\n\n // \u2500\u2500 Ground probe (also true when dy was 0 or clamped exactly) \u2500\u2500\n if (!onFloor) {\n const probe = groundAt(map, x, y, w, h, solids, opts.dropThrough ?? false);\n onFloor = probe.grounded;\n floorSolid = probe.solid;\n }\n\n // \u2500\u2500 Hazard overlap (inset for forgiveness) \u2500\u2500\n const inset = 3;\n let hazard = false;\n {\n const [hx0, hx1] = spanTiles(x + inset, x + w - inset, ts);\n const [hy0, hy1] = spanTiles(y + inset, y + h - inset, ts);\n for (let ty = hy0; ty <= hy1 && !hazard; ty++)\n for (let tx = hx0; tx <= hx1 && !hazard; tx++) if (tileAt(map, tx, ty) === TILE.HAZARD) hazard = true;\n }\n\n return { x, y, hitX, hitY, onFloor, onCeiling, onWallLeft, onWallRight, hazard, floorSolid };\n}\n\n/** Is there support directly under the rect (within 1px)? */\nexport function groundAt(map: TilemapData, x: number, y: number, w: number, h: number, solids: SolidRect[] = [], dropThrough = false): { grounded: boolean; solid: number } {\n const ts = map.tileSize;\n const bottom = y + h;\n const [tx0, tx1] = spanTiles(x, x + w, ts);\n const ty = Math.floor((bottom + 1) / ts);\n for (let tx = tx0; tx <= tx1; tx++) {\n const t = tileAt(map, tx, ty);\n if (t === TILE.SOLID) return { grounded: true, solid: -1 };\n if (t === TILE.ONEWAY && !dropThrough && Math.abs(bottom - ty * ts) <= 1 + EPS) return { grounded: true, solid: -1 };\n }\n for (let i = 0; i < solids.length; i++) {\n const s = solids[i];\n const inX = s.x < x + w - EPS && s.x + s.w > x + EPS;\n if (inX && bottom <= s.y + 1 + EPS && bottom >= s.y - 1 - EPS) return { grounded: true, solid: i };\n }\n return { grounded: false, solid: -1 };\n}\n", "// PlatformerController: a state-of-the-art 2D kinematic character controller.\n// Pure and deterministic \u2014 plain-data state, stepped at the fixed timestep, no\n// engine imports beyond physics/math \u2014 so every game-feel feature below is\n// unit-testable in Node by pumping frames.\n//\n// Implements the modern platforming canon:\n// coyote time \u00B7 jump buffering \u00B7 variable jump height \u00B7 halved-gravity apex\n// jump corner correction \u00B7 dash (8-way) \u00B7 dash corner correction\n// wall slide + wall jump \u00B7 moving-platform carry + lift momentum storage\n// one-way platforms + drop-through\n\nimport { dhypot } from '../core/dmath';\nimport { moveRect, rectBlocked, type SolidRect } from './aabb';\nimport type { TilemapData } from './tilemap';\n\nexport interface PlatformerConfig {\n width: number;\n height: number;\n /** Ground run speed (px/s) and accelerations (px/s\u00B2). */\n runSpeed: number;\n groundAccel: number;\n groundFriction: number;\n airAccel: number;\n /**\n * Horizontal decel with no input while airborne (px/s\u00B2). Keep LOW: inherited\n * momentum (lift jumps, wall kicks) must survive flight to feel right.\n */\n airFriction: number;\n /** Gravity (px/s\u00B2), terminal fall speed, and the apex modifier. */\n gravity: number;\n maxFall: number;\n /** |vy| below this counts as the jump apex\u2026 */\n apexThreshold: number;\n /** \u2026where gravity is multiplied by this while jump is held (the floaty peak). */\n apexGravityMult: number;\n /** Initial jump velocity (px/s, upward) and early-release cut multiplier. */\n jumpVelocity: number;\n jumpCutMult: number;\n /** Grace timers (seconds). */\n coyoteTime: number;\n jumpBuffer: number;\n /** Max px the body is nudged sideways to slip past a ceiling corner when jumping. */\n jumpCornerNudge: number;\n /** Max px the body is nudged vertically to slip past a corner while dashing. */\n dashCornerNudge: number;\n /** Mid-air jumps (0 = none, 1 = double jump\u2026), refilled on landing/wall. */\n airJumps: number;\n /** Air-jump velocity as a fraction of jumpVelocity. */\n airJumpMult: number;\n /** Dash: speed (px/s), duration (s), cooldown (s), charges refilled on landing. */\n dashSpeed: number;\n dashTime: number;\n dashCooldown: number;\n dashCharges: number;\n /** Wall interaction. */\n wallSlideMaxFall: number;\n wallJumpVelX: number;\n wallJumpVelY: number;\n /** Seconds after a wall jump during which input can't cancel the outward velocity. */\n wallJumpLock: number;\n}\n\n/** Tuned for 32px tiles at 60Hz in the 1280\u00D7720 design space. */\nexport const DEFAULT_PLATFORMER: PlatformerConfig = {\n width: 22,\n height: 28,\n runSpeed: 340,\n groundAccel: 3800,\n groundFriction: 4200,\n airAccel: 2600,\n airFriction: 260,\n gravity: 2300,\n maxFall: 660,\n apexThreshold: 60,\n apexGravityMult: 0.5,\n jumpVelocity: 650,\n jumpCutMult: 0.4,\n coyoteTime: 0.1,\n jumpBuffer: 0.12,\n jumpCornerNudge: 10,\n dashCornerNudge: 12,\n airJumps: 0,\n airJumpMult: 0.92,\n dashSpeed: 640,\n dashTime: 0.14,\n dashCooldown: 0.25,\n dashCharges: 1,\n wallSlideMaxFall: 150,\n wallJumpVelX: 360,\n wallJumpVelY: 600,\n wallJumpLock: 0.13,\n};\n\n/** Per-step intent, sampled from actions by the game (never raw keys). */\nexport interface PadInput {\n moveX: number; // -1 | 0 | 1\n moveY: number; // -1 (up) | 0 | 1 (down)\n jumpHeld: boolean;\n jumpPressed: boolean;\n dashPressed: boolean;\n}\n\nexport const PAD_NEUTRAL: PadInput = { moveX: 0, moveY: 0, jumpHeld: false, jumpPressed: false, dashPressed: false };\n\n/** A moving platform: its current rect, plus its velocity this step (px/s). */\nexport interface Platform extends SolidRect {\n vx: number;\n vy: number;\n}\n\n/** Plain serializable controller state \u2014 put it in `world.state` so it hashes. */\nexport interface PlatformerState {\n x: number; // top-left of the collision box\n y: number;\n vx: number;\n vy: number;\n facing: number; // -1 | 1\n onGround: boolean;\n onWall: number; // -1 touching left wall, 1 right, 0 none\n coyote: number;\n buffer: number;\n jumping: boolean; // rising from a jump (variable-height window)\n wallLock: number;\n airJumpsLeft: number;\n dashing: number; // time left in current dash\n dashCd: number;\n dashesLeft: number;\n dashVx: number;\n dashVy: number;\n /** Velocity inherited from the platform we stand on (lift momentum storage). */\n carryVx: number;\n carryVy: number;\n dead: boolean;\n}\n\nexport function createPlatformerState(x: number, y: number): PlatformerState {\n return { x, y, vx: 0, vy: 0, facing: 1, onGround: false, onWall: 0, coyote: 0, buffer: 0, jumping: false, wallLock: 0, airJumpsLeft: 0, dashing: 0, dashCd: 0, dashesLeft: 1, dashVx: 0, dashVy: 0, carryVx: 0, carryVy: 0, dead: false };\n}\n\n/** Feel events emitted by a step \u2014 hooks for SFX / particles / screen shake. */\nexport interface PlatformerEvents {\n jumped: boolean;\n wallJumped: boolean;\n airJumped: boolean;\n dashed: boolean;\n landed: boolean;\n died: boolean;\n}\n\nconst approach = (v: number, target: number, delta: number): number => (v < target ? Math.min(v + delta, target) : Math.max(v - delta, target));\n\n/**\n * Advance the controller one fixed step. Mutates `s`; returns feel events.\n * `platforms` should already be at their post-move positions for this step,\n * with `vx/vy` set to their velocity, so the body is carried exactly.\n */\nexport function stepPlatformer(s: PlatformerState, input: PadInput, dt: number, map: TilemapData, cfg: PlatformerConfig = DEFAULT_PLATFORMER, platforms: Platform[] = []): PlatformerEvents {\n const ev: PlatformerEvents = { jumped: false, wallJumped: false, airJumped: false, dashed: false, landed: false, died: false };\n if (s.dead) return ev;\n const wasGrounded = s.onGround;\n\n // \u2500\u2500 Timers \u2500\u2500\n s.coyote = Math.max(0, s.coyote - dt);\n s.buffer = Math.max(0, s.buffer - dt);\n s.wallLock = Math.max(0, s.wallLock - dt);\n s.dashCd = Math.max(0, s.dashCd - dt);\n if (input.jumpPressed) s.buffer = cfg.jumpBuffer;\n\n // \u2500\u2500 Dash start \u2500\u2500\n if (input.dashPressed && s.dashing <= 0 && s.dashCd <= 0 && s.dashesLeft > 0) {\n let dx = input.moveX;\n let dy = input.moveY;\n if (dx === 0 && dy === 0) dx = s.facing;\n const inv = 1 / dhypot(dx, dy);\n s.dashing = cfg.dashTime;\n s.dashCd = cfg.dashCooldown;\n s.dashesLeft--;\n s.dashVx = dx * inv * cfg.dashSpeed;\n s.dashVy = dy * inv * cfg.dashSpeed;\n s.jumping = false;\n ev.dashed = true;\n }\n\n // \u2500\u2500 Horizontal intent \u2500\u2500\n if (s.dashing > 0) {\n s.vx = s.dashVx;\n s.vy = s.dashVy;\n s.dashing -= dt;\n } else if (s.wallLock <= 0) {\n const target = input.moveX * cfg.runSpeed;\n const accel = s.onGround ? (input.moveX !== 0 ? cfg.groundAccel : cfg.groundFriction) : input.moveX !== 0 ? cfg.airAccel : cfg.airFriction;\n s.vx = approach(s.vx, target, accel * dt);\n if (input.moveX !== 0) s.facing = input.moveX > 0 ? 1 : -1;\n }\n\n // \u2500\u2500 Gravity (skipped while dashing) \u2500\u2500\n if (s.dashing <= 0 && !s.onGround) {\n let g = cfg.gravity;\n if (Math.abs(s.vy) < cfg.apexThreshold && input.jumpHeld && s.jumping) g *= cfg.apexGravityMult; // halved-gravity peak\n s.vy = Math.min(s.vy + g * dt, cfg.maxFall);\n if (s.onWall !== 0 && s.vy > cfg.wallSlideMaxFall && input.moveX === s.onWall) s.vy = cfg.wallSlideMaxFall; // wall slide\n }\n\n // \u2500\u2500 Variable jump height: release cuts upward velocity \u2500\u2500\n if (s.jumping && !input.jumpHeld && s.vy < 0) {\n s.vy *= cfg.jumpCutMult;\n s.jumping = false;\n }\n\n // \u2500\u2500 Jump (buffered + coyote) / wall jump \u2500\u2500\n if (s.buffer > 0 && s.dashing <= 0) {\n if (s.onGround || s.coyote > 0) {\n s.vy = -cfg.jumpVelocity;\n // Lift momentum storage: keep the platform's motion.\n s.vx += s.carryVx;\n if (s.carryVy < 0) s.vy += s.carryVy;\n s.jumping = true;\n s.buffer = 0;\n s.coyote = 0;\n s.onGround = false;\n ev.jumped = true;\n } else if (s.onWall !== 0 && cfg.wallJumpVelY > 0) {\n s.vx = -s.onWall * cfg.wallJumpVelX;\n s.vy = -cfg.wallJumpVelY;\n s.facing = -s.onWall;\n s.jumping = true;\n s.buffer = 0;\n s.wallLock = cfg.wallJumpLock;\n ev.wallJumped = true;\n ev.jumped = true;\n } else if (s.airJumpsLeft > 0) {\n s.vy = -cfg.jumpVelocity * cfg.airJumpMult;\n s.airJumpsLeft--;\n s.jumping = true;\n s.buffer = 0;\n ev.jumped = true;\n ev.airJumped = true;\n }\n }\n\n // \u2500\u2500 Move-and-collide, with platform carry \u2500\u2500\n // Holding down passes through one-ways \u2014 INCLUDING while already falling,\n // or the body re-lands on the platform lip one frame after leaving it.\n const dropThrough = input.moveY > 0 && s.buffer <= 0;\n let dx = s.vx * dt + s.carryVx * dt * (s.onGround ? 1 : 0);\n let dy = s.vy * dt + Math.max(0, s.carryVy) * dt * (s.onGround ? 1 : 0);\n let res = moveRect(map, { x: s.x, y: s.y, w: cfg.width, h: cfg.height }, dx, dy, { solids: platforms, dropThrough });\n\n // \u2500\u2500 Jump corner correction: bonked a ceiling edge while rising \u2192 nudge sideways \u2500\u2500\n if (res.onCeiling && s.vy < 0 && s.dashing <= 0) {\n const slip = cornerSlipX(map, platforms, res.x, res.y, cfg.width, cfg.height, dy, cfg.jumpCornerNudge);\n if (slip !== null) {\n res = moveRect(map, { x: slip, y: res.y, w: cfg.width, h: cfg.height }, 0, dy, { solids: platforms, dropThrough });\n res.x = slip;\n }\n }\n\n // \u2500\u2500 Dash corner correction: clipped a wall edge while dashing \u2192 nudge vertically \u2500\u2500\n if (res.hitX && s.dashing > 0 && Math.abs(s.dashVy) < 1) {\n const slip = cornerSlipY(map, platforms, res.x, res.y, cfg.width, cfg.height, dx, cfg.dashCornerNudge);\n if (slip !== null) {\n res = moveRect(map, { x: res.x, y: slip, w: cfg.width, h: cfg.height }, dx, 0, { solids: platforms, dropThrough });\n res.y = slip;\n }\n }\n\n s.x = res.x;\n s.y = res.y;\n if (res.hitY && s.vy > 0) s.vy = 0;\n if (res.onCeiling) {\n s.vy = Math.max(s.vy, 0);\n s.jumping = false;\n }\n if (res.hitX && s.dashing <= 0) s.vx = 0;\n s.onWall = res.onWallLeft ? -1 : res.onWallRight ? 1 : wallTouch(map, platforms, s.x, s.y, cfg.width, cfg.height);\n s.onGround = res.onFloor;\n\n // \u2500\u2500 Ground bookkeeping: coyote, dash refill, landing, lift momentum \u2500\u2500\n if (s.onGround) {\n s.coyote = cfg.coyoteTime;\n s.dashesLeft = cfg.dashCharges;\n s.airJumpsLeft = cfg.airJumps;\n if (!wasGrounded) ev.landed = true;\n if (res.floorSolid >= 0) {\n const p = platforms[res.floorSolid];\n s.carryVx = p.vx;\n s.carryVy = p.vy;\n // Ride the platform exactly: snap feet to its top.\n s.y = p.y - cfg.height;\n } else {\n s.carryVx = 0;\n s.carryVy = 0;\n }\n if (s.vy > 0) s.vy = 0;\n s.jumping = false;\n } else if (wasGrounded && s.carryVy !== 0) {\n // Walked off a lift: keep stored momentum until landing or jumping.\n }\n\n if (res.hazard) {\n s.dead = true;\n ev.died = true;\n }\n return ev;\n}\n\n// \u2500\u2500 Movement envelope: derive level geometry from the config, never guess \u2500\u2500\n// Conservative closed-form bounds (they ignore the apex-gravity bonus, so the\n// real controller always reaches at least this far). Author levels against\n// these \u2014 \"it looks jumpable\" is how unwinnable geometry ships.\n\n/** Max rise of a full jump (px). */\nexport function jumpHeight(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return (cfg.jumpVelocity * cfg.jumpVelocity) / (2 * cfg.gravity);\n}\n\n/** Full-jump airtime returning to takeoff height (s). */\nexport function jumpAirtime(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return (2 * cfg.jumpVelocity) / cfg.gravity;\n}\n\n/** Max horizontal gap clearable by a running jump (px, flat-to-flat). */\nexport function jumpDistance(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return cfg.runSpeed * jumpAirtime(cfg);\n}\n\n/** Max gap clearable by jump + one apex dash (px, flat-to-flat, horizontal dash). */\nexport function dashJumpDistance(cfg: PlatformerConfig = DEFAULT_PLATFORMER): number {\n return jumpDistance(cfg) + (cfg.dashSpeed - cfg.runSpeed) * cfg.dashTime;\n}\n\n/** Try shifting x by up to \u00B1nudge so a rect moving by dy is unblocked. Prefers the smaller shift. */\nfunction cornerSlipX(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number, dy: number, nudge: number): number | null {\n for (let n = 1; n <= nudge; n++) {\n for (const dir of [1, -1]) {\n const nx = x + dir * n;\n if (!rectBlocked(map, nx, y + dy, w, h, solids) && !rectBlocked(map, nx, y, w, h, solids)) return nx;\n }\n }\n return null;\n}\n\n/** Try shifting y by up to \u00B1nudge so a rect moving by dx is unblocked. */\nfunction cornerSlipY(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number, dx: number, nudge: number): number | null {\n for (let n = 1; n <= nudge; n++) {\n for (const dir of [-1, 1]) {\n const ny = y + dir * n;\n if (!rectBlocked(map, x + dx, ny, w, h, solids) && !rectBlocked(map, x, ny, w, h, solids)) return ny;\n }\n }\n return null;\n}\n\n/** Which wall (if any) is the body pressed against? (1px probes) */\nfunction wallTouch(map: TilemapData, solids: SolidRect[], x: number, y: number, w: number, h: number): number {\n if (rectBlocked(map, x + 1, y, w, h, solids)) return 1;\n if (rectBlocked(map, x - 1, y, w, h, solids)) return -1;\n return 0;\n}\n", "// Uniform-grid spatial hash for broad-phase queries over many moving entities\n// (hordes, bullets, RTS units). Deterministic: iteration order is insertion\n// order within cells, and query results preserve first-insertion order.\n// Rebuild-per-step is the intended pattern \u2014 clear() + insert all \u2014 which is\n// O(n) and avoids stale incremental state entirely.\n\nimport type { Rect } from '../core/math';\n\nexport class SpatialHash<T> {\n private cells = new Map<number, T[]>();\n private bounds = new Map<T, Rect>();\n private readonly cellSize: number;\n\n constructor(cellSize = 64) {\n this.cellSize = cellSize;\n }\n\n clear(): void {\n this.cells.clear();\n this.bounds.clear();\n }\n\n get size(): number {\n return this.bounds.size;\n }\n\n private key(cx: number, cy: number): number {\n // Interleave-free packing; fine for worlds within \u00B12^15 cells.\n return (cx + 32768) * 65536 + (cy + 32768);\n }\n\n insert(item: T, rect: Rect): void {\n this.bounds.set(item, rect);\n const cs = this.cellSize;\n const x0 = Math.floor(rect.x / cs);\n const x1 = Math.floor((rect.x + rect.w) / cs);\n const y0 = Math.floor(rect.y / cs);\n const y1 = Math.floor((rect.y + rect.h) / cs);\n for (let cy = y0; cy <= y1; cy++)\n for (let cx = x0; cx <= x1; cx++) {\n const k = this.key(cx, cy);\n const cell = this.cells.get(k);\n if (cell) cell.push(item);\n else this.cells.set(k, [item]);\n }\n }\n\n /** All items whose rects overlap the query rect (deduplicated, deterministic order). */\n query(rect: Rect): T[] {\n const cs = this.cellSize;\n const x0 = Math.floor(rect.x / cs);\n const x1 = Math.floor((rect.x + rect.w) / cs);\n const y0 = Math.floor(rect.y / cs);\n const y1 = Math.floor((rect.y + rect.h) / cs);\n const seen = new Set<T>();\n const out: T[] = [];\n for (let cy = y0; cy <= y1; cy++)\n for (let cx = x0; cx <= x1; cx++) {\n const cell = this.cells.get(this.key(cx, cy));\n if (!cell) continue;\n for (const item of cell) {\n if (seen.has(item)) continue;\n seen.add(item);\n const b = this.bounds.get(item)!;\n if (b.x < rect.x + rect.w && b.x + b.w > rect.x && b.y < rect.y + rect.h && b.y + b.h > rect.y) out.push(item);\n }\n }\n return out;\n }\n\n /** All items within `radius` of a point (circle vs rect-center test on bounds). */\n queryCircle(x: number, y: number, radius: number): T[] {\n const near = this.query({ x: x - radius, y: y - radius, w: radius * 2, h: radius * 2 });\n return near.filter((item) => {\n const b = this.bounds.get(item)!;\n const cx = Math.max(b.x, Math.min(x, b.x + b.w));\n const cy = Math.max(b.y, Math.min(y, b.y + b.h));\n return (x - cx) * (x - cx) + (y - cy) * (y - cy) <= radius * radius;\n });\n }\n}\n", "// Grid raycasting (DDA) over a tilemap \u2014 the sight primitive behind stealth\n// vision cones, sentry line-of-sight, roguelike FOV, and 2D lighting.\n\nimport { dcos, dhypot } from '../core/dmath';\nimport { TILE, tileAt, type TilemapData } from './tilemap';\n\nexport interface RayHit {\n /** True if a solid tile stopped the ray before reaching (x1, y1). */\n blocked: boolean;\n /** Where the ray stopped (the hit point, or the target if unblocked). */\n x: number;\n y: number;\n /** Distance travelled. */\n dist: number;\n}\n\n/**\n * March a ray from (x0,y0) toward (x1,y1) through the tile grid (DDA \u2014 exact,\n * no step-size tuning). SOLID tiles block; everything else passes.\n */\nexport function raycastTiles(map: TilemapData, x0: number, y0: number, x1: number, y1: number): RayHit {\n const ts = map.tileSize;\n const dx = x1 - x0;\n const dy = y1 - y0;\n const maxDist = dhypot(dx, dy);\n if (maxDist === 0) return { blocked: false, x: x1, y: y1, dist: 0 };\n const dirX = dx / maxDist;\n const dirY = dy / maxDist;\n\n let tx = Math.floor(x0 / ts);\n let ty = Math.floor(y0 / ts);\n const stepX = dirX > 0 ? 1 : -1;\n const stepY = dirY > 0 ? 1 : -1;\n const tDeltaX = dirX !== 0 ? Math.abs(ts / dirX) : Infinity;\n const tDeltaY = dirY !== 0 ? Math.abs(ts / dirY) : Infinity;\n let tMaxX = dirX !== 0 ? (dirX > 0 ? (tx + 1) * ts - x0 : x0 - tx * ts) / Math.abs(dirX) : Infinity;\n let tMaxY = dirY !== 0 ? (dirY > 0 ? (ty + 1) * ts - y0 : y0 - ty * ts) / Math.abs(dirY) : Infinity;\n\n let t = 0;\n // The starting tile never blocks (the caster stands in it).\n for (let guard = 0; guard < 512; guard++) {\n if (tMaxX < tMaxY) {\n t = tMaxX;\n tMaxX += tDeltaX;\n tx += stepX;\n } else {\n t = tMaxY;\n tMaxY += tDeltaY;\n ty += stepY;\n }\n if (t >= maxDist) return { blocked: false, x: x1, y: y1, dist: maxDist };\n if (tileAt(map, tx, ty) === TILE.SOLID) {\n return { blocked: true, x: x0 + dirX * t, y: y0 + dirY * t, dist: t };\n }\n }\n return { blocked: true, x: x0 + dirX * t, y: y0 + dirY * t, dist: t };\n}\n\n/** Can a see b with no solid tile between? */\nexport function lineOfSight(map: TilemapData, ax: number, ay: number, bx: number, by: number): boolean {\n return !raycastTiles(map, ax, ay, bx, by).blocked;\n}\n\n/**\n * Is the target inside a vision cone AND visible? (facing is a unit vector;\n * fov is the FULL cone angle in radians.)\n */\nexport function inVisionCone(map: TilemapData, ex: number, ey: number, faceX: number, faceY: number, fov: number, range: number, tx: number, ty: number): boolean {\n const dx = tx - ex;\n const dy = ty - ey;\n const d = dhypot(dx, dy);\n if (d > range || d === 0) return false;\n const dot = (dx * faceX + dy * faceY) / d;\n if (dot < dcos(fov / 2)) return false;\n return lineOfSight(map, ex, ey, tx, ty);\n}\n", "// Deterministic 2D rigid-body dynamics \u2014 data model. The whole physics world\n// is PLAIN JSON (no classes, no hidden caches), so it can live in\n// `world.state` and inherit hashing, snapshot/restore, replay verification,\n// and structuredClone-based planning bots for free. Pure functions over data.\n//\n// Units are pixels / seconds / radians. Only mass RATIOS matter to the\n// solver; density defaults keep numbers small. Convention: a body's local\n// origin is its center of mass (use `polygonBox`/`regularPolygon` helpers).\n\nimport { dcos, dsin } from '../core/dmath';\nimport type { Rect } from '../core/math';\n\nexport type RigidShape =\n | { kind: 'circle'; r: number }\n /** Convex polygon, CCW winding, local coords flat [x0,y0,x1,y1,\u2026]. */\n | { kind: 'poly'; points: number[] };\n\nexport type BodyKind = 'dynamic' | 'static' | 'kinematic';\n\nexport interface RigidBody {\n id: number;\n kind: BodyKind;\n shape: RigidShape;\n /** Pose: position of the center of mass + rotation. */\n x: number; y: number; a: number;\n /** Velocity: linear + angular (rad/s). */\n vx: number; vy: number; w: number;\n /** Mass properties (0 inverse = immovable / non-rotating). */\n m: number; invM: number; i: number; invI: number;\n restitution: number;\n friction: number;\n linDamp: number;\n angDamp: number;\n gravityScale: number;\n /** Swept-circle CCD each step (circles only) \u2014 for very fast bodies. */\n bullet: boolean;\n /** Overlap events only, no collision response. */\n sensor: boolean;\n /** Collision filtering: collide iff (a.mask & b.layer) && (b.mask & a.layer). */\n layer: number;\n mask: number;\n canSleep: boolean;\n sleeping: boolean;\n sleepTime: number;\n /** Characteristic radius: converts spin to rim speed for the sleep test. */\n sleepR: number;\n /** Per-step force/torque accumulators (cleared after integration). */\n fx: number; fy: number; torque: number;\n}\n\nexport interface RigidWorldOpts {\n gravityX?: number;\n gravityY?: number;\n /** Solver velocity iterations (default 16 \u2014 stacks need it). */\n iterations?: number;\n /** Broadphase cell size in px (default 96). */\n cellSize?: number;\n}\n\nexport interface RigidWorld {\n gravityX: number;\n gravityY: number;\n iterations: number;\n cellSize: number;\n nextId: number;\n bodies: RigidBody[];\n joints: import('./rigidJoints').Joint[];\n /** Warm-start impulse cache from the previous step, keyed \"a:b:feature\". */\n warm: Record<string, [number, number]>;\n}\n\nexport function createRigidWorld(opts: RigidWorldOpts = {}): RigidWorld {\n return {\n gravityX: opts.gravityX ?? 0,\n gravityY: opts.gravityY ?? 900,\n iterations: opts.iterations ?? 16,\n cellSize: opts.cellSize ?? 96,\n nextId: 1,\n bodies: [],\n joints: [],\n warm: {},\n };\n}\n\nexport interface RigidBodyDef {\n kind?: BodyKind;\n shape: RigidShape;\n x?: number; y?: number; a?: number;\n vx?: number; vy?: number; w?: number;\n density?: number;\n restitution?: number;\n friction?: number;\n linDamp?: number;\n angDamp?: number;\n gravityScale?: number;\n bullet?: boolean;\n sensor?: boolean;\n layer?: number;\n mask?: number;\n canSleep?: boolean;\n /** Lock rotation (players, elevators): infinite inertia. */\n fixedRotation?: boolean;\n}\n\n/** Area + second moment of area (about the local origin) for a shape. */\nfunction massProps(shape: RigidShape): { area: number; unitI: number } {\n if (shape.kind === 'circle') {\n const area = Math.PI * shape.r * shape.r;\n return { area, unitI: (shape.r * shape.r) / 2 }; // I = m r\u00B2/2\n }\n // Convex polygon: standard cross-product accumulation about the origin.\n const p = shape.points;\n const n = p.length / 2;\n let area = 0;\n let inertia = 0;\n for (let k = 0; k < n; k++) {\n const x0 = p[k * 2], y0 = p[k * 2 + 1];\n const j = (k + 1) % n;\n const x1 = p[j * 2], y1 = p[j * 2 + 1];\n const cross = x0 * y1 - x1 * y0;\n area += cross / 2;\n inertia += (cross * (x0 * x0 + x0 * x1 + x1 * x1 + y0 * y0 + y0 * y1 + y1 * y1)) / 12;\n }\n return { area: Math.abs(area), unitI: area !== 0 ? Math.abs(inertia) / Math.abs(area) : 0 };\n}\n\n/** Mass scale keeps typical bodies O(0.1\u201310) so impulses stay well-ranged. */\nconst DENSITY_SCALE = 1e-4;\n\nexport function addBody(rw: RigidWorld, def: RigidBodyDef): number {\n const kind = def.kind ?? 'dynamic';\n const density = def.density ?? 1;\n const { area, unitI } = massProps(def.shape);\n const m = kind === 'dynamic' ? Math.max(area * density * DENSITY_SCALE, 1e-6) : 0;\n const i = kind === 'dynamic' && !def.fixedRotation ? m * unitI : 0;\n const body: RigidBody = {\n id: rw.nextId++,\n kind,\n shape: def.shape,\n x: def.x ?? 0, y: def.y ?? 0, a: def.a ?? 0,\n vx: def.vx ?? 0, vy: def.vy ?? 0, w: def.w ?? 0,\n m, invM: m > 0 ? 1 / m : 0,\n i, invI: i > 0 ? 1 / i : 0,\n restitution: def.restitution ?? 0.1,\n friction: def.friction ?? 0.4,\n linDamp: def.linDamp ?? 0,\n angDamp: def.angDamp ?? 0.6,\n gravityScale: def.gravityScale ?? 1,\n bullet: def.bullet ?? false,\n sensor: def.sensor ?? false,\n layer: def.layer ?? 1,\n mask: def.mask ?? 0xffff,\n canSleep: def.canSleep ?? true,\n sleeping: false,\n sleepTime: 0,\n sleepR: def.shape.kind === 'circle'\n ? def.shape.r\n : Math.sqrt(def.shape.points.reduce((m, _, i, p) => (i % 2 ? m : Math.max(m, p[i] * p[i] + p[i + 1] * p[i + 1])), 0)),\n fx: 0, fy: 0, torque: 0,\n };\n rw.bodies.push(body);\n return body.id;\n}\n\nexport function getBody(rw: RigidWorld, id: number): RigidBody | undefined {\n const bs = rw.bodies;\n for (let k = 0; k < bs.length; k++) if (bs[k].id === id) return bs[k];\n return undefined;\n}\n\nexport function removeBody(rw: RigidWorld, id: number): void {\n const idx = rw.bodies.findIndex((b) => b.id === id);\n if (idx >= 0) rw.bodies.splice(idx, 1);\n rw.joints = rw.joints.filter((j) => j.a !== id && j.b !== id);\n}\n\nexport function wakeBody(b: RigidBody): void {\n b.sleeping = false;\n b.sleepTime = 0;\n}\n\n/** Apply an impulse at a world point (wakes the body). */\nexport function applyImpulse(rw: RigidWorld, id: number, ix: number, iy: number, px?: number, py?: number): void {\n const b = getBody(rw, id);\n if (!b || b.invM === 0) return;\n wakeBody(b);\n b.vx += ix * b.invM;\n b.vy += iy * b.invM;\n if (px !== undefined && py !== undefined) {\n b.w += ((px - b.x) * iy - (py - b.y) * ix) * b.invI;\n }\n}\n\n/** World-space vertices of a poly body (freshly computed \u2014 no caches). */\nexport function worldPoints(b: RigidBody): number[] {\n if (b.shape.kind !== 'poly') return [];\n const c = dcos(b.a), s = dsin(b.a);\n const p = b.shape.points;\n const out = new Array<number>(p.length);\n for (let k = 0; k < p.length; k += 2) {\n out[k] = b.x + p[k] * c - p[k + 1] * s;\n out[k + 1] = b.y + p[k] * s + p[k + 1] * c;\n }\n return out;\n}\n\nexport function bodyAABB(b: RigidBody): Rect {\n if (b.shape.kind === 'circle') {\n const r = b.shape.r;\n return { x: b.x - r, y: b.y - r, w: r * 2, h: r * 2 };\n }\n const wp = worldPoints(b);\n let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;\n for (let k = 0; k < wp.length; k += 2) {\n if (wp[k] < x0) x0 = wp[k];\n if (wp[k] > x1) x1 = wp[k];\n if (wp[k + 1] < y0) y0 = wp[k + 1];\n if (wp[k + 1] > y1) y1 = wp[k + 1];\n }\n return { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };\n}\n\n/** Centered box as a CCW convex polygon \u2014 the workhorse shape helper. */\nexport function polygonBox(w: number, h: number): RigidShape {\n const hw = w / 2, hh = h / 2;\n return { kind: 'poly', points: [-hw, -hh, hw, -hh, hw, hh, -hw, hh] };\n}\n", "// Narrowphase collision for rigid bodies: circle\u2013circle, circle\u2013poly, and\n// poly\u2013poly (SAT + reference-face clipping, Box2D-lite style). Produces\n// contact manifolds with STABLE feature ids so the solver can warm-start.\n// Pure functions; deterministic tie-breaks everywhere.\n\nimport { dhypot } from '../core/dmath';\nimport type { RigidBody } from './rigidBody';\nimport { worldPoints } from './rigidBody';\n\nexport interface ContactPoint {\n px: number; py: number; // world contact point\n pen: number; // penetration depth (>0 means overlapping)\n feature: number; // stable id for warm starting\n // solver scratch (accumulated impulses live in the warm cache, not here)\n}\n\nexport interface Manifold {\n a: RigidBody;\n b: RigidBody;\n nx: number; ny: number; // contact normal, from A toward B\n points: ContactPoint[]; // 1..2\n}\n\nfunction collideCircles(a: RigidBody, b: RigidBody): Manifold | null {\n if (a.shape.kind !== 'circle' || b.shape.kind !== 'circle') return null;\n const dx = b.x - a.x, dy = b.y - a.y;\n const rsum = a.shape.r + b.shape.r;\n const d2 = dx * dx + dy * dy;\n if (d2 >= rsum * rsum) return null;\n const d = Math.sqrt(d2);\n // Coincident centers: deterministic fallback normal.\n const nx = d > 1e-9 ? dx / d : 1, ny = d > 1e-9 ? dy / d : 0;\n return {\n a, b, nx, ny,\n points: [{ px: a.x + nx * a.shape.r, py: a.y + ny * a.shape.r, pen: rsum - d, feature: 0 }],\n };\n}\n\n/** Circle B against polygon A. Returns manifold with normal A\u2192B. */\nfunction collidePolyCircle(a: RigidBody, b: RigidBody): Manifold | null {\n if (a.shape.kind !== 'poly' || b.shape.kind !== 'circle') return null;\n const wp = worldPoints(a);\n const n = wp.length / 2;\n const r = b.shape.r;\n // Find the face with max separation of the circle center.\n let bestSep = -Infinity, bestI = 0;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ex = wp[j * 2] - wp[k * 2], ey = wp[j * 2 + 1] - wp[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len; // outward for CCW in y-down coords\n const sep = (b.x - wp[k * 2]) * nx + (b.y - wp[k * 2 + 1]) * ny;\n if (sep > bestSep) { bestSep = sep; bestI = k; }\n }\n if (bestSep > r) return null;\n const k = bestI, j = (bestI + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1], bx2 = wp[j * 2], by2 = wp[j * 2 + 1];\n if (bestSep < 1e-9) {\n // Center inside the poly: push out along the deepest face normal.\n const ex = bx2 - ax, ey = by2 - ay;\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n return { a, b, nx, ny, points: [{ px: b.x - nx * r, py: b.y - ny * r, pen: r - bestSep, feature: bestI }] };\n }\n // Closest point on the face segment (vertex regions included).\n const ex = bx2 - ax, ey = by2 - ay;\n const e2 = ex * ex + ey * ey || 1;\n let t = ((b.x - ax) * ex + (b.y - ay) * ey) / e2;\n t = t < 0 ? 0 : t > 1 ? 1 : t;\n const cx = ax + ex * t, cy = ay + ey * t;\n const dx = b.x - cx, dy = b.y - cy;\n const d2 = dx * dx + dy * dy;\n if (d2 >= r * r) return null;\n const d = Math.sqrt(d2) || 1e-9;\n const nx = dx / d, ny = dy / d;\n return { a, b, nx, ny, points: [{ px: cx, py: cy, pen: r - d, feature: bestI }] };\n}\n\n/** Max separation of B's hull from A's faces; returns [separation, faceIndex]. */\nfunction maxSeparation(wpA: number[], wpB: number[]): [number, number] {\n const nA = wpA.length / 2, nB = wpB.length / 2;\n let best = -Infinity, bestI = 0;\n for (let k = 0; k < nA; k++) {\n const j = (k + 1) % nA;\n const ex = wpA[j * 2] - wpA[k * 2], ey = wpA[j * 2 + 1] - wpA[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n // Deepest point of B along this face normal.\n let minDot = Infinity;\n for (let v = 0; v < nB; v++) {\n const d = (wpB[v * 2] - wpA[k * 2]) * nx + (wpB[v * 2 + 1] - wpA[k * 2 + 1]) * ny;\n if (d < minDot) minDot = d;\n }\n if (minDot > best) { best = minDot; bestI = k; }\n }\n return [best, bestI];\n}\n\nfunction collidePolys(a: RigidBody, b: RigidBody): Manifold | null {\n const wpA = worldPoints(a), wpB = worldPoints(b);\n const [sepA, faceA] = maxSeparation(wpA, wpB);\n if (sepA > 0) return null;\n const [sepB, faceB] = maxSeparation(wpB, wpA);\n if (sepB > 0) return null;\n\n // Reference poly: the one with the larger (less negative) separation.\n // Deterministic bias toward A on near-ties.\n let ref: number[], inc: number[], refFace: number, flip: boolean;\n if (sepB > sepA + 1e-4) { ref = wpB; inc = wpA; refFace = faceB; flip = true; }\n else { ref = wpA; inc = wpB; refFace = faceA; flip = false; }\n\n const nRef = ref.length / 2, nInc = inc.length / 2;\n const rj = (refFace + 1) % nRef;\n const rex = ref[rj * 2] - ref[refFace * 2], rey = ref[rj * 2 + 1] - ref[refFace * 2 + 1];\n const rlen = dhypot(rex, rey) || 1;\n const rnx = rey / rlen, rny = -rex / rlen; // reference face normal (outward)\n const rtx = rex / rlen, rty = rey / rlen; // reference face tangent\n\n // Incident face: most anti-parallel to the reference normal.\n let incFace = 0, minDot = Infinity;\n for (let k = 0; k < nInc; k++) {\n const j = (k + 1) % nInc;\n const ex = inc[j * 2] - inc[k * 2], ey = inc[j * 2 + 1] - inc[k * 2 + 1];\n const len = dhypot(ex, ey) || 1;\n const d = (ey / len) * rnx + (-ex / len) * rny;\n if (d < minDot) { minDot = d; incFace = k; }\n }\n const ij = (incFace + 1) % nInc;\n // Two incident vertices; the feature id is (flip, refFace, slot) \u2014 NOT the\n // clip state. Clip-state ids churn every frame while a stack micro-rocks,\n // which mis-applies warm-start impulses and pumps energy into the pile.\n let v1x = inc[incFace * 2], v1y = inc[incFace * 2 + 1];\n let v2x = inc[ij * 2], v2y = inc[ij * 2 + 1];\n\n // Clip against the two side planes of the reference face.\n const refX = ref[refFace * 2], refY = ref[refFace * 2 + 1];\n const refX2 = ref[rj * 2], refY2 = ref[rj * 2 + 1];\n // Side 1: keep t >= 0 along tangent from refV1; Side 2: keep t <= faceLen.\n for (let side = 0; side < 2; side++) {\n const ox = side === 0 ? refX : refX2, oy = side === 0 ? refY : refY2;\n const sx = side === 0 ? rtx : -rtx, sy = side === 0 ? rty : -rty;\n const d1 = (v1x - ox) * sx + (v1y - oy) * sy;\n const d2 = (v2x - ox) * sx + (v2y - oy) * sy;\n if (d1 < 0 && d2 < 0) return null; // fully clipped (shouldn't happen on overlap)\n if (d1 < 0) {\n const t = d1 / (d1 - d2);\n v1x = v1x + (v2x - v1x) * t; v1y = v1y + (v2y - v1y) * t;\n } else if (d2 < 0) {\n const t = d2 / (d2 - d1);\n v2x = v2x + (v1x - v2x) * t; v2y = v2y + (v1y - v2y) * t;\n }\n }\n\n // Keep points behind the reference face; normal must point A\u2192B.\n const nx = flip ? -rnx : rnx, ny = flip ? -rny : rny;\n const points: ContactPoint[] = [];\n const pen1 = -((v1x - refX) * rnx + (v1y - refY) * rny);\n const pen2 = -((v2x - refX) * rnx + (v2y - refY) * rny);\n // Feature id = (flip, refFace, incFace, slot). Stable while the same two\n // faces stay in contact (micro-rocking stacks reuse warm impulses), but\n // fresh whenever a tumbling box rolls onto its next corner (stale impulses\n // at new lever arms would pump energy).\n const fid = ((flip ? 1 : 0) * 64 + refFace) * 64 + incFace;\n if (pen1 > 0) points.push({ px: v1x, py: v1y, pen: pen1, feature: fid * 2 });\n if (pen2 > 0) points.push({ px: v2x, py: v2y, pen: pen2, feature: fid * 2 + 1 });\n if (points.length === 0) return null;\n return { a, b, nx, ny, points };\n}\n\n/** Dispatch on shape kinds. Normal always points from A toward B. */\nexport function collide(a: RigidBody, b: RigidBody): Manifold | null {\n const ka = a.shape.kind, kb = b.shape.kind;\n if (ka === 'circle' && kb === 'circle') return collideCircles(a, b);\n if (ka === 'poly' && kb === 'poly') return collidePolys(a, b);\n if (ka === 'poly' && kb === 'circle') return collidePolyCircle(a, b);\n // circle vs poly: flip so poly is A, then invert the normal back.\n const m = collidePolyCircle(b, a);\n if (!m) return null;\n return { a, b, nx: -m.nx, ny: -m.ny, points: m.points };\n}\n", "// Joints for the rigid-body engine: distance (rod / rope) and revolute\n// (pin, with optional motor and angle limits). Velocity-level constraints\n// with Baumgarte stabilization, solved inside the same iteration loop as\n// contacts. Plain data + pure solve functions.\n\nimport { dcos, dhypot, dsin } from '../core/dmath';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { getBody, wakeBody } from './rigidBody';\n\nexport interface DistanceJoint {\n kind: 'distance';\n id: number;\n a: number; b: number; // body ids\n ax: number; ay: number; // local anchor on A\n bx: number; by: number; // local anchor on B\n length: number;\n /** Rope mode: only constrain when stretched past `length`. */\n rope: boolean;\n}\n\nexport interface RevoluteJoint {\n kind: 'revolute';\n id: number;\n a: number; b: number;\n ax: number; ay: number;\n bx: number; by: number;\n /** Motor: drive relative angular velocity toward `motorSpeed`. */\n motorSpeed: number;\n maxMotorTorque: number; // 0 = motor off\n /** Angle limits on (b.a - a.a - refAngle); NaN-free: enabled flag. */\n limitLower: number;\n limitUpper: number;\n limitEnabled: boolean;\n refAngle: number;\n}\n\nexport type Joint = DistanceJoint | RevoluteJoint;\n\nexport interface DistanceJointDef {\n a: number; b: number;\n ax?: number; ay?: number; bx?: number; by?: number;\n /** Defaults to the current anchor distance. */\n length?: number;\n rope?: boolean;\n}\n\nexport interface RevoluteJointDef {\n a: number; b: number;\n /** World-space pivot; local anchors are derived from current poses. */\n px: number; py: number;\n motorSpeed?: number;\n maxMotorTorque?: number;\n limitLower?: number;\n limitUpper?: number;\n}\n\nfunction toLocal(b: RigidBody, wx: number, wy: number): [number, number] {\n const c = dcos(b.a), s = dsin(b.a);\n const dx = wx - b.x, dy = wy - b.y;\n return [dx * c + dy * s, -dx * s + dy * c];\n}\n\nfunction anchorWorld(b: RigidBody, lx: number, ly: number): [number, number] {\n const c = dcos(b.a), s = dsin(b.a);\n return [b.x + lx * c - ly * s, b.y + lx * s + ly * c];\n}\n\nexport function addDistanceJoint(rw: RigidWorld, def: DistanceJointDef): number {\n const A = getBody(rw, def.a), B = getBody(rw, def.b);\n if (!A || !B) throw new Error(`distance joint: missing body ${def.a}/${def.b}`);\n const ax = def.ax ?? 0, ay = def.ay ?? 0, bx = def.bx ?? 0, by = def.by ?? 0;\n const [wax, way] = anchorWorld(A, ax, ay);\n const [wbx, wby] = anchorWorld(B, bx, by);\n const j: DistanceJoint = {\n kind: 'distance', id: rw.nextId++,\n a: def.a, b: def.b, ax, ay, bx, by,\n length: def.length ?? dhypot(wbx - wax, wby - way),\n rope: def.rope ?? false,\n };\n rw.joints.push(j);\n wakeBody(A); wakeBody(B);\n return j.id;\n}\n\nexport function addRevoluteJoint(rw: RigidWorld, def: RevoluteJointDef): number {\n const A = getBody(rw, def.a), B = getBody(rw, def.b);\n if (!A || !B) throw new Error(`revolute joint: missing body ${def.a}/${def.b}`);\n const [ax, ay] = toLocal(A, def.px, def.py);\n const [bx, by] = toLocal(B, def.px, def.py);\n const j: RevoluteJoint = {\n kind: 'revolute', id: rw.nextId++,\n a: def.a, b: def.b, ax, ay, bx, by,\n motorSpeed: def.motorSpeed ?? 0,\n maxMotorTorque: def.maxMotorTorque ?? 0,\n limitLower: def.limitLower ?? 0,\n limitUpper: def.limitUpper ?? 0,\n limitEnabled: def.limitLower !== undefined || def.limitUpper !== undefined,\n refAngle: B.a - A.a,\n };\n rw.joints.push(j);\n wakeBody(A); wakeBody(B);\n return j.id;\n}\n\nexport function getJoint(rw: RigidWorld, id: number): Joint | undefined {\n for (const j of rw.joints) if (j.id === id) return j;\n return undefined;\n}\n\nexport function removeJoint(rw: RigidWorld, id: number): void {\n rw.joints = rw.joints.filter((j) => j.id !== id);\n}\n\n/** Per-step scratch for accumulated-impulse clamping (one per joint). */\nexport interface JointScratch {\n motorImpulse: number;\n}\n\n/** One velocity iteration for a single joint. `bias` uses dt for Baumgarte. */\nexport function solveJoint(j: Joint, A: RigidBody, B: RigidBody, dt: number, scratch: JointScratch): void {\n const [wax, way] = anchorWorld(A, j.ax, j.ay);\n const [wbx, wby] = anchorWorld(B, j.bx, j.by);\n const rax = wax - A.x, ray = way - A.y;\n const rbx = wbx - B.x, rby = wby - B.y;\n\n if (j.kind === 'distance') {\n let dx = wbx - wax, dy = wby - way;\n const dist = dhypot(dx, dy);\n if (dist < 1e-9) return;\n dx /= dist; dy /= dist;\n const stretch = dist - j.length;\n if (j.rope && stretch <= 0) return; // slack rope\n // Relative velocity along the axis.\n const vax = A.vx - A.w * ray, vay = A.vy + A.w * rax;\n const vbx = B.vx - B.w * rby, vby = B.vy + B.w * rbx;\n const vrel = (vbx - vax) * dx + (vby - vay) * dy;\n const crossA = rax * dy - ray * dx;\n const crossB = rbx * dy - rby * dx;\n const k = A.invM + B.invM + A.invI * crossA * crossA + B.invI * crossB * crossB;\n if (k < 1e-12) return;\n const bias = (0.2 / dt) * stretch;\n let lambda = -(vrel + bias) / k;\n if (j.rope && lambda > 0) lambda = 0; // rope can only pull inward\n const ix = dx * lambda, iy = dy * lambda;\n A.vx -= ix * A.invM; A.vy -= iy * A.invM;\n A.w -= (rax * iy - ray * ix) * A.invI;\n B.vx += ix * B.invM; B.vy += iy * B.invM;\n B.w += (rbx * iy - rby * ix) * B.invI;\n return;\n }\n\n // Revolute: motor + limits first (1D angular), then point-to-point (2D).\n if (j.maxMotorTorque > 0) {\n const kw = A.invI + B.invI;\n if (kw > 1e-12) {\n const cdot = B.w - A.w - j.motorSpeed;\n const imp = -cdot / kw;\n // Accumulated clamp: total motor impulse this STEP \u2264 maxMotorTorque\u00B7dt,\n // regardless of iteration count (Box2D semantics).\n const maxImp = j.maxMotorTorque * dt;\n const acc0 = scratch.motorImpulse;\n scratch.motorImpulse = Math.min(Math.max(acc0 + imp, -maxImp), maxImp);\n const applied = scratch.motorImpulse - acc0;\n A.w -= applied * A.invI;\n B.w += applied * B.invI;\n }\n }\n if (j.limitEnabled) {\n const kw = A.invI + B.invI;\n if (kw > 1e-12) {\n const angle = B.a - A.a - j.refAngle;\n let c = 0;\n if (angle < j.limitLower) c = angle - j.limitLower;\n else if (angle > j.limitUpper) c = angle - j.limitUpper;\n if (c !== 0) {\n const cdot = B.w - A.w;\n const imp = -(cdot + (0.2 / dt) * c) / kw;\n // Only push back toward the range.\n if ((c < 0 && imp > 0) || (c > 0 && imp < 0)) {\n A.w -= imp * A.invI;\n B.w += imp * B.invI;\n }\n }\n }\n }\n // Point-to-point: solve the 2x2 system K * lambda = -(vrel + bias).\n const vax = A.vx - A.w * ray, vay = A.vy + A.w * rax;\n const vbx = B.vx - B.w * rby, vby = B.vy + B.w * rbx;\n const cx = wbx - wax, cy = wby - way;\n const vrx = vbx - vax + (0.2 / dt) * cx;\n const vry = vby - vay + (0.2 / dt) * cy;\n const k11 = A.invM + B.invM + A.invI * ray * ray + B.invI * rby * rby;\n const k12 = -A.invI * rax * ray - B.invI * rbx * rby;\n const k22 = A.invM + B.invM + A.invI * rax * rax + B.invI * rbx * rbx;\n const det = k11 * k22 - k12 * k12;\n if (Math.abs(det) < 1e-12) return;\n const ix = -(k22 * vrx - k12 * vry) / det;\n const iy = -(k11 * vry - k12 * vrx) / det;\n A.vx -= ix * A.invM; A.vy -= iy * A.invM;\n A.w -= (rax * iy - ray * ix) * A.invI;\n B.vx += ix * B.invM; B.vy += iy * B.invM;\n B.w += (rbx * iy - rby * ix) * B.invI;\n}\n", "// The rigid-body step pipeline: integrate forces \u2192 broadphase (spatial hash,\n// ordered pairs) \u2192 narrowphase \u2192 warm-started sequential-impulse solve\n// (joints + contacts) \u2192 integrate positions \u2192 bullet CCD \u2192 sleeping.\n//\n// Penetration recovery uses SPLIT IMPULSE (Chipmunk-style bias velocities): a\n// separate pseudo-velocity field feels the Baumgarte push, integrates into\n// POSITION only, and is discarded \u2014 so stacks recover overlap without gaining\n// kinetic energy, settle truly calm, and can sleep.\n//\n// Deterministic: bodies iterate in array order, pairs in (idA, idB) order,\n// and the warm-start cache is rebuilt every step from plain data.\n\nimport { dhypot } from '../core/dmath';\nimport { SpatialHash } from './spatialHash';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { bodyAABB, getBody, wakeBody, worldPoints } from './rigidBody';\nimport { collide, type Manifold } from './rigidCollide';\nimport { solveJoint } from './rigidJoints';\n\nexport interface ContactEvent {\n a: number; b: number; // body ids (a < b)\n px: number; py: number; // representative contact point\n nx: number; ny: number; // normal a\u2192b\n /** Total normal impulse this step \u2014 scales with hit violence. */\n impulse: number;\n /** Sensor overlap (no collision response was applied). */\n sensor: boolean;\n}\n\nconst SLOP = 0.5; // allowed overlap, px\nconst BIAS = 0.2; // Baumgarte factor (position recovery rate)\nconst REST_THRESHOLD = 40; // px/s \u2014 below this, no bounce\nconst SLEEP_LIN2 = 64; // (8 px/s)\u00B2 \u2014 resting piles hum at 5\u201320 px/s\nconst SLEEP_RIM = 8; // px/s of rim speed (|w|\u00B7sleepR)\nconst TIME_TO_SLEEP = 0.5; // s\nconst WAKE_LIN2 = 100; // partner speed\u00B2 that wakes a sleeper\n\ninterface SolvePoint {\n rax: number; ray: number; rbx: number; rby: number;\n pen: number;\n massN: number; massT: number;\n restBias: number; // restitution target velocity (real)\n posBias: number; // penetration target velocity (pseudo)\n pn: number; pt: number; // accumulated impulses (real)\n pb: number; // accumulated impulse (pseudo)\n key: string;\n}\n\ninterface SolveManifold {\n m: Manifold;\n ia: number; ib: number; // body array indices (for the bias fields)\n points: SolvePoint[];\n friction: number;\n}\n\nfunction canCollide(a: RigidBody, b: RigidBody): boolean {\n if (a.invM === 0 && b.invM === 0 && a.kind !== 'kinematic' && b.kind !== 'kinematic' && !a.sensor && !b.sensor) return false;\n return (a.mask & b.layer) !== 0 && (b.mask & a.layer) !== 0;\n}\n\nexport function rigidStep(rw: RigidWorld, dt: number): ContactEvent[] {\n const bodies = rw.bodies;\n const events: ContactEvent[] = [];\n if (dt <= 0) return events;\n\n // \u2500\u2500 1 \u00B7 integrate forces \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) { b.fx = 0; b.fy = 0; b.torque = 0; continue; }\n b.vx += (rw.gravityX * b.gravityScale + b.fx * b.invM) * dt;\n b.vy += (rw.gravityY * b.gravityScale + b.fy * b.invM) * dt;\n b.w += b.torque * b.invI * dt;\n const ld = 1 / (1 + b.linDamp * dt);\n b.vx *= ld; b.vy *= ld;\n b.w *= 1 / (1 + b.angDamp * dt);\n b.fx = 0; b.fy = 0; b.torque = 0;\n }\n\n // \u2500\u2500 2 \u00B7 broadphase: spatial hash, pairs in deterministic order \u2500\u2500\u2500\n const hash = new SpatialHash<RigidBody>(rw.cellSize);\n const indexOf = new Map<RigidBody, number>();\n for (let k = 0; k < bodies.length; k++) {\n hash.insert(bodies[k], bodyAABB(bodies[k]));\n indexOf.set(bodies[k], k);\n }\n const manifolds: SolveManifold[] = [];\n const seen = new Set<number>();\n // Joint-connected bodies never collide with each other (Box2D convention \u2014\n // a pinned wheel must not grind against its own anchor).\n const jointed = new Set<number>();\n for (const j of rw.joints) {\n const lo = Math.min(j.a, j.b), hi = Math.max(j.a, j.b);\n jointed.add(lo * 1048576 + hi);\n }\n for (let k = 0; k < bodies.length; k++) {\n const a = bodies[k];\n const near = hash.query(bodyAABB(a));\n for (const b of near) {\n if (b.id <= a.id) continue;\n const packed = a.id * 1048576 + b.id;\n if (seen.has(packed)) continue;\n seen.add(packed);\n if (jointed.has(packed)) continue;\n if (!canCollide(a, b)) continue;\n // Skip unless at least one side is an AWAKE mover \u2014 this is what lets a\n // settled stack truly freeze (a sleeping box on a static floor gets no\n // solver impulses at all).\n const activeA = !a.sleeping && a.kind !== 'static';\n const activeB = !b.sleeping && b.kind !== 'static';\n if (!activeA && !activeB) continue;\n const m = collide(a, b);\n if (!m) continue;\n // Wake a sleeper hit by something moving.\n const wakeIf = (s: RigidBody, o: RigidBody) => {\n if (s.sleeping && (o.vx * o.vx + o.vy * o.vy > WAKE_LIN2 || o.kind === 'kinematic')) wakeBody(s);\n };\n wakeIf(a, b); wakeIf(b, a);\n if (a.sensor || b.sensor) {\n events.push({ a: a.id, b: b.id, px: m.points[0].px, py: m.points[0].py, nx: m.nx, ny: m.ny, impulse: 0, sensor: true });\n continue;\n }\n // Pre-step: effective masses, restitution capture, warm start.\n const sp: SolvePoint[] = [];\n const tx = -m.ny, ty = m.nx;\n for (const p of m.points) {\n const rax = p.px - a.x, ray = p.py - a.y;\n const rbx = p.px - b.x, rby = p.py - b.y;\n const crossAN = rax * m.ny - ray * m.nx;\n const crossBN = rbx * m.ny - rby * m.nx;\n const kn = a.invM + b.invM + a.invI * crossAN * crossAN + b.invI * crossBN * crossBN;\n const crossAT = rax * ty - ray * tx;\n const crossBT = rbx * ty - rby * tx;\n const kt = a.invM + b.invM + a.invI * crossAT * crossAT + b.invI * crossBT * crossBT;\n // Approach speed for restitution (captured before solving).\n const vrx = b.vx - b.w * rby - a.vx + a.w * ray;\n const vry = b.vy + b.w * rbx - a.vy - a.w * rax;\n const vn = vrx * m.nx + vry * m.ny;\n const e = Math.max(a.restitution, b.restitution);\n const key = `${a.id}:${b.id}:${p.feature}`;\n const warm = rw.warm[key];\n const sp1: SolvePoint = {\n rax, ray, rbx, rby, pen: p.pen,\n massN: kn > 1e-12 ? 1 / kn : 0,\n massT: kt > 1e-12 ? 1 / kt : 0,\n restBias: vn < -REST_THRESHOLD ? -e * vn : 0,\n posBias: (BIAS / dt) * Math.max(0, p.pen - SLOP),\n pn: warm ? warm[0] : 0,\n pt: warm ? warm[1] : 0,\n pb: 0,\n key,\n };\n sp.push(sp1);\n }\n manifolds.push({ m, ia: k, ib: indexOf.get(b)!, points: sp, friction: Math.sqrt(a.friction * b.friction) });\n }\n }\n\n // Warm-start pass \u2014 applied only AFTER every point captured its clean\n // approach velocity. Interleaving capture with application double-counts\n // restitution (the bounce target re-adds speed warm-starting already\n // reversed) and pumps energy into resting piles.\n for (const sm of manifolds) {\n const { a, b, nx, ny } = sm.m;\n const tx = -ny, ty = nx;\n for (const p of sm.points) {\n if (p.pn === 0 && p.pt === 0) continue;\n const ix = nx * p.pn + tx * p.pt;\n const iy = ny * p.pn + ty * p.pt;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n }\n }\n\n // Solve in SUPPORT ORDER \u2014 static pairs first, then bottom-up (larger y\n // first in y-down coords). Sequential impulse converges a resting pile in\n // far fewer iterations when impulses propagate up the support chain.\n // Deterministic: ties break on (a.id, b.id).\n manifolds.sort((p, q) => {\n const ps = p.m.a.invM === 0 || p.m.b.invM === 0 ? 0 : 1;\n const qs = q.m.a.invM === 0 || q.m.b.invM === 0 ? 0 : 1;\n if (ps !== qs) return ps - qs;\n const py = Math.max(p.m.a.y, p.m.b.y), qy = Math.max(q.m.a.y, q.m.b.y);\n if (py !== qy) return qy - py;\n if (p.m.a.id !== q.m.a.id) return p.m.a.id - q.m.a.id;\n return p.m.b.id - q.m.b.id;\n });\n\n // Pseudo-velocity fields for split-impulse position recovery (scratch \u2014\n // never serialized, discarded at the end of the step).\n const bvx = new Float64Array(bodies.length);\n const bvy = new Float64Array(bodies.length);\n const bw = new Float64Array(bodies.length);\n\n // \u2500\u2500 3 \u00B7 velocity iterations: joints then contacts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const jointScratch = rw.joints.map(() => ({ motorImpulse: 0 }));\n for (let iter = 0; iter < rw.iterations; iter++) {\n for (let jk = 0; jk < rw.joints.length; jk++) {\n const j = rw.joints[jk];\n const A = getBody(rw, j.a), B = getBody(rw, j.b);\n if (!A || !B) continue;\n if (A.sleeping && B.sleeping) continue;\n if (A.sleeping) wakeBody(A);\n if (B.sleeping) wakeBody(B);\n solveJoint(j, A, B, dt, jointScratch[jk]);\n }\n for (const sm of manifolds) {\n const { a, b, nx, ny } = sm.m;\n const { ia, ib } = sm;\n const tx = -ny, ty = nx;\n for (const p of sm.points) {\n // Normal impulse (real velocities; restitution target only).\n let vrx = b.vx - b.w * p.rby - a.vx + a.w * p.ray;\n let vry = b.vy + b.w * p.rbx - a.vy - a.w * p.rax;\n const vn = vrx * nx + vry * ny;\n let dPn = p.massN * (p.restBias - vn);\n const pn0 = p.pn;\n p.pn = Math.max(pn0 + dPn, 0);\n dPn = p.pn - pn0;\n let ix = nx * dPn, iy = ny * dPn;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n // Friction impulse (clamped by the friction cone).\n vrx = b.vx - b.w * p.rby - a.vx + a.w * p.ray;\n vry = b.vy + b.w * p.rbx - a.vy - a.w * p.rax;\n const vt = vrx * tx + vry * ty;\n let dPt = p.massT * -vt;\n const maxPt = sm.friction * p.pn;\n const pt0 = p.pt;\n p.pt = Math.min(Math.max(pt0 + dPt, -maxPt), maxPt);\n dPt = p.pt - pt0;\n ix = tx * dPt; iy = ty * dPt;\n a.vx -= ix * a.invM; a.vy -= iy * a.invM;\n a.w -= (p.rax * iy - p.ray * ix) * a.invI;\n b.vx += ix * b.invM; b.vy += iy * b.invM;\n b.w += (p.rbx * iy - p.rby * ix) * b.invI;\n // Split-impulse penetration recovery (pseudo velocities \u2192 position\n // only; no kinetic energy enters the sim).\n if (p.posBias > 0) {\n const vbn = (bvx[ib] - bw[ib] * p.rby - bvx[ia] + bw[ia] * p.ray) * nx\n + (bvy[ib] + bw[ib] * p.rbx - bvy[ia] - bw[ia] * p.rax) * ny;\n let dPb = p.massN * (p.posBias - vbn);\n const pb0 = p.pb;\n p.pb = Math.max(pb0 + dPb, 0);\n dPb = p.pb - pb0;\n const bix = nx * dPb, biy = ny * dPb;\n // Linear-only pseudo push: rotating positions without refreshing\n // manifolds amplifies stack rocking, so pseudo torque stays off.\n bvx[ia] -= bix * a.invM; bvy[ia] -= biy * a.invM;\n bvx[ib] += bix * b.invM; bvy[ib] += biy * b.invM;\n }\n }\n }\n }\n\n // \u2500\u2500 4 \u00B7 integrate positions (real + pseudo velocity; pseudo dies) \u2500\n const preX: number[] = [], preY: number[] = [];\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n preX.push(b.x); preY.push(b.y);\n if (b.invM === 0 && b.kind !== 'kinematic') continue;\n if (b.sleeping) continue;\n b.x += (b.vx + bvx[k]) * dt;\n b.y += (b.vy + bvy[k]) * dt;\n b.a += (b.w + bw[k]) * dt;\n }\n\n // \u2500\u2500 5 \u00B7 bullet CCD (swept circle vs everything it can hit) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (!b.bullet || b.shape.kind !== 'circle' || b.sleeping) continue;\n const dx = b.x - preX[k], dy = b.y - preY[k];\n if (dx * dx + dy * dy < 1) continue;\n let bestT = 1;\n for (let q = 0; q < bodies.length; q++) {\n const o = bodies[q];\n if (o === b || o.bullet || o.sensor || !canCollide(b, o)) continue;\n const t = sweepCircle(preX[k], preY[k], dx, dy, b.shape.r, o);\n if (t >= 0 && t < bestT) bestT = t;\n }\n if (bestT < 1) {\n // Stop just PAST the impact time: a sub-slop penetration must exist or\n // the discrete narrowphase (pen > 0) never sees a contact, and the body\n // hangs on the surface accumulating gravity velocity forever.\n const len = dhypot(dx, dy) || 1;\n b.x = preX[k] + dx * bestT + (dx / len) * 0.4;\n b.y = preY[k] + dy * bestT + (dy / len) * 0.4;\n // leave velocity intact \u2014 next step's contact solve applies restitution.\n }\n }\n\n // \u2500\u2500 6 \u00B7 sleeping \u2014 ISLAND-atomic (a pile sleeps as one, or not at all) \u2500\n // Union-find over dynamic\u2013dynamic contacts and joints; static bodies do\n // not conduct (two piles on one floor are separate islands).\n const touching = new Set<number>();\n const parent: number[] = [];\n for (let k = 0; k < bodies.length; k++) parent.push(k);\n const find = (x: number): number => {\n while (parent[x] !== x) { parent[x] = parent[parent[x]]; x = parent[x]; }\n return x;\n };\n const union = (x: number, y: number) => { parent[find(x)] = find(y); };\n for (const sm of manifolds) {\n touching.add(sm.m.a.id); touching.add(sm.m.b.id);\n if (sm.m.a.kind === 'dynamic' && sm.m.b.kind === 'dynamic') union(sm.ia, sm.ib);\n }\n for (const j of rw.joints) {\n touching.add(j.a); touching.add(j.b);\n const A = getBody(rw, j.a), B = getBody(rw, j.b);\n if (A?.kind === 'dynamic' && B?.kind === 'dynamic') union(indexOf.get(A)!, indexOf.get(B)!);\n }\n // Per-body calm clocks (a solver-injected velocity also re-wakes a sleeper).\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic') continue;\n const lin2 = b.vx * b.vx + b.vy * b.vy;\n if (b.sleeping) {\n if (lin2 > WAKE_LIN2) wakeBody(b);\n continue;\n }\n if (!b.canSleep || !touching.has(b.id)) { b.sleepTime = 0; continue; }\n b.sleepTime = lin2 < SLEEP_LIN2 && Math.abs(b.w) * b.sleepR < SLEEP_RIM ? b.sleepTime + dt : 0;\n }\n // An island sleeps when EVERY member has been calm long enough.\n const islandMin = new Map<number, number>();\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) continue;\n const root = find(k);\n const t = !b.canSleep || !touching.has(b.id) ? -1 : b.sleepTime;\n const cur = islandMin.get(root);\n islandMin.set(root, cur === undefined ? t : Math.min(cur, t));\n }\n for (let k = 0; k < bodies.length; k++) {\n const b = bodies[k];\n if (b.kind !== 'dynamic' || b.sleeping) continue;\n if ((islandMin.get(find(k)) ?? -1) >= TIME_TO_SLEEP) {\n b.sleeping = true;\n b.vx = 0; b.vy = 0; b.w = 0;\n }\n }\n\n // \u2500\u2500 7 \u00B7 contact events + rebuild the warm cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const warm: Record<string, [number, number]> = {};\n for (const sm of manifolds) {\n let total = 0;\n for (const p of sm.points) {\n total += p.pn;\n if (p.pn !== 0 || p.pt !== 0) warm[p.key] = [p.pn, p.pt];\n }\n const p0 = sm.m.points[0];\n events.push({\n a: sm.m.a.id, b: sm.m.b.id, px: p0.px, py: p0.py,\n nx: sm.m.nx, ny: sm.m.ny, impulse: total, sensor: false,\n });\n }\n rw.warm = warm;\n return events;\n}\n\n/** Earliest t\u2208[0,1] where a circle swept along (dx,dy) first touches body o, or -1. */\nfunction sweepCircle(x0: number, y0: number, dx: number, dy: number, r: number, o: RigidBody): number {\n if (o.shape.kind === 'circle') {\n return sweepVsCircle(x0, y0, dx, dy, o.x, o.y, r + o.shape.r);\n }\n // Poly: Minkowski sum = edges offset outward by r + vertex circles of radius r.\n const wp = worldPoints(o);\n const n = wp.length / 2;\n let best = -1;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1];\n const bx = wp[j * 2], by = wp[j * 2 + 1];\n const ex = bx - ax, ey = by - ay;\n const len = dhypot(ex, ey) || 1;\n const nx = ey / len, ny = -ex / len;\n // Offset edge segment \u2014 only FRONT-side crossings count (motion into the\n // face), and only from a start point that is NOT already touching the\n // face. A touching/overlapping start is the contact solver's regime: TOI\n // would clamp t\u22480 every frame and pin a sliding ball in place.\n const startSep = (x0 - ax) * nx + (y0 - ay) * ny - r;\n if (dx * nx + dy * ny < 0 && startSep > 0.5) {\n const t = sweepVsSegment(x0, y0, dx, dy, ax + nx * r, ay + ny * r, bx + nx * r, by + ny * r);\n if (t >= 0 && (best < 0 || t < best)) best = t;\n }\n // Vertex circle.\n const tv = sweepVsCircle(x0, y0, dx, dy, ax, ay, r);\n if (tv >= 0 && (best < 0 || tv < best)) best = tv;\n }\n return best;\n}\n\nfunction sweepVsCircle(x0: number, y0: number, dx: number, dy: number, cx: number, cy: number, R: number): number {\n const fx = x0 - cx, fy = y0 - cy;\n const a = dx * dx + dy * dy;\n if (a < 1e-12) return -1;\n const b = 2 * (fx * dx + fy * dy);\n // Already touching or overlapping (within a slop ring): the contact solver\n // owns this \u2014 a TOI of ~0 would pin a rolling/sliding ball in place.\n if (fx * fx + fy * fy < (R + 0.5) * (R + 0.5)) return -1;\n const c = fx * fx + fy * fy - R * R;\n const disc = b * b - 4 * a * c;\n if (disc < 0) return -1;\n const t = (-b - Math.sqrt(disc)) / (2 * a);\n return t >= 0 && t <= 1 ? t : -1;\n}\n\nfunction sweepVsSegment(x0: number, y0: number, dx: number, dy: number, ax: number, ay: number, bx: number, by: number): number {\n const ex = bx - ax, ey = by - ay;\n const denom = dx * ey - dy * ex;\n if (Math.abs(denom) < 1e-12) return -1;\n const t = ((ax - x0) * ey - (ay - y0) * ex) / denom;\n const s = ((ax - x0) * dy - (ay - y0) * dx) / denom;\n return t >= 0 && t <= 1 && s >= 0 && s <= 1 ? t : -1;\n}\n", "// Spatial queries against rigid bodies: point tests and raycasts.\n// Pure functions; results are deterministic (bodies scanned in array order).\n\nimport { dhypot } from '../core/dmath';\nimport type { RigidBody, RigidWorld } from './rigidBody';\nimport { worldPoints } from './rigidBody';\n\nexport interface RigidRayHit {\n id: number;\n t: number; // fraction along the ray [0,1]\n x: number; y: number; // hit point\n nx: number; ny: number; // surface normal\n}\n\n/** Is a world point inside this body's shape? */\nexport function bodyContains(b: RigidBody, x: number, y: number): boolean {\n if (b.shape.kind === 'circle') {\n const dx = x - b.x, dy = y - b.y;\n return dx * dx + dy * dy <= b.shape.r * b.shape.r;\n }\n const wp = worldPoints(b);\n const n = wp.length / 2;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ex = wp[j * 2] - wp[k * 2], ey = wp[j * 2 + 1] - wp[k * 2 + 1];\n if ((x - wp[k * 2]) * ey - (y - wp[k * 2 + 1]) * ex > 0) return false;\n }\n return true;\n}\n\n/** First body containing the point (topmost = last added wins ties via scan order). */\nexport function pointQuery(rw: RigidWorld, x: number, y: number, mask = 0xffff): RigidBody | undefined {\n let hit: RigidBody | undefined;\n for (const b of rw.bodies) if ((b.layer & mask) !== 0 && bodyContains(b, x, y)) hit = b;\n return hit;\n}\n\nfunction rayCircle(x0: number, y0: number, dx: number, dy: number, cx: number, cy: number, r: number): number {\n const fx = x0 - cx, fy = y0 - cy;\n const a = dx * dx + dy * dy;\n if (a < 1e-12) return -1;\n const b = 2 * (fx * dx + fy * dy);\n const c = fx * fx + fy * fy - r * r;\n const disc = b * b - 4 * a * c;\n if (disc < 0) return -1;\n const t = (-b - Math.sqrt(disc)) / (2 * a);\n return t >= 0 && t <= 1 ? t : -1;\n}\n\n/** Closest hit along the segment (x0,y0)\u2192(x1,y1), or null. */\nexport function rayCastRigid(rw: RigidWorld, x0: number, y0: number, x1: number, y1: number, mask = 0xffff): RigidRayHit | null {\n const dx = x1 - x0, dy = y1 - y0;\n let best: RigidRayHit | null = null;\n for (const b of rw.bodies) {\n if ((b.layer & mask) === 0) continue;\n if (b.shape.kind === 'circle') {\n const t = rayCircle(x0, y0, dx, dy, b.x, b.y, b.shape.r);\n if (t >= 0 && (!best || t < best.t)) {\n const hx = x0 + dx * t, hy = y0 + dy * t;\n const len = dhypot(hx - b.x, hy - b.y) || 1;\n best = { id: b.id, t, x: hx, y: hy, nx: (hx - b.x) / len, ny: (hy - b.y) / len };\n }\n continue;\n }\n const wp = worldPoints(b);\n const n = wp.length / 2;\n for (let k = 0; k < n; k++) {\n const j = (k + 1) % n;\n const ax = wp[k * 2], ay = wp[k * 2 + 1];\n const ex = wp[j * 2] - ax, ey = wp[j * 2 + 1] - ay;\n const denom = dx * ey - dy * ex;\n if (Math.abs(denom) < 1e-12) continue;\n const t = ((ax - x0) * ey - (ay - y0) * ex) / denom;\n const s = ((ax - x0) * dy - (ay - y0) * dx) / denom;\n if (t < 0 || t > 1 || s < 0 || s > 1) continue;\n if (!best || t < best.t) {\n const len = dhypot(ex, ey) || 1;\n best = { id: b.id, t, x: x0 + dx * t, y: y0 + dy * t, nx: ey / len, ny: -ex / len };\n }\n }\n }\n return best;\n}\n", "// The display list: a flat, backend-agnostic vocabulary of draw commands.\n// The scene tree *projects* to DrawCommand[]; a backend (SVG/Canvas/Headless)\n// consumes them. Pure data \u2014 no browser types \u2014 so the projection is testable.\n\nimport type { Transform } from '../core/math';\n\n/** One color stop of a gradient. `offset` is 0..1 along the gradient axis. */\nexport interface GradientStop {\n offset: number;\n color: string;\n}\n\n/**\n * A gradient fill in OBJECT-BOUNDING-BOX space: all coordinates are 0..1\n * relative to the painted shape's bounds, so the same gradient reads correctly\n * on a shape of any size or position (matches SVG `gradientUnits`).\n */\nexport interface LinearGradient {\n type: 'linear';\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n stops: GradientStop[];\n}\n\nexport interface RadialGradient {\n type: 'radial';\n /** Center + radius, all 0..1 in object-bounding-box space. */\n cx: number;\n cy: number;\n r: number;\n stops: GradientStop[];\n}\n\nexport type Gradient = LinearGradient | RadialGradient;\n\n/** A soft shadow / outer glow. `dx=dy=0` is a symmetric glow; offset = drop. */\nexport interface Shadow {\n color: string;\n /** Blur radius in local px. */\n blur: number;\n dx?: number;\n dy?: number;\n}\n\nexport interface Paint {\n fill?: string;\n stroke?: string;\n strokeWidth?: number;\n opacity?: number;\n /** Round line joins/caps for organic shapes. */\n round?: boolean;\n /** A gradient fill; when present it overrides `fill` for the shape body. */\n gradient?: Gradient;\n /** A soft outer glow / drop shadow applied to the shape. */\n shadow?: Shadow;\n /**\n * Dash pattern for strokes, in local px (`[dash, gap, \u2026]` \u2014 same as\n * Canvas2D `setLineDash` / SVG `stroke-dasharray`). Omit for solid lines.\n */\n lineDash?: number[];\n}\n\nexport type TextAlign = 'left' | 'center' | 'right';\n\ninterface Base extends Paint {\n /** World transform (design-space). */\n transform: Transform;\n /** Painter's-order key; ties broken by tree order. Default 0. */\n z: number;\n /**\n * Render layer: commands sort by layer FIRST, then z, then tree order.\n * Layer 0 (default) is the world; layer 1 is the screen-space overlay pass\n * (HUD, transitions) \u2014 set automatically for `Node.screenSpace` subtrees, so\n * overlays always paint above world content regardless of z values.\n */\n layer?: number;\n /**\n * Transient view chrome \u2014 a drifting popup, particle, or tween that lives for\n * a moment and is never something the player reads for meaning. Layout lints\n * (see verify/layout) skip these by default: a \"+10\" floating over a HUD label\n * is motion, not a collision. Set by cosmetic emitters (FloatingText/Particles).\n */\n transient?: boolean;\n}\n\nexport interface RectCommand extends Base {\n kind: 'rect';\n x: number;\n y: number;\n w: number;\n h: number;\n /** Corner radius. */\n r?: number;\n}\n\nexport interface CircleCommand extends Base {\n kind: 'circle';\n cx: number;\n cy: number;\n radius: number;\n}\n\nexport interface EllipseCommand extends Base {\n kind: 'ellipse';\n cx: number;\n cy: number;\n rx: number;\n ry: number;\n}\n\n/**\n * A circular arc (open stroke) or sector/pie (closed to the center).\n * Angles are radians, clockwise from +x (screen convention, y-down);\n * the arc runs from `start` to `end` in the clockwise direction.\n */\nexport interface ArcCommand extends Base {\n kind: 'arc';\n cx: number;\n cy: number;\n radius: number;\n start: number;\n end: number;\n /** When true, close through the center (a pie slice) so `fill` reads as a sector. */\n sector?: boolean;\n}\n\nexport interface PolyCommand extends Base {\n kind: 'poly';\n /** Flat [x0,y0,x1,y1,\u2026] in local space. */\n points: number[];\n closed: boolean;\n}\n\nexport interface PathCommand extends Base {\n kind: 'path';\n /** SVG path data in local space. */\n d: string;\n}\n\nexport interface TextCommand extends Base {\n kind: 'text';\n text: string;\n x: number;\n y: number;\n size: number;\n font?: string;\n align?: TextAlign;\n weight?: number;\n}\n\nexport interface ImageCommand extends Base {\n kind: 'image';\n /** data: URI or path. */\n href: string;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport type DrawCommand =\n | RectCommand\n | CircleCommand\n | EllipseCommand\n | ArcCommand\n | PolyCommand\n | PathCommand\n | TextCommand\n | ImageCommand;\n\n/** Stable painter's sort: by layer, then z, then original index (tree order) as tiebreak. */\nexport function sortCommands(cmds: DrawCommand[]): DrawCommand[] {\n return cmds\n .map((c, i) => [c, i] as const)\n .sort((a, b) => (a[0].layer ?? 0) - (b[0].layer ?? 0) || a[0].z - b[0].z || a[1] - b[1])\n .map(([c]) => c);\n}\n", "// Paint builders + backend resolution for gradients and soft shadows/glows.\n// The display-list vocabulary (commands.ts) carries gradients/shadows as pure\n// data in OBJECT-BOUNDING-BOX space (all coords 0..1 of the painted shape's\n// bounds); this module turns that data into SVG <defs> or Canvas paint objects.\n//\n// COSMETIC: these describe *look*, never state. Used on cosmetic nodes they stay\n// out of world.hash(); on canonical nodes the plain-JSON descriptors hash\n// deterministically like any other paint prop. No wall-clock, no Math.random.\n\nimport { dcos, dsin } from '../core/dmath';\nimport type {\n DrawCommand,\n Gradient,\n GradientStop,\n LinearGradient,\n RadialGradient,\n Shadow,\n} from './commands';\n\nconst n = (v: number): string => (Number.isInteger(v) ? String(v) : (Math.round(v * 1000) / 1000).toString());\n\ntype StopInput = string | GradientStop;\n\n/** Colors \u2192 evenly-spaced stops; explicit `{offset,color}` pass through. */\nfunction toStops(stops: readonly StopInput[]): GradientStop[] {\n const last = Math.max(1, stops.length - 1);\n return stops.map((s, i) => (typeof s === 'string' ? { offset: i / last, color: s } : s));\n}\n\n/**\n * A linear gradient by angle in degrees (0 = left\u2192right, 90 = top\u2192bottom).\n * Stops are colors (auto-spaced) or explicit `{offset, color}`.\n */\nexport function linearGradient(stops: readonly StopInput[], angleDeg = 90): LinearGradient {\n const a = (angleDeg * Math.PI) / 180;\n const dx = dcos(a) * 0.5;\n const dy = dsin(a) * 0.5;\n return { type: 'linear', x1: 0.5 - dx, y1: 0.5 - dy, x2: 0.5 + dx, y2: 0.5 + dy, stops: toStops(stops) };\n}\n\n/** A radial gradient centered in the shape by default (inner stop first). */\nexport function radialGradient(\n stops: readonly StopInput[],\n opts: { cx?: number; cy?: number; r?: number } = {},\n): RadialGradient {\n return { type: 'radial', cx: opts.cx ?? 0.5, cy: opts.cy ?? 0.5, r: opts.r ?? 0.5, stops: toStops(stops) };\n}\n\n/** A symmetric soft outer glow. */\nexport function glow(color: string, blur: number): Shadow {\n return { color, blur };\n}\n\n/** A soft drop shadow, offset by (dx,dy). */\nexport function dropShadow(color: string, blur: number, dx = 0, dy = 0): Shadow {\n return { color, blur, dx, dy };\n}\n\n// \u2500\u2500 SVG <defs> emission \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction stopMarkup(stop: GradientStop): string {\n // A stop color may carry its own alpha as `rgba(...)`; SVG needs it split off,\n // but for our hex/rgb palette we simply pass stop-color through.\n return `<stop offset=\"${n(stop.offset)}\" stop-color=\"${stop.color}\"/>`;\n}\n\nexport function gradientDef(g: Gradient, id: string): string {\n const stops = g.stops.map(stopMarkup).join('');\n if (g.type === 'linear') {\n return `<linearGradient id=\"${id}\" x1=\"${n(g.x1)}\" y1=\"${n(g.y1)}\" x2=\"${n(g.x2)}\" y2=\"${n(g.y2)}\">${stops}</linearGradient>`;\n }\n return `<radialGradient id=\"${id}\" cx=\"${n(g.cx)}\" cy=\"${n(g.cy)}\" r=\"${n(g.r)}\">${stops}</radialGradient>`;\n}\n\nexport function shadowDef(s: Shadow, id: string): string {\n // Generous region so wide blurs aren't clipped by the default filter box.\n return (\n `<filter id=\"${id}\" x=\"-60%\" y=\"-60%\" width=\"220%\" height=\"220%\">` +\n `<feDropShadow dx=\"${n(s.dx ?? 0)}\" dy=\"${n(s.dy ?? 0)}\" stdDeviation=\"${n(s.blur / 2)}\" flood-color=\"${s.color}\"/>` +\n `</filter>`\n );\n}\n\n// \u2500\u2500 Canvas resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport interface BBox {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Local-space bounding box of a shape command (null for paths/text/image). */\nexport function shapeBBox(c: DrawCommand): BBox | null {\n switch (c.kind) {\n case 'rect':\n return { x: c.x, y: c.y, w: c.w, h: c.h };\n case 'circle':\n return { x: c.cx - c.radius, y: c.cy - c.radius, w: c.radius * 2, h: c.radius * 2 };\n case 'ellipse':\n return { x: c.cx - c.rx, y: c.cy - c.ry, w: c.rx * 2, h: c.ry * 2 };\n case 'arc':\n // The full circle the arc lies on \u2014 good enough for gradient mapping.\n return { x: c.cx - c.radius, y: c.cy - c.radius, w: c.radius * 2, h: c.radius * 2 };\n case 'poly': {\n if (c.points.length < 2) return null;\n let minX = c.points[0];\n let maxX = c.points[0];\n let minY = c.points[1];\n let maxY = c.points[1];\n for (let i = 0; i < c.points.length; i += 2) {\n minX = Math.min(minX, c.points[i]);\n maxX = Math.max(maxX, c.points[i]);\n minY = Math.min(minY, c.points[i + 1]);\n maxY = Math.max(maxY, c.points[i + 1]);\n }\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n }\n default:\n return null;\n }\n}\n\n// \u2500\u2500 Renderer robustness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A malformed DrawCommand (NaN position from a physics blowup, a negative\n// radius from an over-eager tween) must never kill the render loop. Backends\n// call invalidCommandReason() per command and skip+warn instead of throwing\n// (triage: ptg 34). Valid commands cost only a few Number.isFinite calls \u2014\n// no allocation on the hot path.\n\n/** Why a command's geometry is unpaintable, or null when it's fine. */\nexport function invalidCommandReason(c: DrawCommand): string | null {\n switch (c.kind) {\n case 'rect':\n if (!Number.isFinite(c.x) || !Number.isFinite(c.y) || !Number.isFinite(c.w) || !Number.isFinite(c.h))\n return 'non-finite x/y/w/h';\n return null;\n case 'circle':\n if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy)) return 'non-finite center';\n if (!Number.isFinite(c.radius)) return 'non-finite radius';\n if (c.radius < 0) return 'negative radius';\n return null;\n case 'ellipse':\n if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy)) return 'non-finite center';\n if (!Number.isFinite(c.rx) || !Number.isFinite(c.ry)) return 'non-finite rx/ry';\n if (c.rx < 0 || c.ry < 0) return 'negative rx/ry';\n return null;\n case 'arc':\n if (!Number.isFinite(c.cx) || !Number.isFinite(c.cy)) return 'non-finite center';\n if (!Number.isFinite(c.radius)) return 'non-finite radius';\n if (c.radius < 0) return 'negative radius';\n if (!Number.isFinite(c.start) || !Number.isFinite(c.end)) return 'non-finite start/end';\n return null;\n default:\n return null;\n }\n}\n\nconst warnedCommands = new Set<string>();\n\n/**\n * console.warn once per (kind + reason) \u2014 a bad value animating every frame\n * logs a single line, not sixty a second. `detail` (the offending command or\n * error) is passed through so the console shows the actual value.\n */\nexport function warnCommandOnce(kind: string, reason: string, detail?: unknown): void {\n const key = `${kind}:${reason}`;\n if (warnedCommands.has(key)) return;\n warnedCommands.add(key);\n console.warn(`hayao/render: skipped '${kind}' command \u2014 ${reason}`, detail);\n}\n\n/** Build a Canvas gradient mapped from object-bounding-box space into `bbox`. */\nexport function canvasGradient(\n ctx: { createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient; createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient },\n g: Gradient,\n bbox: BBox,\n): CanvasGradient {\n const px = (u: number): number => bbox.x + u * bbox.w;\n const py = (v: number): number => bbox.y + v * bbox.h;\n let grad: CanvasGradient;\n if (g.type === 'linear') {\n grad = ctx.createLinearGradient(px(g.x1), py(g.y1), px(g.x2), py(g.y2));\n } else {\n // Map the unit radius by the larger box extent so it reads round-ish.\n const r = g.r * Math.max(bbox.w, bbox.h);\n grad = ctx.createRadialGradient(px(g.cx), py(g.cy), 0, px(g.cx), py(g.cy), r);\n }\n for (const s of g.stops) grad.addColorStop(Math.max(0, Math.min(1, s.offset)), s.color);\n return grad;\n}\n", "import type { DrawCommand } from './commands';\nimport type { Vec2 } from '../core/math';\n\n/** A backend that paints a display list into a host (DOM, canvas, or nothing). */\nexport interface Renderer {\n readonly width: number;\n readonly height: number;\n /** Paint one frame. */\n draw(commands: DrawCommand[]): void;\n /** Attach to a DOM parent (browser backends). */\n mount?(parent: HTMLElement): void;\n /** The mounted DOM node (canvas or svg), for attaching pointer listeners. */\n readonly element?: HTMLElement | SVGElement;\n /**\n * Invert the display transform: a browser pointer event's clientX/clientY \u2192\n * design-space coordinates. The backend owns the letterbox (`object-fit:\n * contain` / `preserveAspectRatio`) and DPR, so it's the only place that can\n * undo them correctly. Returns design coords even outside the letterbox\n * (values fall outside 0..width/height there).\n */\n toDesign?(clientX: number, clientY: number): Vec2;\n /**\n * The drawn (letterboxed) design area within the mount, in mount-local px:\n * `{ x, y, width, height, scale }`. Host-drawn UI (floating touch controls,\n * DOM HUD) anchors to this rect instead of re-deriving the `object-fit:\n * contain` math the backend already does for `toDesign`. Undefined for\n * headless backends.\n */\n viewport?(): Viewport;\n dispose?(): void;\n}\n\n/** The drawn area within the mount: offset + size in host px, plus design\u2192px scale. */\nexport interface Viewport {\n x: number;\n y: number;\n width: number;\n height: number;\n scale: number;\n}\n\nexport interface RendererConfig {\n width: number;\n height: number;\n background?: string;\n}\n\n/**\n * Undo a centered uniform-fit (`object-fit: contain` / SVG `xMidYMid meet`):\n * map a client pixel inside `rect` back to the design box `width\u00D7height`. Shared\n * by every DOM backend so the letterbox math lives in exactly one place.\n */\nexport function clientToDesign(rect: { left: number; top: number; width: number; height: number }, width: number, height: number, clientX: number, clientY: number): Vec2 {\n const scale = Math.min(rect.width / width, rect.height / height) || 1;\n const offsetX = (rect.width - width * scale) / 2;\n const offsetY = (rect.height - height * scale) / 2;\n return {\n x: (clientX - rect.left - offsetX) / scale,\n y: (clientY - rect.top - offsetY) / scale,\n };\n}\n\n/**\n * The centered uniform-fit rect for a design box inside an element of size\n * `rect` \u2014 the inverse framing of `clientToDesign`, in element-local px. Shared\n * by every DOM backend's `viewport()`.\n */\nexport function fitViewport(rect: { width: number; height: number }, width: number, height: number): Viewport {\n const scale = Math.min(rect.width / width, rect.height / height) || 1;\n return {\n x: (rect.width - width * scale) / 2,\n y: (rect.height - height * scale) / 2,\n width: width * scale,\n height: height * scale,\n scale,\n };\n}\n", "// Pure display-list \u2192 SVG markup. No DOM required, so it runs in Node \u2014 which\n// means the engine can produce a *vector screenshot* of any frame headlessly\n// (an AI-first win: judge layout from a file, no browser, no GPU, no fuzz).\n// The DOM SvgRenderer reuses this; tests assert on it directly.\n\nimport { sortCommands, type ArcCommand, type DrawCommand, type Paint } from './commands';\nimport { gradientDef, invalidCommandReason, shadowDef, warnCommandOnce } from './paint';\nimport { TAU, type Transform } from '../core/math';\nimport { dcos, dsin } from '../core/dmath';\n\nconst n = (v: number): string => (Number.isInteger(v) ? String(v) : (Math.round(v * 1000) / 1000).toString());\n\nfunction matrix(t: Transform): string {\n return `matrix(${n(t.a)} ${n(t.b)} ${n(t.c)} ${n(t.d)} ${n(t.e)} ${n(t.f)})`;\n}\n\nfunction paintAttrs(p: Paint, fillOverride?: string, filterId?: string): string {\n const parts: string[] = [];\n parts.push(`fill=\"${fillOverride ?? p.fill ?? 'none'}\"`);\n if (p.stroke) {\n parts.push(`stroke=\"${p.stroke}\"`);\n parts.push(`stroke-width=\"${n(p.strokeWidth ?? 1)}\"`);\n if (p.round) parts.push('stroke-linejoin=\"round\" stroke-linecap=\"round\"');\n if (p.lineDash && p.lineDash.length) parts.push(`stroke-dasharray=\"${p.lineDash.map(n).join(' ')}\"`);\n }\n if (p.opacity !== undefined && p.opacity !== 1) parts.push(`opacity=\"${n(p.opacity)}\"`);\n if (filterId) parts.push(`filter=\"url(#${filterId})\"`);\n return parts.join(' ');\n}\n\nfunction escapeText(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n/**\n * Path data for an arc/sector. Angles are radians, clockwise from +x in the\n * y-down screen convention \u2014 which is SVG sweep-flag 1. Sweeps over half a\n * turn set large-arc-flag; a full turn splits into two half-turn A commands\n * (a single A whose endpoints coincide renders nothing).\n */\nfunction arcPathData(c: ArcCommand): string {\n const r = c.radius;\n const x0 = c.cx + dcos(c.start) * r;\n const y0 = c.cy + dsin(c.start) * r;\n const raw = c.end - c.start;\n let sweep = ((raw % TAU) + TAU) % TAU;\n if (sweep === 0 && raw !== 0) sweep = TAU;\n if (sweep >= TAU - 1e-9) {\n const xh = c.cx + dcos(c.start + Math.PI) * r;\n const yh = c.cy + dsin(c.start + Math.PI) * r;\n return `M ${n(x0)} ${n(y0)} A ${n(r)} ${n(r)} 0 1 1 ${n(xh)} ${n(yh)} A ${n(r)} ${n(r)} 0 1 1 ${n(x0)} ${n(y0)} Z`;\n }\n const x1 = c.cx + dcos(c.start + sweep) * r;\n const y1 = c.cy + dsin(c.start + sweep) * r;\n const large = sweep > Math.PI ? 1 : 0;\n const a = `A ${n(r)} ${n(r)} 0 ${large} 1 ${n(x1)} ${n(y1)}`;\n return c.sector\n ? `M ${n(c.cx)} ${n(c.cy)} L ${n(x0)} ${n(y0)} ${a} Z`\n : `M ${n(x0)} ${n(y0)} ${a}`;\n}\n\n// A command may carry a gradient fill and/or a soft shadow. Both become entries\n// in <defs> with ids salted by `idBase` (unique per command, per render) so\n// multiple panels composited into one document never cross-reference.\nfunction commandToSVG(c: DrawCommand, defs: string[], idBase: string): string {\n const tf = `transform=\"${matrix(c.transform)}\"`;\n let fillOverride: string | undefined;\n let filterId: string | undefined;\n if (c.gradient) {\n const id = `${idBase}g`;\n defs.push(gradientDef(c.gradient, id));\n fillOverride = `url(#${id})`;\n }\n if (c.shadow) {\n filterId = `${idBase}s`;\n defs.push(shadowDef(c.shadow, filterId));\n }\n const paint = paintAttrs(c, fillOverride, filterId);\n switch (c.kind) {\n case 'rect':\n return `<rect x=\"${n(c.x)}\" y=\"${n(c.y)}\" width=\"${n(c.w)}\" height=\"${n(c.h)}\"${c.r ? ` rx=\"${n(c.r)}\"` : ''} ${tf} ${paint}/>`;\n case 'circle':\n return `<circle cx=\"${n(c.cx)}\" cy=\"${n(c.cy)}\" r=\"${n(c.radius)}\" ${tf} ${paint}/>`;\n case 'ellipse':\n return `<ellipse cx=\"${n(c.cx)}\" cy=\"${n(c.cy)}\" rx=\"${n(c.rx)}\" ry=\"${n(c.ry)}\" ${tf} ${paint}/>`;\n case 'arc':\n return `<path d=\"${arcPathData(c)}\" ${tf} ${paint}/>`;\n case 'poly': {\n const pts = [];\n for (let i = 0; i < c.points.length; i += 2) pts.push(`${n(c.points[i])},${n(c.points[i + 1])}`);\n const tag = c.closed ? 'polygon' : 'polyline';\n return `<${tag} points=\"${pts.join(' ')}\" ${tf} ${paint}/>`;\n }\n case 'path':\n return `<path d=\"${c.d}\" ${tf} ${paint}/>`;\n case 'text': {\n const anchor = c.align === 'center' ? 'middle' : c.align === 'right' ? 'end' : 'start';\n const font = c.font ? ` font-family=\"${c.font}\"` : '';\n const weight = c.weight ? ` font-weight=\"${c.weight}\"` : '';\n const fill = fillOverride ?? c.fill ?? '#000';\n const filter = filterId ? ` filter=\"url(#${filterId})\"` : '';\n // Text carries Paint, so an explicit `stroke` outlines the glyph.\n // paint-order=\"stroke\" lays the outline UNDER the fill so a thick stroke\n // frames the letter instead of eating into it \u2014 the crisp readable-on-any-\n // background look consumers otherwise faked with stacked halo copies.\n const stroke = c.stroke\n ? ` stroke=\"${c.stroke}\" stroke-width=\"${n(c.strokeWidth ?? 1)}\" paint-order=\"stroke\"${c.round ? ' stroke-linejoin=\"round\"' : ''}`\n : '';\n const opacity = c.opacity !== undefined && c.opacity !== 1 ? ` opacity=\"${n(c.opacity)}\"` : '';\n return `<text x=\"${n(c.x)}\" y=\"${n(c.y)}\" font-size=\"${n(c.size)}\" text-anchor=\"${anchor}\" dominant-baseline=\"middle\"${font}${weight} fill=\"${fill}\"${stroke}${opacity}${filter} ${tf}>${escapeText(c.text)}</text>`;\n }\n case 'image': {\n const filter = filterId ? ` filter=\"url(#${filterId})\"` : '';\n return `<image href=\"${c.href}\" x=\"${n(c.x)}\" y=\"${n(c.y)}\" width=\"${n(c.w)}\" height=\"${n(c.h)}\" ${tf}${c.opacity !== undefined && c.opacity !== 1 ? ` opacity=\"${n(c.opacity)}\"` : ''}${filter}/>`;\n }\n }\n}\n\n/**\n * Inner SVG markup for a display list (no wrapping <svg>). `idPrefix` salts the\n * ids of any gradient/shadow <defs> so several inner markups can share one SVG\n * document (e.g. a filmstrip) without their `url(#\u2026)` references colliding.\n */\nexport function commandsToSVGInner(commands: DrawCommand[], idPrefix = 'h'): string {\n const defs: string[] = [];\n const body = sortCommands(commands)\n .map((c, i) => {\n // Same robustness contract as Canvas2D: skip + warn-once on malformed\n // geometry instead of emitting broken markup.\n const bad = invalidCommandReason(c);\n if (bad) {\n warnCommandOnce(c.kind, bad, c);\n return '';\n }\n return commandToSVG(c, defs, `${idPrefix}${i}`);\n })\n .join('');\n return (defs.length ? `<defs>${defs.join('')}</defs>` : '') + body;\n}\n\n/** A complete, standalone SVG document string for a frame \u2014 a headless screenshot. */\nexport function renderToSVGString(\n commands: DrawCommand[],\n width: number,\n height: number,\n background = '#ffffff',\n): string {\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${width} ${height}\" width=\"${width}\" height=\"${height}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${width}\" height=\"${height}\" fill=\"${background}\"/>` +\n commandsToSVGInner(commands) +\n `</svg>`\n );\n}\n", "// SVG DOM backend. Resolution-independent (crisp at any DPR \u2014 the OHYG lesson:\n// SVG sidesteps canvas text fuzz entirely) and DOM-inspectable, which makes\n// browser verification trivial: querySelector IS the probe.\n\nimport type { DrawCommand } from './commands';\nimport { clientToDesign, fitViewport, type Renderer, type RendererConfig, type Viewport } from './renderer';\nimport { commandsToSVGInner } from './svgString';\nimport type { Vec2 } from '../core/math';\n\nconst SVGNS = 'http://www.w3.org/2000/svg';\n\nexport class SvgRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private svg: SVGSVGElement;\n private bg: SVGRectElement;\n private layer: SVGGElement;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n\n this.svg = document.createElementNS(SVGNS, 'svg');\n this.svg.setAttribute('viewBox', `0 0 ${this.width} ${this.height}`);\n this.svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\n this.svg.style.width = '100%';\n this.svg.style.height = '100%';\n this.svg.style.display = 'block';\n\n this.bg = document.createElementNS(SVGNS, 'rect');\n this.bg.setAttribute('x', '0');\n this.bg.setAttribute('y', '0');\n this.bg.setAttribute('width', String(this.width));\n this.bg.setAttribute('height', String(this.height));\n this.bg.setAttribute('fill', this.background);\n this.svg.appendChild(this.bg);\n\n this.layer = document.createElementNS(SVGNS, 'g');\n this.svg.appendChild(this.layer);\n }\n\n mount(parent: HTMLElement): void {\n parent.appendChild(this.svg);\n }\n\n draw(commands: DrawCommand[]): void {\n // Simple and correct for v0.1: rebuild the layer markup each frame. SVG is\n // retained-mode so the browser diffs efficiently; heavy scenes use Canvas2D.\n this.layer.innerHTML = commandsToSVGInner(commands);\n }\n\n setBackground(color: string): void {\n this.background = color;\n this.bg.setAttribute('fill', color);\n }\n\n get element(): SVGSVGElement {\n return this.svg;\n }\n\n /** Map a pointer event's clientX/Y into design space (undoes the letterbox). */\n toDesign(clientX: number, clientY: number): Vec2 {\n return clientToDesign(this.svg.getBoundingClientRect(), this.width, this.height, clientX, clientY);\n }\n\n viewport(): Viewport {\n return fitViewport(this.svg.getBoundingClientRect(), this.width, this.height);\n }\n\n dispose(): void {\n this.svg.remove();\n }\n}\n", "// Shared Canvas2D drawing logic \u2014 consumed by Canvas2DRenderer and WebGL2Renderer.\n// Extracted so the rasterization path is the SAME for both backends: WebGL2 uses\n// Canvas2D as an offscreen rasterizer and uploads the result as a texture.\n\nimport { sortCommands, type DrawCommand, type Paint } from './commands';\nimport { canvasGradient, invalidCommandReason, shapeBBox, warnCommandOnce } from './paint';\n\ntype Ctx2D = CanvasRenderingContext2D;\n\nfunction fillFor(ctx: Ctx2D, c: DrawCommand): string | CanvasGradient | undefined {\n const p = c as Paint;\n if (p.gradient) {\n const bbox = shapeBBox(c);\n if (bbox && bbox.w > 0 && bbox.h > 0) return canvasGradient(ctx, p.gradient, bbox);\n const stops = p.gradient.stops;\n return stops.length ? stops[stops.length - 1].color : p.fill;\n }\n return p.fill;\n}\n\nfunction applyStroke(ctx: Ctx2D, c: DrawCommand): void {\n const fill = fillFor(ctx, c);\n if (fill && fill !== 'none') {\n ctx.fillStyle = fill;\n ctx.fill();\n }\n if (c.stroke) {\n ctx.strokeStyle = c.stroke;\n ctx.lineWidth = c.strokeWidth ?? 1;\n if (c.round) {\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n }\n ctx.stroke();\n }\n}\n\nfunction roundRectPath(ctx: Ctx2D, x: number, y: number, w: number, h: number, r: number): void {\n const rr = Math.min(r, w / 2, h / 2);\n ctx.moveTo(x + rr, y);\n ctx.arcTo(x + w, y, x + w, y + h, rr);\n ctx.arcTo(x + w, y + h, x, y + h, rr);\n ctx.arcTo(x, y + h, x, y, rr);\n ctx.arcTo(x, y, x + w, y, rr);\n ctx.closePath();\n}\n\nfunction paintCommand(ctx: Ctx2D, c: DrawCommand): void {\n switch (c.kind) {\n case 'rect':\n ctx.beginPath();\n if (c.r) roundRectPath(ctx, c.x, c.y, c.w, c.h, c.r);\n else ctx.rect(c.x, c.y, c.w, c.h);\n applyStroke(ctx, c);\n break;\n case 'circle':\n ctx.beginPath();\n ctx.arc(c.cx, c.cy, c.radius, 0, Math.PI * 2);\n applyStroke(ctx, c);\n break;\n case 'ellipse':\n ctx.beginPath();\n ctx.ellipse(c.cx, c.cy, c.rx, c.ry, 0, 0, Math.PI * 2);\n applyStroke(ctx, c);\n break;\n case 'arc':\n // Angles are radians, clockwise from +x (y-down screen convention) \u2014\n // exactly ctx.arc's default direction. A sector closes through the center.\n ctx.beginPath();\n if (c.sector) ctx.moveTo(c.cx, c.cy);\n ctx.arc(c.cx, c.cy, c.radius, c.start, c.end);\n if (c.sector) ctx.closePath();\n applyStroke(ctx, c);\n break;\n case 'poly':\n ctx.beginPath();\n for (let i = 0; i < c.points.length; i += 2) {\n if (i === 0) ctx.moveTo(c.points[i], c.points[i + 1]);\n else ctx.lineTo(c.points[i], c.points[i + 1]);\n }\n if (c.closed) ctx.closePath();\n applyStroke(ctx, c);\n break;\n case 'path': {\n const p = new Path2D(c.d);\n const fill = fillFor(ctx, c);\n if (fill && fill !== 'none') {\n ctx.fillStyle = fill;\n ctx.fill(p);\n }\n if (c.stroke) {\n ctx.strokeStyle = c.stroke;\n ctx.lineWidth = c.strokeWidth ?? 1;\n if (c.round) {\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n }\n ctx.stroke(p);\n }\n break;\n }\n case 'text':\n ctx.font = `${c.weight ?? 400} ${c.size}px ${c.font ?? 'sans-serif'}`;\n ctx.textAlign = c.align ?? 'left';\n ctx.textBaseline = 'middle';\n // Stroke first so the outline frames the glyph (matches SVG paint-order=\"stroke\").\n if (c.stroke) {\n ctx.strokeStyle = c.stroke;\n ctx.lineWidth = c.strokeWidth ?? 1;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.strokeText(c.text, c.x, c.y);\n }\n ctx.fillStyle = c.fill ?? '#000';\n ctx.fillText(c.text, c.x, c.y);\n break;\n case 'image':\n break; // async images omitted in this rasterizer version\n }\n}\n\n/**\n * Paint a sorted display list onto an existing Canvas2D context at `scale`\n * (device pixel ratio). The caller is responsible for sizing the canvas to\n * `width * scale` \u00D7 `height * scale` before calling.\n */\nexport function drawToCanvas2D(\n ctx: Ctx2D,\n commands: DrawCommand[],\n width: number,\n height: number,\n background: string,\n scale: number,\n): void {\n ctx.setTransform(scale, 0, 0, scale, 0, 0);\n ctx.fillStyle = background;\n ctx.fillRect(0, 0, width, height);\n\n for (const c of sortCommands(commands)) {\n // Malformed geometry (NaN positions, negative radii\u2026) is skipped with a\n // warn-once instead of poisoning the canvas path state or throwing.\n const bad = invalidCommandReason(c);\n if (bad) {\n warnCommandOnce(c.kind, bad, c);\n continue;\n }\n ctx.save();\n try {\n const t = c.transform;\n ctx.transform(t.a, t.b, t.c, t.d, t.e, t.f);\n ctx.globalAlpha = (c as Paint).opacity ?? 1;\n const sh = (c as Paint).shadow;\n if (sh) {\n ctx.shadowColor = sh.color;\n ctx.shadowBlur = sh.blur;\n ctx.shadowOffsetX = sh.dx ?? 0;\n ctx.shadowOffsetY = sh.dy ?? 0;\n }\n const dash = (c as Paint).lineDash;\n // setLineDash is part of the saved drawing state \u2014 restore() resets it.\n if (dash && dash.length) ctx.setLineDash(dash);\n paintCommand(ctx, c);\n } catch (err) {\n // Per-command isolation: one bad draw must never kill the render loop.\n warnCommandOnce(c.kind, 'paint threw', err);\n }\n ctx.restore();\n }\n}\n", "// Canvas2D backend. For scenes with many primitives/particles where SVG's DOM\n// node count would bite. Same display list, immediate-mode painting, DPR-aware.\n\nimport type { DrawCommand } from './commands';\nimport { clientToDesign, fitViewport, type Renderer, type RendererConfig, type Viewport } from './renderer';\nimport { drawToCanvas2D } from './canvas2d-core';\nimport type { Vec2 } from '../core/math';\n\nexport class Canvas2DRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private dpr = 1;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n this.canvas = document.createElement('canvas');\n this.canvas.style.width = '100%';\n this.canvas.style.height = '100%';\n // Letterbox, never stretch or crop: the design space must arrive intact\n // (a stretched canvas hides gameplay at the edges on off-ratio windows).\n this.canvas.style.objectFit = 'contain';\n this.canvas.style.display = 'block';\n const ctx = this.canvas.getContext('2d');\n if (!ctx) throw new Error('hayao: 2D canvas context unavailable');\n this.ctx = ctx;\n this.resize();\n }\n\n mount(parent: HTMLElement): void {\n parent.appendChild(this.canvas);\n this.resize();\n }\n\n private resize(): void {\n this.dpr = Math.min(3, globalThis.devicePixelRatio || 1);\n this.canvas.width = Math.round(this.width * this.dpr);\n this.canvas.height = Math.round(this.height * this.dpr);\n }\n\n draw(commands: DrawCommand[]): void {\n drawToCanvas2D(this.ctx, commands, this.width, this.height, this.background, this.dpr);\n }\n\n get element(): HTMLCanvasElement {\n return this.canvas;\n }\n\n /** Map a pointer event's clientX/Y into design space (undoes the letterbox). */\n toDesign(clientX: number, clientY: number): Vec2 {\n return clientToDesign(this.canvas.getBoundingClientRect(), this.width, this.height, clientX, clientY);\n }\n\n viewport(): Viewport {\n return fitViewport(this.canvas.getBoundingClientRect(), this.width, this.height);\n }\n\n dispose(): void {\n this.canvas.remove();\n }\n}\n", "// WebGL2 backend \u2014 the GPU display surface for hayao.\n//\n// Architecture: Canvas2D rasterizes the display list to an offscreen canvas;\n// WebGL2 uploads the result as a texture and runs it through a programmable\n// GLSL post-processing pipeline. This gives:\n//\n// 1. Pixel-exact parity with Canvas2DRenderer for ALL command types\n// (text, paths, gradients, shadows) with zero per-type GPU code.\n// 2. A programmable multi-pass post-processing pipeline with auto-uniforms\n// (u_time, u_resolution) and user-settable uniforms (setUniform).\n// 3. Standard multi-pass patterns via setPipeline(): bloom, blur chains,\n// composite effects \u2014 each pass reads u_scene (original frame) and\n// u_prev (previous pass output).\n// 4. Named built-in effects via WEBGL_EFFECTS \u2014 import and use without\n// writing GLSL.\n//\n// Sim/determinism contract: untouched. This renderer is a pure display-list\n// consumer. Wall-clock (u_time) is host-only and never enters world.hash().\n\nimport type { DrawCommand } from './commands';\nimport { clientToDesign, fitViewport, type Renderer, type RendererConfig, type Viewport } from './renderer';\nimport { drawToCanvas2D } from './canvas2d-core';\nimport type { Vec2 } from '../core/math';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Value for a GLSL uniform: float, vec2, vec3, or vec4. */\nexport type UniformValue = number | [number, number] | [number, number, number] | [number, number, number, number];\n\n/**\n * One pass in a post-processing pipeline. Each pass is a GLSL fragment shader\n * that receives:\n * uniform sampler2D u_scene \u2014 the original Canvas2D rasterized frame\n * uniform sampler2D u_prev \u2014 output of the previous pass (= u_scene for pass 0)\n * uniform float u_time \u2014 wall-clock seconds (cosmetic only, never hashed)\n * uniform vec2 u_resolution \u2014 display canvas size in pixels\n * in vec2 v_uv \u2014 0..1 UV with (0,0) at top-left\n * out vec4 fragColor \u2014 output pixel\n *\n * Plus any custom uniforms added via setUniform() or the pass's own `uniforms` map.\n */\nexport interface PostProcessPass {\n /** GLSL #version 300 es fragment shader source. */\n shader: string;\n /** Per-pass custom uniforms (merged with the renderer-level ones, pass overrides renderer). */\n uniforms?: Record<string, UniformValue>;\n}\n\n// \u2500\u2500 GLSL \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst VERT_SRC = /* glsl */ `#version 300 es\nout vec2 v_uv;\nvoid main() {\n const vec2 CORNERS[4] = vec2[](\n vec2(-1.0, -1.0), vec2(1.0, -1.0),\n vec2(-1.0, 1.0), vec2(1.0, 1.0)\n );\n const vec2 UVS[4] = vec2[](\n vec2(0.0, 1.0), vec2(1.0, 1.0),\n vec2(0.0, 0.0), vec2(1.0, 0.0)\n );\n v_uv = UVS[gl_VertexID];\n gl_Position = vec4(CORNERS[gl_VertexID], 0.0, 1.0);\n}`;\n\nconst PASSTHROUGH_FRAG = /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_scene;\nuniform sampler2D u_prev;\nout vec4 fragColor;\nvoid main() { fragColor = texture(u_prev, v_uv); }`;\n\n// \u2500\u2500 Named built-in effects \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Ready-made GLSL fragment shaders for common post-processing effects.\n * Use in setPostProcess() or as passes in setPipeline().\n *\n * Each effect references u_scene / u_prev / u_time / u_resolution as needed.\n * Custom tuning: pass a custom uniform via setUniform() \u2014 names are noted below.\n *\n * @example\n * ```ts\n * import { WebGL2Renderer, WEBGL_EFFECTS } from '@hayao';\n * const renderer = new WebGL2Renderer({ width, height, postProcess: WEBGL_EFFECTS.vignette });\n * // Tune: renderer.setUniform('u_vignette', 0.5);\n * ```\n */\nexport const WEBGL_EFFECTS = {\n /** Passthrough \u2014 no effect. */\n passthrough: PASSTHROUGH_FRAG,\n\n /** Pixelate: blockSize in pixels (default 4). setUniform('u_block', N) */\n pixelate: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform vec2 u_resolution;\nuniform float u_block;\nout vec4 fragColor;\nvoid main() {\n float block = max(1.0, u_block > 0.0 ? u_block : 4.0);\n vec2 px = floor(v_uv * u_resolution / block) * block / u_resolution;\n fragColor = texture(u_prev, px);\n}`,\n\n /** Vignette: darkens edges. setUniform('u_vignette', 0.0..1.0, default 0.4) */\n vignette: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform float u_vignette;\nout vec4 fragColor;\nvoid main() {\n vec4 col = texture(u_prev, v_uv);\n vec2 uv = v_uv - 0.5;\n float d = dot(uv, uv);\n float strength = u_vignette > 0.0 ? u_vignette : 0.4;\n fragColor = col * (1.0 - d * strength * 4.0);\n}`,\n\n /** CRT scanlines + slight barrel distortion. u_time drives the scan roll. */\n crt: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_crt_lines; // scanline density, default 600\nuniform float u_crt_warp; // barrel strength, default 0.08\nout vec4 fragColor;\nvoid main() {\n float lines = u_crt_lines > 0.0 ? u_crt_lines : 600.0;\n float warp = u_crt_warp > 0.0 ? u_crt_warp : 0.08;\n // barrel distortion\n vec2 uv = v_uv - 0.5;\n float r2 = dot(uv, uv);\n uv *= 1.0 + warp * r2;\n uv += 0.5;\n if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {\n fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n return;\n }\n vec4 col = texture(u_prev, uv);\n // rolling scanlines\n float scan = sin((uv.y * lines + u_time * 40.0) * 3.14159) * 0.5 + 0.5;\n col.rgb *= 0.75 + 0.25 * scan;\n // slight green phosphor tint\n col.rgb = mix(col.rgb, col.rgb * vec3(0.9, 1.05, 0.85), 0.3);\n fragColor = col;\n}`,\n\n /** Chromatic aberration / RGB fringe. setUniform('u_aberration', 0..0.01, default 0.004) */\n chromaticAberration: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform float u_aberration;\nout vec4 fragColor;\nvoid main() {\n float amt = u_aberration > 0.0 ? u_aberration : 0.004;\n vec2 dir = v_uv - 0.5;\n float r = texture(u_prev, v_uv + dir * amt * 2.0).r;\n float g = texture(u_prev, v_uv).g;\n float b = texture(u_prev, v_uv - dir * amt * 2.0).b;\n fragColor = vec4(r, g, b, 1.0);\n}`,\n\n /** Palette-shift / hue rotation. u_hue_shift in radians, driven by u_time for animation. */\n hueRotate: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform float u_hue_shift; // radians; if 0 uses u_time\nuniform float u_time;\nout vec4 fragColor;\nvoid main() {\n float angle = u_hue_shift != 0.0 ? u_hue_shift : u_time * 0.5;\n vec4 col = texture(u_prev, v_uv);\n // Hue rotate via Rodrigues in YIQ-ish space\n float c = cos(angle), s = sin(angle);\n mat3 m = mat3(\n 0.299+0.701*c+0.168*s, 0.587-0.587*c+0.330*s, 0.114-0.114*c-0.497*s,\n 0.299-0.299*c-0.328*s, 0.587+0.413*c+0.035*s, 0.114-0.114*c+0.292*s,\n 0.299-0.300*c+1.250*s, 0.587-0.588*c-1.050*s, 0.114+0.886*c-0.203*s\n );\n fragColor = vec4(m * col.rgb, col.a);\n}`,\n\n /** Wave distortion (heat haze, underwater). setUniform('u_wave_amp', default 0.003) */\n wave: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform float u_time;\nuniform float u_wave_amp;\nuniform float u_wave_freq;\nout vec4 fragColor;\nvoid main() {\n float amp = u_wave_amp > 0.0 ? u_wave_amp : 0.003;\n float freq = u_wave_freq > 0.0 ? u_wave_freq : 8.0;\n vec2 uv = v_uv;\n uv.x += sin(uv.y * freq + u_time * 2.5) * amp;\n uv.y += cos(uv.x * freq + u_time * 2.5) * amp;\n fragColor = texture(u_prev, clamp(uv, 0.0, 1.0));\n}`,\n\n // \u2500\u2500 Multi-pass bloom building blocks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Use with setPipeline([brightpass, hblur, vblur, bloomComposite]).\n\n /** Bloom pass 1/4: extract bright pixels above threshold (default 0.6). */\n bloomBrightpass: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform float u_bloom_threshold;\nout vec4 fragColor;\nvoid main() {\n vec4 col = texture(u_prev, v_uv);\n float lum = dot(col.rgb, vec3(0.2126, 0.7152, 0.0722));\n float thresh = u_bloom_threshold > 0.0 ? u_bloom_threshold : 0.55;\n float weight = smoothstep(thresh - 0.05, thresh + 0.05, lum);\n fragColor = col * weight;\n}`,\n\n /** Bloom pass 2/4: horizontal gaussian blur (13-tap). */\n bloomHBlur: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform vec2 u_resolution;\nuniform float u_bloom_spread;\nout vec4 fragColor;\nvoid main() {\n float spread = u_bloom_spread > 0.0 ? u_bloom_spread : 1.0;\n vec2 texel = vec2(spread / u_resolution.x, 0.0);\n const float W[7] = float[](0.0625, 0.125, 0.1875, 0.25, 0.1875, 0.125, 0.0625);\n vec4 sum = vec4(0.0);\n for (int i = 0; i < 7; i++)\n sum += texture(u_prev, clamp(v_uv + float(i-3) * texel, 0.0, 1.0)) * W[i];\n fragColor = sum;\n}`,\n\n /** Bloom pass 3/4: vertical gaussian blur (13-tap). */\n bloomVBlur: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_prev;\nuniform vec2 u_resolution;\nuniform float u_bloom_spread;\nout vec4 fragColor;\nvoid main() {\n float spread = u_bloom_spread > 0.0 ? u_bloom_spread : 1.0;\n vec2 texel = vec2(0.0, spread / u_resolution.y);\n const float W[7] = float[](0.0625, 0.125, 0.1875, 0.25, 0.1875, 0.125, 0.0625);\n vec4 sum = vec4(0.0);\n for (int i = 0; i < 7; i++)\n sum += texture(u_prev, clamp(v_uv + float(i-3) * texel, 0.0, 1.0)) * W[i];\n fragColor = sum;\n}`,\n\n /** Bloom pass 4/4: composite original + blurred bloom. u_bloom_intensity controls strength. */\n bloomComposite: /* glsl */ `#version 300 es\nprecision mediump float;\nin vec2 v_uv;\nuniform sampler2D u_scene;\nuniform sampler2D u_prev;\nuniform float u_bloom_intensity;\nout vec4 fragColor;\nvoid main() {\n vec4 scene = texture(u_scene, v_uv);\n vec4 bloom = texture(u_prev, v_uv);\n float intensity = u_bloom_intensity > 0.0 ? u_bloom_intensity : 0.8;\n fragColor = vec4(scene.rgb + bloom.rgb * intensity, scene.a);\n}`,\n} as const satisfies Record<string, string>;\n\n// Convenience bloom pipeline \u2014 the canonical 4-pass setup.\nexport const BLOOM_PIPELINE: PostProcessPass[] = [\n { shader: WEBGL_EFFECTS.bloomBrightpass },\n { shader: WEBGL_EFFECTS.bloomHBlur },\n { shader: WEBGL_EFFECTS.bloomVBlur },\n { shader: WEBGL_EFFECTS.bloomComposite },\n];\n\n// \u2500\u2500 WebGL helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction compileShader(gl: WebGL2RenderingContext, type: number, src: string): WebGLShader {\n const sh = gl.createShader(type);\n if (!sh) throw new Error('hayao/webgl: createShader failed');\n gl.shaderSource(sh, src);\n gl.compileShader(sh);\n if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {\n const log = gl.getShaderInfoLog(sh);\n gl.deleteShader(sh);\n throw new Error(`hayao/webgl: shader compile error\\n${log}`);\n }\n return sh;\n}\n\nfunction buildProgram(gl: WebGL2RenderingContext, fragSrc: string): WebGLProgram {\n const vert = compileShader(gl, gl.VERTEX_SHADER, VERT_SRC);\n const frag = compileShader(gl, gl.FRAGMENT_SHADER, fragSrc);\n const prog = gl.createProgram();\n if (!prog) throw new Error('hayao/webgl: createProgram failed');\n gl.attachShader(prog, vert);\n gl.attachShader(prog, frag);\n gl.linkProgram(prog);\n gl.deleteShader(vert);\n gl.deleteShader(frag);\n if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {\n const log = gl.getProgramInfoLog(prog);\n gl.deleteProgram(prog);\n throw new Error(`hayao/webgl: program link error\\n${log}`);\n }\n return prog;\n}\n\nfunction applyUniform(gl: WebGL2RenderingContext, prog: WebGLProgram, name: string, value: UniformValue): void {\n const loc = gl.getUniformLocation(prog, name);\n if (loc === null) return; // silently ignore unused uniforms\n if (typeof value === 'number') {\n gl.uniform1f(loc, value);\n } else if (value.length === 2) {\n gl.uniform2f(loc, value[0], value[1]);\n } else if (value.length === 3) {\n gl.uniform3f(loc, value[0], value[1], value[2]);\n } else {\n gl.uniform4f(loc, value[0], value[1], value[2], value[3]);\n }\n}\n\ninterface FboSlot {\n fbo: WebGLFramebuffer;\n tex: WebGLTexture;\n}\n\nfunction makeFboSlot(gl: WebGL2RenderingContext, w: number, h: number): FboSlot {\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return { fbo, tex };\n}\n\n// \u2500\u2500 WebGL2Renderer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WebGLRendererConfig extends RendererConfig {\n /**\n * Initial post-processing shader or pipeline. Pass a GLSL string for a\n * single-pass effect, or use setPipeline() for multi-pass. Defaults to\n * passthrough.\n */\n postProcess?: string;\n}\n\n/**\n * GPU-accelerated renderer with a programmable GLSL post-processing pipeline.\n *\n * ## Quick start\n * ```ts\n * import { WebGL2Renderer, WEBGL_EFFECTS, BLOOM_PIPELINE } from '@hayao';\n *\n * // Single-pass:\n * const renderer = new WebGL2Renderer({ width, height,\n * postProcess: WEBGL_EFFECTS.vignette });\n * renderer.setUniform('u_vignette', 0.5);\n *\n * // Multi-pass bloom:\n * const renderer = new WebGL2Renderer({ width, height });\n * renderer.setPipeline(BLOOM_PIPELINE);\n * renderer.setUniform('u_bloom_intensity', 1.2);\n *\n * // Runtime effect swap:\n * renderer.setPostProcess(WEBGL_EFFECTS.crt);\n * renderer.clearPostProcess(); // back to passthrough\n * ```\n *\n * ## Auto-uniforms (available in every shader, every pass)\n * - `uniform float u_time` \u2014 wall-clock seconds (cosmetic, never hashed)\n * - `uniform vec2 u_resolution` \u2014 display canvas size in px (w, h)\n * - `uniform sampler2D u_scene` \u2014 original Canvas2D rasterized frame\n * - `uniform sampler2D u_prev` \u2014 output of the previous pass (= u_scene for pass 0)\n *\n * ## Determinism\n * `u_time` is wall-clock and NOT part of `world.hash()`. The renderer is a\n * pure display-list consumer \u2014 it never writes state back into the engine.\n * All verify passes run against `HeadlessRenderer` / `SvgRenderer` and see\n * the same DrawCommand[] regardless of post-processing.\n */\nexport class WebGL2Renderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n\n private glCanvas: HTMLCanvasElement;\n private gl: WebGL2RenderingContext;\n private offscreen: HTMLCanvasElement;\n private ctx2d: CanvasRenderingContext2D;\n private dpr = 1;\n\n /** Original rasterized scene texture. */\n private sceneTex: WebGLTexture;\n /** Intermediate pass framebuffers (one per non-final pass). */\n private fbos: FboSlot[] = [];\n /** Compiled programs, one per pass. */\n private programs: WebGLProgram[] = [];\n /** Per-pass uniform maps (merged with global uniforms). */\n private passUniforms: Array<Record<string, UniformValue>> = [];\n /** Empty VAO for gl_VertexID-only draws. */\n private vao: WebGLVertexArrayObject;\n\n /** Frames drawn, driving u_time at a nominal 60 fps (cosmetic, but deterministic). */\n private framesDrawn = 0;\n /** Global custom uniforms applied to every pass. */\n private uniforms = new Map<string, UniformValue>();\n\n constructor(config: WebGLRendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n\n this.glCanvas = document.createElement('canvas');\n this.glCanvas.style.width = '100%';\n this.glCanvas.style.height = '100%';\n this.glCanvas.style.objectFit = 'contain';\n this.glCanvas.style.display = 'block';\n\n const gl = this.glCanvas.getContext('webgl2', { alpha: false, antialias: false, preserveDrawingBuffer: false });\n if (!gl) throw new Error('hayao/webgl: WebGL2 unavailable \u2014 fall back to Canvas2DRenderer');\n this.gl = gl;\n\n this.offscreen = document.createElement('canvas');\n const ctx2d = this.offscreen.getContext('2d');\n if (!ctx2d) throw new Error('hayao/webgl: Canvas2D unavailable for rasterization');\n this.ctx2d = ctx2d;\n\n this.resize();\n\n const vao = gl.createVertexArray();\n if (!vao) throw new Error('hayao/webgl: createVertexArray failed');\n this.vao = vao;\n\n const tex = gl.createTexture();\n if (!tex) throw new Error('hayao/webgl: createTexture failed');\n this.sceneTex = tex;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // Default: single passthrough pass.\n this.buildPipeline([{ shader: config.postProcess ?? PASSTHROUGH_FRAG }]);\n }\n\n mount(parent: HTMLElement): void {\n parent.appendChild(this.glCanvas);\n this.resize();\n }\n\n private resize(): void {\n this.dpr = Math.min(3, globalThis.devicePixelRatio || 1);\n const w = Math.round(this.width * this.dpr);\n const h = Math.round(this.height * this.dpr);\n this.glCanvas.width = w;\n this.glCanvas.height = h;\n this.offscreen.width = w;\n this.offscreen.height = h;\n this.gl.viewport(0, 0, w, h);\n // FBOs must be resized too.\n for (const slot of this.fbos) {\n this.gl.bindTexture(this.gl.TEXTURE_2D, slot.tex);\n this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, w, h, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n }\n }\n\n private buildPipeline(passes: PostProcessPass[]): void {\n const gl = this.gl;\n const w = this.glCanvas.width || Math.round(this.width * this.dpr);\n const h = this.glCanvas.height || Math.round(this.height * this.dpr);\n\n // Release old resources.\n for (const p of this.programs) gl.deleteProgram(p);\n for (const s of this.fbos) { gl.deleteFramebuffer(s.fbo); gl.deleteTexture(s.tex); }\n this.programs = [];\n this.fbos = [];\n this.passUniforms = [];\n\n for (const pass of passes) {\n this.programs.push(buildProgram(gl, pass.shader));\n this.passUniforms.push(pass.uniforms ?? {});\n }\n\n // Create N-1 intermediate FBOs (final pass renders to screen).\n for (let i = 0; i < passes.length - 1; i++) {\n this.fbos.push(makeFboSlot(gl, w, h));\n }\n }\n\n draw(commands: DrawCommand[]): void {\n const gl = this.gl;\n const n = this.programs.length;\n const t = this.framesDrawn++ / 60;\n const w = this.glCanvas.width;\n const h = this.glCanvas.height;\n\n // 1. Rasterize the display list onto the offscreen Canvas2D.\n drawToCanvas2D(this.ctx2d, commands, this.width, this.height, this.background, this.dpr);\n\n // 2. Upload the rasterized frame to the scene texture (TEXTURE0).\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.sceneTex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.offscreen);\n\n gl.bindVertexArray(this.vao);\n\n for (let i = 0; i < n; i++) {\n const prog = this.programs[i];\n const isLast = i === n - 1;\n\n // Target: intermediate FBO or screen.\n if (isLast) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, w, h);\n } else {\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbos[i].fbo);\n gl.viewport(0, 0, w, h);\n }\n\n gl.useProgram(prog);\n\n // u_scene = original scene (TEXTURE0).\n gl.uniform1i(gl.getUniformLocation(prog, 'u_scene'), 0);\n\n // u_prev = previous pass output (TEXTURE1), or scene if first pass.\n gl.activeTexture(gl.TEXTURE1);\n if (i === 0) {\n gl.bindTexture(gl.TEXTURE_2D, this.sceneTex);\n } else {\n gl.bindTexture(gl.TEXTURE_2D, this.fbos[i - 1].tex);\n }\n gl.uniform1i(gl.getUniformLocation(prog, 'u_prev'), 1);\n gl.activeTexture(gl.TEXTURE0);\n\n // Auto-uniforms.\n gl.uniform1f(gl.getUniformLocation(prog, 'u_time'), t);\n gl.uniform2f(gl.getUniformLocation(prog, 'u_resolution'), w, h);\n\n // Global custom uniforms.\n for (const [name, val] of this.uniforms) applyUniform(gl, prog, name, val);\n\n // Per-pass uniforms (override global).\n for (const [name, val] of Object.entries(this.passUniforms[i])) applyUniform(gl, prog, name, val);\n\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n }\n\n // \u2500\u2500 Public control API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Set a custom uniform applied to every pass. Useful for knob-driven effect\n * parameters (intensity, scale, colour) without recompiling the shader.\n * The value is set on every draw() until cleared or overridden.\n *\n * ```ts\n * renderer.setUniform('u_vignette', 0.5);\n * renderer.setUniform('u_bloom_intensity', [1.0, 0.8]);\n * ```\n */\n setUniform(name: string, value: UniformValue): this {\n this.uniforms.set(name, value);\n return this;\n }\n\n /** Remove a custom uniform. */\n clearUniform(name: string): this {\n this.uniforms.delete(name);\n return this;\n }\n\n /**\n * Replace the post-processing pipeline. Accepts an array of passes; each\n * pass reads `u_prev` (previous output) and `u_scene` (original frame).\n * Throws on shader compile error \u2014 previous pipeline stays active.\n *\n * For single-pass effects, prefer `setPostProcess(shader)`. For the standard\n * bloom setup, use `setPipeline(BLOOM_PIPELINE)`.\n *\n * ```ts\n * renderer.setPipeline([\n * { shader: WEBGL_EFFECTS.bloomBrightpass },\n * { shader: WEBGL_EFFECTS.bloomHBlur },\n * { shader: WEBGL_EFFECTS.bloomVBlur },\n * { shader: WEBGL_EFFECTS.bloomComposite },\n * ]);\n * renderer.setUniform('u_bloom_intensity', 1.0);\n * ```\n */\n setPipeline(passes: PostProcessPass[]): this {\n this.buildPipeline(passes.length ? passes : [{ shader: PASSTHROUGH_FRAG }]);\n return this;\n }\n\n /**\n * Convenience: set a single-pass post-processing shader.\n * Throws on compile error \u2014 previous effect stays active.\n */\n setPostProcess(fragmentShader: string): this {\n return this.setPipeline([{ shader: fragmentShader }]);\n }\n\n /** Restore passthrough (no post-processing). */\n clearPostProcess(): this {\n return this.setPostProcess(PASSTHROUGH_FRAG);\n }\n\n get element(): HTMLCanvasElement { return this.glCanvas; }\n\n toDesign(clientX: number, clientY: number): Vec2 {\n return clientToDesign(this.glCanvas.getBoundingClientRect(), this.width, this.height, clientX, clientY);\n }\n\n viewport(): Viewport {\n return fitViewport(this.glCanvas.getBoundingClientRect(), this.width, this.height);\n }\n\n dispose(): void {\n const gl = this.gl;\n gl.deleteTexture(this.sceneTex);\n for (const p of this.programs) gl.deleteProgram(p);\n for (const s of this.fbos) { gl.deleteFramebuffer(s.fbo); gl.deleteTexture(s.tex); }\n gl.deleteVertexArray(this.vao);\n this.glCanvas.remove();\n }\n}\n", "// The headless backend: records the last display list instead of painting it.\n// Tests assert on the commands directly; scripts turn them into a vector\n// screenshot via renderToSVGString. This is why a hayao game is testable with\n// zero browser \u2014 the renderer is just a data sink.\n\nimport type { DrawCommand } from './commands';\nimport type { Renderer, RendererConfig } from './renderer';\nimport { renderToSVGString } from './svgString';\n\nexport class HeadlessRenderer implements Renderer {\n readonly width: number;\n readonly height: number;\n private background: string;\n private last: DrawCommand[] = [];\n frameCount = 0;\n\n constructor(config: RendererConfig) {\n this.width = config.width;\n this.height = config.height;\n this.background = config.background ?? '#ffffff';\n }\n\n draw(commands: DrawCommand[]): void {\n this.last = commands;\n this.frameCount++;\n }\n\n /** The most recently drawn display list. */\n get commands(): DrawCommand[] {\n return this.last;\n }\n\n /** Count commands of a given kind (handy for assertions). */\n count(kind: DrawCommand['kind']): number {\n return this.last.filter((c) => c.kind === kind).length;\n }\n\n /** A vector screenshot of the last frame. */\n toSVGString(): string {\n return renderToSVGString(this.last, this.width, this.height, this.background);\n }\n}\n", "// 9-slice panels: one scalable UI frame from a handful of params. A rectangle is\n// split into a 3\u00D73 grid \u2014 the four corners keep a fixed size while the edges\n// stretch along one axis and the center fills \u2014 so a frame drawn at any size\n// keeps crisp, undistorted corners. Pure: it just emits DrawCommands into a\n// display list, so it renders headlessly and never touches game state. Colour the\n// regions differently (light top/left, dark bottom/right) for an instant bevel.\n\nimport { IDENTITY, type Rect, type Transform } from '../core/math';\nimport type { DrawCommand } from './commands';\n\nexport interface NineSliceStyle {\n /** Corner size in px \u2014 the slice inset that never stretches. */\n border: number;\n /** Center fill (the panel body). */\n fill?: string;\n /** Edge fill (top/bottom/left/right strips). Defaults to `fill`. */\n edge?: string;\n /** Corner fill (the four fixed squares). Defaults to `edge`. */\n corner?: string;\n /** Optional bevel: lighten the top/left, darken the bottom/right. */\n highlight?: string;\n shadow?: string;\n /** Outline stroke drawn around the whole frame. */\n stroke?: string;\n strokeWidth?: number;\n /** Outer corner radius applied to the four corner squares. */\n radius?: number;\n}\n\n/**\n * Emit the draw commands for a 9-slice panel filling `rect`. Regions are pushed\n * back-to-front (center \u2192 edges \u2192 corners) at painter key `z`, transformed by\n * `transform` (screen space by default). Border is clamped so it never exceeds\n * half the smaller side, keeping the grid valid at any size.\n */\nexport function nineSlice(rect: Rect, style: NineSliceStyle, z = 0, transform: Transform = IDENTITY): DrawCommand[] {\n const b = Math.max(0, Math.min(style.border, rect.w / 2, rect.h / 2));\n const fill = style.fill ?? '#fbf6ea';\n const edge = style.edge ?? fill;\n const corner = style.corner ?? edge;\n const out: DrawCommand[] = [];\n const x0 = rect.x;\n const x1 = rect.x + b;\n const x2 = rect.x + rect.w - b;\n const y0 = rect.y;\n const y1 = rect.y + b;\n const y2 = rect.y + rect.h - b;\n const iw = rect.w - 2 * b; // inner (stretched) width\n const ih = rect.h - 2 * b; // inner (stretched) height\n\n const push = (x: number, y: number, w: number, h: number, f: string, r?: number): void => {\n if (w <= 0 || h <= 0) return;\n out.push({ kind: 'rect', x, y, w, h, r, fill: f, transform, z });\n };\n\n // Center + the four stretchable edges.\n push(x1, y1, iw, ih, fill);\n push(x1, y0, iw, b, style.highlight ?? edge); // top\n push(x1, y2, iw, b, style.shadow ?? edge); // bottom\n push(x0, y1, b, ih, style.highlight ?? edge); // left\n push(x2, y1, b, ih, style.shadow ?? edge); // right\n\n // Four fixed corners (drawn last so their radius reads clean over the edges).\n const r = style.radius;\n push(x0, y0, b, b, corner, r);\n push(x2, y0, b, b, corner, r);\n push(x0, y2, b, b, corner, r);\n push(x2, y2, b, b, corner, r);\n\n // Optional outline around the whole frame.\n if (style.stroke) {\n out.push({\n kind: 'rect',\n x: rect.x,\n y: rect.y,\n w: rect.w,\n h: rect.h,\n r: style.radius,\n fill: 'none',\n stroke: style.stroke,\n strokeWidth: style.strokeWidth ?? 2,\n transform,\n z: z + 0.001,\n });\n }\n return out;\n}\n\n/** Ready-made frame looks. */\nexport const PANEL_PRESETS = {\n parchment: (): NineSliceStyle => ({ border: 10, fill: '#fbf6ea', edge: '#efe4c8', corner: '#e2d3a8', highlight: '#fdfaf0', shadow: '#d9c79c', stroke: '#b8a06a', strokeWidth: 2, radius: 4 }),\n slate: (): NineSliceStyle => ({ border: 8, fill: '#2c3040', edge: '#363c4f', corner: '#454c63', highlight: '#4a5268', shadow: '#20242f', stroke: '#151821', strokeWidth: 2, radius: 3 }),\n} as const;\n", "// Curated palettes \u2014 code-as-art means no arbitrary RGB; pick from a named,\n// on-model set. The default is \"Kent\u014D\" (\u898B\u5F53): the woodblock-registration palette\n// that also dresses hayao.dev. It fuses the site's washi/sumi/ai/shu ink tokens\n// with landscape hues loosely drawn from Lospec's \"Miyazaki 16\", giving a warm,\n// low-key set that reads cleanly in BOTH light and dark games. Every pairing here\n// is WCAG-AA verified (see scripts/palette-audit.ts); the engine stays fully\n// palette-agnostic \u2014 this is a nice starting point, never a restriction.\n\nimport type { Rng } from '../core/rng';\nimport { dpow } from '../core/dmath';\n\n/**\n * The Kent\u014D swatch set \u2014 the single source of truth every named palette derives\n * from. Neutrals form one continuous ground\u2192ink ramp; each of the eight hues has\n * a `Deep` tone (holds AA as a large mark on light washi) and a bright tone (pops\n * on dark sumi/kuro). Traditional Japanese color names keep it on-brand. Pick a\n * hue by name the way the site does, or use a ready-made `Palette` below.\n */\nexport const KENTO = {\n // neutrals: light ground \u2192 dark ink, one continuous ramp\n gofun: '#f7f1e2', // \u80E1\u7C89 shell-white, lightest paper\n washi: '#efe7d3', // \u548C\u7D19 default light ground\n kinu: '#e4d8bd', // \u7D79 warm raised panel / card\n line: '#d8cbac', // \u2500 hairline / grid on light\n kinako: '#b9a882', // \u9EC4\u7C89 tan mid-neutral / muted ink on dark\n stone: '#6c6252', // \u77F3 secondary text on light (AA at body size)\n sumiSoft: '#494133', // \u58A8\u8584 body ink\n sumi: '#23201a', // \u58A8 primary ink / default dark-ish ground\n kuro: '#181820', // \u7384 cool near-black ground for dark games\n yohaku: '#12121a', // \u4F59\u767D deepest dark ground\n darkLine: '#2c2c36', // hairline / grid on dark\n\n // eight hues: `Deep` for light-mode fills, bright for dark-mode / emphasis\n shuDeep: '#b23a24', shu: '#d9583c', // \u6731 vermilion\n kakiDeep: '#bf6a1c', kaki: '#e79a49', // \u67FF persimmon / orange\n koDeep: '#94741d', ko: '#e3c054', // \u9EC4\u571F ochre-gold\n matsuDeep: '#4a7a3a', matsu: '#8bad52', // \u677E\u8449 pine green\n asagiDeep: '#2c7a90', asagi: '#57bad2', // \u6D45\u8471 teal-cyan\n aiDeep: '#2b4257', ai: '#5a86ad', // \u85CD indigo\n fujiDeep: '#63548c', fuji: '#a091cf', // \u85E4 wisteria violet\n sakuDeep: '#b0506e', saku: '#e097ac', // \u685C dusty rose\n} as const;\n\nexport interface Palette {\n name: string;\n bg: string;\n ink: string;\n inkSoft: string;\n line: string;\n accent: string;\n accent2: string;\n good: string;\n warn: string;\n /** A small ordered ramp for categorical fills. */\n ramp: string[];\n /** The full on-brand swatch set, for games that pick hues by name. */\n swatches?: typeof KENTO;\n}\n\n/** Default light woodblock palette \u2014 washi ground, sumi ink, deep accents. */\nexport const MEADOW: Palette = {\n name: 'meadow',\n bg: KENTO.washi,\n ink: KENTO.sumi,\n inkSoft: KENTO.sumiSoft,\n line: KENTO.line,\n accent: KENTO.shuDeep,\n accent2: KENTO.aiDeep,\n good: KENTO.matsuDeep,\n warn: KENTO.kakiDeep,\n // deep tones so categorical fills hold contrast on the light ground\n ramp: [KENTO.shuDeep, KENTO.kakiDeep, KENTO.koDeep, KENTO.matsuDeep, KENTO.asagiDeep, KENTO.aiDeep, KENTO.fujiDeep, KENTO.sakuDeep],\n swatches: KENTO,\n};\n\n/** Dark counterpart \u2014 kuro ground, gofun ink, the same hues in their bright tone. */\nexport const DUSK: Palette = {\n name: 'dusk',\n bg: KENTO.kuro,\n ink: KENTO.gofun,\n inkSoft: KENTO.kinako,\n line: KENTO.darkLine,\n accent: KENTO.shu,\n accent2: KENTO.asagi,\n good: KENTO.matsu,\n warn: KENTO.ko,\n // bright tones so categorical fills pop on the dark ground\n ramp: [KENTO.shu, KENTO.kaki, KENTO.ko, KENTO.matsu, KENTO.asagi, KENTO.ai, KENTO.fuji, KENTO.saku],\n swatches: KENTO,\n};\n\n/** Higher-key paper variant \u2014 brightest ground, same hue family. */\nexport const PAPER: Palette = {\n name: 'paper',\n bg: KENTO.gofun,\n ink: KENTO.sumi,\n inkSoft: KENTO.stone,\n line: KENTO.kinu,\n accent: KENTO.sakuDeep,\n accent2: KENTO.asagiDeep,\n good: KENTO.matsuDeep,\n warn: KENTO.kakiDeep,\n ramp: [KENTO.sakuDeep, KENTO.kakiDeep, KENTO.koDeep, KENTO.matsuDeep, KENTO.asagiDeep, KENTO.aiDeep, KENTO.fujiDeep, KENTO.shuDeep],\n swatches: KENTO,\n};\n\nexport const PALETTES: Record<string, Palette> = { meadow: MEADOW, dusk: DUSK, paper: PAPER };\n\n/** Blend two hex colors (t in [0,1]). Deterministic, no allocations of note. */\nexport function mix(a: string, b: string, t: number): string {\n const pa = hexToRgb(a);\n const pb = hexToRgb(b);\n const r = Math.round(pa[0] + (pb[0] - pa[0]) * t);\n const g = Math.round(pa[1] + (pb[1] - pa[1]) * t);\n const bl = Math.round(pa[2] + (pb[2] - pa[2]) * t);\n return rgbToHex(r, g, bl);\n}\n\nexport function withAlpha(hex: string, alpha: number): string {\n const [r, g, b] = hexToRgb(hex);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nfunction hexToRgb(hex: string): [number, number, number] {\n let h = hex.replace('#', '');\n if (h.length === 3) h = h.split('').map((c) => c + c).join('');\n const n = parseInt(h, 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\nfunction rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, '0')).join('');\n}\n\n// \u2500\u2500 HSL / HSV constructors + drift \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Procedural theming and palette drift (space-huggers `setHSLA`+`mutate`,\n// dr1v3n-wild/dodo `.hsl`). Pure arithmetic \u2014 no trig \u2014 so it's netplay-safe.\n// Colors are cosmetic; when drift reads `world.rng` it advances deterministically.\n\nexport interface HSL {\n /** Hue in degrees [0,360). */\n h: number;\n /** Saturation [0,1]. */\n s: number;\n /** Lightness [0,1]. */\n l: number;\n}\n\nconst mod360 = (h: number): number => ((h % 360) + 360) % 360;\nconst clamp01 = (v: number): number => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/** HSL \u2192 hex. h in degrees (wraps), s/l in [0,1]. */\nexport function hsl(h: number, s: number, l: number): string {\n h = mod360(h) / 360;\n s = clamp01(s);\n l = clamp01(l);\n if (s === 0) {\n const v = l * 255;\n return rgbToHex(v, v, v);\n }\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number): number => {\n t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n };\n return rgbToHex(hue(h + 1 / 3) * 255, hue(h) * 255, hue(h - 1 / 3) * 255);\n}\n\n/** HSV/HSB \u2192 hex. h in degrees (wraps), s/v in [0,1]. */\nexport function hsv(h: number, s: number, v: number): string {\n h = mod360(h) / 60;\n s = clamp01(s);\n v = clamp01(v);\n const c = v * s;\n const x = c * (1 - Math.abs((h % 2) - 1));\n const m = v - c;\n let r = 0;\n let g = 0;\n let b = 0;\n if (h < 1) [r, g, b] = [c, x, 0];\n else if (h < 2) [r, g, b] = [x, c, 0];\n else if (h < 3) [r, g, b] = [0, c, x];\n else if (h < 4) [r, g, b] = [0, x, c];\n else if (h < 5) [r, g, b] = [x, 0, c];\n else [r, g, b] = [c, 0, x];\n return rgbToHex((r + m) * 255, (g + m) * 255, (b + m) * 255);\n}\n\n/** Decompose a hex color into HSL. Inverse of `hsl()`. */\nexport function hexToHsl(hex: string): HSL {\n const [r255, g255, b255] = hexToRgb(hex);\n const r = r255 / 255;\n const g = g255 / 255;\n const b = b255 / 255;\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n const d = max - min;\n if (d === 0) return { h: 0, s: 0, l };\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === r) h = (g - b) / d + (g < b ? 6 : 0);\n else if (max === g) h = (b - r) / d + 2;\n else h = (r - g) / d + 4;\n return { h: h * 60, s, l };\n}\n\nexport interface DriftAmounts {\n /** Max hue drift \u00B1 degrees. */\n hue?: number;\n /** Max saturation drift \u00B1 (absolute, [0,1]). */\n sat?: number;\n /** Max lightness drift \u00B1 (absolute, [0,1]). */\n light?: number;\n}\n\n/**\n * Drift a color in HSL space by random amounts from `world.rng` (space-huggers'\n * `mutate`). Deterministic given rng state; hue wraps, s/l clamp. Cosmetic, but\n * because it consumes rng draws, call it in a stable order.\n */\nexport function mutateColor(rng: Rng, hex: string, amounts: DriftAmounts = {}): string {\n const c = hexToHsl(hex);\n const dh = amounts.hue ?? 0;\n const ds = amounts.sat ?? 0;\n const dl = amounts.light ?? 0;\n return hsl(\n c.h + rng.range(-dh, dh),\n c.s + rng.range(-ds, ds),\n c.l + rng.range(-dl, dl),\n );\n}\n\n// \u2500\u2500 gamma-correct (linear-space) interpolation + gradients \u2500\u2500\u2500\u2500\u2500\u2500\n// super-castle blends in linear light, not sRGB \u2014 perceptually correct, no muddy\n// mid-tones. sRGB\u2194linear uses the exact IEC transfer curve; the 2.4 exponent\n// routes through dmath's dpow so it's bit-identical across engines and never\n// trips the \"no Math.pow\" invariant.\n\nconst srgbToLinear = (c: number): number => (c <= 0.04045 ? c / 12.92 : dpow((c + 0.055) / 1.055, 2.4));\nconst linearToSrgb = (c: number): number => (c <= 0.0031308 ? c * 12.92 : 1.055 * dpow(c, 1 / 2.4) - 0.055);\n\n/** Blend two hex colors in linear light (gamma-correct). t in [0,1]. */\nexport function mixLinear(a: string, b: string, t: number): string {\n const pa = hexToRgb(a);\n const pb = hexToRgb(b);\n const chan = (i: number): number => {\n const la = srgbToLinear(pa[i] / 255);\n const lb = srgbToLinear(pb[i] / 255);\n return linearToSrgb(la + (lb - la) * t) * 255;\n };\n return rgbToHex(chan(0), chan(1), chan(2));\n}\n\n/**\n * Sample a multi-stop gradient at t in [0,1], blending in linear light. Stops\n * are evenly spaced hex colors (\u2265 1). Great for procedural sky/heat/health ramps.\n */\nexport function sampleGradient(stops: readonly string[], t: number): string {\n if (stops.length === 0) return '#000000';\n if (stops.length === 1) return stops[0];\n const clamped = clamp01(t);\n const scaled = clamped * (stops.length - 1);\n const i = Math.min(stops.length - 2, Math.floor(scaled));\n return mixLinear(stops[i], stops[i + 1], scaled - i);\n}\n\n/** Materialize an n-color ramp from gradient stops (linear-light interpolation). */\nexport function gradient(stops: readonly string[], n: number): string[] {\n if (n <= 0) return [];\n if (n === 1) return [sampleGradient(stops, 0)];\n return Array.from({ length: n }, (_, i) => sampleGradient(stops, i / (n - 1)));\n}\n", "// Procedural vector shape builders \u2014 the \"code-as-art\" toolkit. All pure and\n// deterministic (any randomness must be passed an Rng), producing point arrays\n// or SVG path strings usable directly in a Sprite.\n\nimport { dcos, dsin } from '../core/dmath';\nimport type { Rng } from '../core/rng';\nimport { TAU, type Vec2 } from '../core/math';\n\n/** Regular polygon points (flat [x,y,\u2026]) centered at origin. */\nexport function regularPolygon(sides: number, radius: number, rotation = 0): number[] {\n const pts: number[] = [];\n for (let i = 0; i < sides; i++) {\n const a = rotation + (i / sides) * TAU;\n pts.push(dcos(a) * radius, dsin(a) * radius);\n }\n return pts;\n}\n\n/** Star with alternating outer/inner radii. */\nexport function star(points: number, outer: number, inner: number, rotation = -Math.PI / 2): number[] {\n const pts: number[] = [];\n for (let i = 0; i < points * 2; i++) {\n const r = i % 2 === 0 ? outer : inner;\n const a = rotation + (i / (points * 2)) * TAU;\n pts.push(dcos(a) * r, dsin(a) * r);\n }\n return pts;\n}\n\n/** An organic blob outline as an SVG path (deterministic given the Rng). */\nexport function blobPath(rng: Rng, radius: number, wobble = 0.25, lobes = 7): string {\n const pts: Vec2[] = [];\n for (let i = 0; i < lobes; i++) {\n const a = (i / lobes) * TAU;\n const r = radius * (1 - wobble + rng.float() * wobble * 2);\n pts.push({ x: dcos(a) * r, y: dsin(a) * r });\n }\n return smoothClosedPath(pts);\n}\n\n/** Convert a point list into a smooth closed path (Catmull-Rom \u2192 cubic B\u00E9zier). */\nexport function smoothClosedPath(points: Vec2[], tension = 1): string {\n const nPts = points.length;\n if (nPts < 3) return '';\n const p = (i: number) => points[((i % nPts) + nPts) % nPts];\n const r = (v: number) => Math.round(v * 100) / 100;\n let d = `M ${r(p(0).x)} ${r(p(0).y)}`;\n for (let i = 0; i < nPts; i++) {\n const p0 = p(i - 1);\n const p1 = p(i);\n const p2 = p(i + 1);\n const p3 = p(i + 2);\n const c1x = p1.x + ((p2.x - p0.x) / 6) * tension;\n const c1y = p1.y + ((p2.y - p0.y) / 6) * tension;\n const c2x = p2.x - ((p3.x - p1.x) / 6) * tension;\n const c2y = p2.y - ((p3.y - p1.y) / 6) * tension;\n d += ` C ${r(c1x)} ${r(c1y)}, ${r(c2x)} ${r(c2y)}, ${r(p2.x)} ${r(p2.y)}`;\n }\n return d + ' Z';\n}\n\n/** Smooth open path through points (for trails, curves). */\nexport function smoothOpenPath(points: Vec2[], tension = 1): string {\n const nPts = points.length;\n if (nPts < 2) return '';\n const r = (v: number) => Math.round(v * 100) / 100;\n let d = `M ${r(points[0].x)} ${r(points[0].y)}`;\n for (let i = 0; i < nPts - 1; i++) {\n const p0 = points[Math.max(0, i - 1)];\n const p1 = points[i];\n const p2 = points[i + 1];\n const p3 = points[Math.min(nPts - 1, i + 2)];\n const c1x = p1.x + ((p2.x - p0.x) / 6) * tension;\n const c1y = p1.y + ((p2.y - p0.y) / 6) * tension;\n const c2x = p2.x - ((p3.x - p1.x) / 6) * tension;\n const c2y = p2.y - ((p3.y - p1.y) / 6) * tension;\n d += ` C ${r(c1x)} ${r(c1y)}, ${r(c2x)} ${r(c2y)}, ${r(p2.x)} ${r(p2.y)}`;\n }\n return d;\n}\n", "// Procedural sprite / texture generation \u2014 build whole tilesets and sprites\n// from code with ~0 asset bytes (the defining js13k art trick). A `PixelBuffer`\n// is a tiny indexed bitmap; decoders reconstruct one from a compact encoding\n// (packed 2-bit, RLE run pairs, or a 1-bit BigInt/hex bitmap), and the emitter\n// projects it to run-merged `rect` draw commands the renderer already speaks.\n//\n// COSMETIC / DETERMINISM: the pixels here are pure *view* derived from constant\n// data (or from `world.rng`, never `Math.random`). The output rects carry no\n// canonical state, so `TextureSprite` sets `cosmetic = true` \u2014 it never enters\n// `world.hash()`/snapshot. Decoding is a pure function of its inputs.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { DrawCommand, RectCommand } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\n\n/** A palette entry; `null` (or a missing index) renders transparent. */\nexport type Swatch = string | null;\n\n/** A small indexed bitmap: `data[y * width + x]` is a palette index. */\nexport class PixelBuffer {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n\n constructor(width: number, height: number, data?: Uint8Array) {\n this.width = width;\n this.height = height;\n this.data = data ?? new Uint8Array(width * height);\n }\n\n get(x: number, y: number): number {\n if (x < 0 || y < 0 || x >= this.width || y >= this.height) return 0;\n return this.data[y * this.width + x];\n }\n set(x: number, y: number, index: number): void {\n if (x < 0 || y < 0 || x >= this.width || y >= this.height) return;\n this.data[y * this.width + x] = index;\n }\n\n /** Build from a rows-of-strings grid, mapping each character to an index. */\n static fromRows(rows: readonly string[], charToIndex: Record<string, number>): PixelBuffer {\n const height = rows.length;\n const width = rows.reduce((w, r) => Math.max(w, r.length), 0);\n const buf = new PixelBuffer(width, height);\n for (let y = 0; y < height; y++) {\n const row = rows[y];\n for (let x = 0; x < row.length; x++) buf.data[y * width + x] = charToIndex[row[x]] ?? 0;\n }\n return buf;\n }\n\n /** A copy with every index passed through `lut` (2-bit \u2192 palette remap). */\n remap(lut: readonly number[]): PixelBuffer {\n const out = new Uint8Array(this.data.length);\n for (let i = 0; i < this.data.length; i++) out[i] = lut[this.data[i]] ?? 0;\n return new PixelBuffer(this.width, this.height, out);\n }\n}\n\n/** Normalize a packed bitmap source (hex string, `0b\u2026`/`0x\u2026`, or bigint) to a BigInt. */\nfunction toBig(source: bigint | string): bigint {\n if (typeof source === 'bigint') return source;\n const s = source.trim();\n if (s.startsWith('0x') || s.startsWith('0b') || s.startsWith('0o')) return BigInt(s);\n return BigInt('0x' + s);\n}\n\n/**\n * Decode a 1-bit-per-pixel bitmap packed MSB-first into a BigInt/hex string\n * (the super-castle-style trick). Pixel `i` reads bit `(w*h-1-i)`, so a hex\n * literal reads left-to-right, top-to-bottom. Produces indices 0 or 1.\n */\nexport function decodeBits(source: bigint | string, width: number, height: number): PixelBuffer {\n const bits = toBig(source);\n const total = width * height;\n const buf = new PixelBuffer(width, height);\n for (let i = 0; i < total; i++) {\n buf.data[i] = Number((bits >> BigInt(total - 1 - i)) & 1n);\n }\n return buf;\n}\n\n/**\n * Decode a 2-bit-per-pixel bitmap (indices 0\u20133) packed MSB-first, matching the\n * dying-dreams \"2-bit source \u2192 palette LUT\" pipeline. Pass the result through\n * `PixelBuffer.remap(lut)` to lift the 2-bit indices into a wider palette.\n */\nexport function decode2bit(source: bigint | string, width: number, height: number): PixelBuffer {\n const bits = toBig(source);\n const total = width * height;\n const buf = new PixelBuffer(width, height);\n for (let i = 0; i < total; i++) {\n const shift = BigInt((total - 1 - i) * 2);\n buf.data[i] = Number((bits >> shift) & 3n);\n }\n return buf;\n}\n\n/**\n * Decode a run-length-encoded index stream (witchcat-style). `runs` is a flat\n * list of `[count, index, count, index, \u2026]` filled row-major. A short encoding\n * for sprites dominated by flat colour.\n */\nexport function decodeRLE(runs: readonly number[], width: number, height: number): PixelBuffer {\n const buf = new PixelBuffer(width, height);\n let p = 0;\n for (let i = 0; i + 1 < runs.length; i += 2) {\n const count = runs[i];\n const index = runs[i + 1];\n for (let k = 0; k < count && p < buf.data.length; k++) buf.data[p++] = index;\n }\n return buf;\n}\n\n/** Encode a PixelBuffer back to RLE run pairs \u2014 the inverse of `decodeRLE`. */\nexport function encodeRLE(buf: PixelBuffer): number[] {\n const runs: number[] = [];\n const d = buf.data;\n for (let i = 0; i < d.length; ) {\n const v = d[i];\n let count = 1;\n while (i + count < d.length && d[i + count] === v) count++;\n runs.push(count, v);\n i += count;\n }\n return runs;\n}\n\nexport interface PixelDrawOptions {\n /** Size of one pixel cell in design units. Default 1. */\n cell?: number;\n /** Top-left origin in local space. Default 0,0. */\n x?: number;\n y?: number;\n /** Painter z. Default 0. */\n z?: number;\n /** World transform for the emitted commands. Default identity. */\n transform?: Transform;\n}\n\n/**\n * Project a PixelBuffer to `rect` draw commands, run-merging horizontal spans\n * of the same colour so a 16\u00D716 sprite is a handful of rects, not 256. Palette\n * entries that are `null`/undefined render transparent (skipped). Pure \u2014 the\n * commands carry no state and belong under a `cosmetic` node.\n */\nexport function pixelsToCommands(\n buf: PixelBuffer,\n palette: readonly Swatch[],\n options: PixelDrawOptions = {},\n): RectCommand[] {\n const cell = options.cell ?? 1;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const out: RectCommand[] = [];\n for (let y = 0; y < buf.height; y++) {\n let x = 0;\n while (x < buf.width) {\n const idx = buf.get(x, y);\n const fill = palette[idx];\n if (fill == null) {\n x++;\n continue;\n }\n let run = 1;\n while (x + run < buf.width && buf.get(x + run, y) === idx) run++;\n out.push({\n kind: 'rect',\n x: ox + x * cell,\n y: oy + y * cell,\n w: run * cell,\n h: cell,\n transform,\n z,\n fill,\n });\n x += run;\n }\n }\n return out;\n}\n\nexport interface TextureSpriteConfig extends NodeConfig {\n buffer: PixelBuffer;\n palette: readonly Swatch[];\n /** Pixel cell size in design units. Default 1. */\n cell?: number;\n /** Draw centered on the node origin instead of top-left. Default true. */\n center?: boolean;\n}\n\n/**\n * A scene node that renders a decoded PixelBuffer. It is pure view over\n * constant art data, so it is `cosmetic = true` by default \u2014 excluded from\n * `serialize()`/`hash()`/snapshot. Position/scale it like any other node.\n */\nexport class TextureSprite extends Node {\n override readonly type = 'TextureSprite';\n buffer: PixelBuffer;\n palette: readonly Swatch[];\n cell: number;\n center: boolean;\n\n constructor(config: TextureSpriteConfig) {\n super(config);\n this.buffer = config.buffer;\n this.palette = config.palette;\n this.cell = config.cell ?? 1;\n this.center = config.center ?? true;\n this.cosmetic = true;\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const cell = this.cell;\n const x = this.center ? -(this.buffer.width * cell) / 2 : 0;\n const y = this.center ? -(this.buffer.height * cell) / 2 : 0;\n for (const cmd of pixelsToCommands(this.buffer, this.palette, { cell, x, y, z: this.z, transform: world })) {\n out.push(cmd);\n }\n }\n}\n", "// A built-in 5-pixel-tall proportional bitmap font (\"code-as-art\" \u2014 no font\n// asset). Each glyph is rows of `#` (lit) / `.` (off), top to bottom; the glyph\n// width is its row length, so letters are proportional (I is 1 wide, M is 5).\n// Uppercase-only: layout folds lowercase to uppercase. Pure constant data.\n\n/** A font: named glyph bitmaps plus vertical/spacing metrics. */\nexport interface BitmapFont {\n readonly height: number;\n /** Blank columns between glyphs. */\n readonly tracking: number;\n /** Width of a space character (advance only, no pixels). */\n readonly spaceWidth: number;\n readonly glyphs: Readonly<Record<string, readonly string[]>>;\n}\n\nconst G: Record<string, string[]> = {\n A: ['.#.', '#.#', '###', '#.#', '#.#'],\n B: ['##.', '#.#', '##.', '#.#', '##.'],\n C: ['.##', '#..', '#..', '#..', '.##'],\n D: ['##.', '#.#', '#.#', '#.#', '##.'],\n E: ['###', '#..', '##.', '#..', '###'],\n F: ['###', '#..', '##.', '#..', '#..'],\n G: ['.##', '#..', '#.#', '#.#', '.##'],\n H: ['#.#', '#.#', '###', '#.#', '#.#'],\n I: ['#', '#', '#', '#', '#'],\n J: ['..#', '..#', '..#', '#.#', '.#.'],\n K: ['#.#', '##.', '#..', '##.', '#.#'],\n L: ['#..', '#..', '#..', '#..', '###'],\n M: ['#...#', '##.##', '#.#.#', '#...#', '#...#'],\n N: ['#...#', '##..#', '#.#.#', '#..##', '#...#'],\n O: ['.#.', '#.#', '#.#', '#.#', '.#.'],\n P: ['##.', '#.#', '##.', '#..', '#..'],\n Q: ['.#.', '#.#', '#.#', '#.#', '.##'],\n R: ['##.', '#.#', '##.', '#.#', '#.#'],\n S: ['.##', '#..', '.#.', '..#', '##.'],\n T: ['###', '.#.', '.#.', '.#.', '.#.'],\n U: ['#.#', '#.#', '#.#', '#.#', '###'],\n V: ['#.#', '#.#', '#.#', '#.#', '.#.'],\n W: ['#...#', '#...#', '#.#.#', '##.##', '#...#'],\n X: ['#.#', '#.#', '.#.', '#.#', '#.#'],\n Y: ['#.#', '#.#', '.#.', '.#.', '.#.'],\n Z: ['###', '..#', '.#.', '#..', '###'],\n '0': ['.#.', '#.#', '#.#', '#.#', '.#.'],\n '1': ['.#.', '##.', '.#.', '.#.', '###'],\n '2': ['##.', '..#', '.#.', '#..', '###'],\n '3': ['##.', '..#', '.#.', '..#', '##.'],\n '4': ['#.#', '#.#', '###', '..#', '..#'],\n '5': ['###', '#..', '##.', '..#', '##.'],\n '6': ['.##', '#..', '##.', '#.#', '.#.'],\n '7': ['###', '..#', '.#.', '.#.', '.#.'],\n '8': ['.#.', '#.#', '.#.', '#.#', '.#.'],\n '9': ['.#.', '#.#', '.##', '..#', '##.'],\n '.': ['.', '.', '.', '.', '#'],\n ',': ['..', '..', '..', '.#', '#.'],\n '!': ['#', '#', '#', '.', '#'],\n '?': ['##.', '..#', '.#.', '...', '.#.'],\n ':': ['.', '#', '.', '#', '.'],\n ';': ['..', '.#', '..', '.#', '#.'],\n '-': ['...', '...', '###', '...', '...'],\n '+': ['...', '.#.', '###', '.#.', '...'],\n '=': ['...', '###', '...', '###', '...'],\n '/': ['..#', '..#', '.#.', '#..', '#..'],\n \"'\": ['#', '#', '.', '.', '.'],\n '\"': ['#.#', '#.#', '...', '...', '...'],\n '(': ['.#', '#.', '#.', '#.', '.#'],\n ')': ['#.', '.#', '.#', '.#', '#.'],\n '<': ['..#', '.#.', '#..', '.#.', '..#'],\n '>': ['#..', '.#.', '..#', '.#.', '#..'],\n '%': ['#.#', '..#', '.#.', '#..', '#.#'],\n '*': ['...', '#.#', '.#.', '#.#', '...'],\n '#': ['#.#', '###', '#.#', '###', '#.#'],\n};\n\n/** The default built-in font: 5px tall, proportional, uppercase + digits + punctuation. */\nexport const FONT_5: BitmapFont = {\n height: 5,\n tracking: 1,\n spaceWidth: 3,\n glyphs: G,\n};\n", "// Bitmap/pixel text: glyph atlas \u2192 proportional layout \u2192 run-merged draw\n// commands. Covers what the js13k HUD/dialogue games hand-build: per-char\n// widths, word wrap, typewriter reveal (clock-driven, never wall-clock), and\n// inline colour markup via a `{tag}\u2026{/}` stack (clawstrike/coup-ahoo style).\n//\n// COSMETIC / DETERMINISM: text is pure view. Layout is a pure function of\n// (font, string, width). Typewriter reveal is a pure function of sim time from\n// `world.time`/`clock` \u2014 no `performance.now`. `BitmapText` is `cosmetic`.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { DrawCommand, RectCommand, TextAlign } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\nimport { FONT_5, type BitmapFont } from './font5';\n\n/** One source character with an optional colour and its index in the source string. */\nexport interface RichChar {\n ch: string;\n color?: string;\n i: number;\n}\n\n/**\n * Parse inline colour markup into per-character colours. `{name}` pushes a\n * colour, `{/}` pops it (a stack, so nesting works); `{{` is a literal `{`.\n * A tag resolves through `colorMap`, or is used literally if it starts with `#`\n * or is not in the map. Text outside any tag has no colour (caller default).\n */\nexport function parseRich(markup: string, colorMap: Record<string, string> = {}): RichChar[] {\n const out: RichChar[] = [];\n const stack: string[] = [];\n let i = 0;\n let srcIndex = 0;\n while (i < markup.length) {\n const c = markup[i];\n if (c === '{' && markup[i + 1] === '{') {\n out.push({ ch: '{', color: stack[stack.length - 1], i: srcIndex++ });\n i += 2;\n continue;\n }\n if (c === '{') {\n const end = markup.indexOf('}', i);\n if (end === -1) {\n out.push({ ch: c, color: stack[stack.length - 1], i: srcIndex++ });\n i++;\n continue;\n }\n const tag = markup.slice(i + 1, end);\n if (tag === '/') stack.pop();\n else stack.push(tag[0] === '#' ? tag : (colorMap[tag] ?? tag));\n i = end + 1;\n continue;\n }\n out.push({ ch: c, color: stack[stack.length - 1], i: srcIndex++ });\n i++;\n }\n return out;\n}\n\n/** Fold a character to one the font can draw (uppercase; unknown \u2192 space or `?`). */\nfunction resolveChar(font: BitmapFont, ch: string): string {\n if (ch === ' ' || ch === '\\n') return ch;\n const up = ch.toUpperCase();\n if (font.glyphs[up]) return up;\n if (font.glyphs[ch]) return ch;\n return font.glyphs['?'] ? '?' : ' ';\n}\n\n/** Width of a single glyph (advance excludes tracking). */\nfunction glyphWidth(font: BitmapFont, ch: string): number {\n if (ch === ' ') return font.spaceWidth;\n const rows = font.glyphs[ch];\n return rows ? rows[0].length : font.spaceWidth;\n}\n\n/** Width in font-pixels of a run of already-resolved chars on one line. */\nexport function measureLine(font: BitmapFont, chars: readonly RichChar[]): number {\n let w = 0;\n for (let k = 0; k < chars.length; k++) {\n w += glyphWidth(font, chars[k].ch);\n if (k < chars.length - 1) w += font.tracking;\n }\n return w;\n}\n\n/** Width in font-pixels of a plain string (no wrapping). */\nexport function measureText(font: BitmapFont, text: string): number {\n return measureLine(font, [...text].map((ch, i) => ({ ch: resolveChar(font, ch), i })));\n}\n\nexport interface PlacedGlyph {\n ch: string;\n color?: string;\n /** Source-string index (for typewriter reveal). */\n i: number;\n /** Top-left in font-pixel units. */\n x: number;\n y: number;\n w: number;\n}\n\nexport interface TextLayout {\n glyphs: PlacedGlyph[];\n /** Bounding size in font-pixel units. */\n width: number;\n height: number;\n lines: number;\n}\n\nexport interface TextLayoutOptions {\n /** Wrap width in font-pixels. Omit for no wrapping. */\n maxWidth?: number;\n /** Extra blank rows between lines. Default 1. */\n lineSpacing?: number;\n /** Horizontal alignment within `maxWidth` (or the widest line). Default 'left'. */\n align?: TextAlign;\n}\n\n/**\n * Lay out text into placed glyphs (font-pixel coords), word-wrapping on spaces\n * and breaking on `\\n`. Accepts a plain string or a `RichChar[]` from\n * `parseRich`. Pure and deterministic.\n */\nexport function layoutText(\n font: BitmapFont,\n input: string | readonly RichChar[],\n options: TextLayoutOptions = {},\n): TextLayout {\n const lineSpacing = options.lineSpacing ?? 1;\n const source: RichChar[] =\n typeof input === 'string' ? [...input].map((ch, i) => ({ ch, i })) : input.map((r) => ({ ...r }));\n\n // Split into hard lines on '\\n', then greedily wrap each on spaces.\n const hardLines: RichChar[][] = [[]];\n for (const rc of source) {\n if (rc.ch === '\\n') hardLines.push([]);\n else hardLines[hardLines.length - 1].push({ ...rc, ch: resolveChar(font, rc.ch) });\n }\n\n const rows: RichChar[][] = [];\n for (const line of hardLines) {\n if (options.maxWidth === undefined) {\n rows.push(line);\n continue;\n }\n let current: RichChar[] = [];\n let word: RichChar[] = [];\n const flushWord = () => {\n if (word.length === 0) return;\n const sep = current.length ? font.spaceWidth + font.tracking : 0;\n if (current.length && measureLine(font, current) + sep + measureLine(font, word) > options.maxWidth!) {\n rows.push(current);\n current = [];\n }\n if (current.length) current.push({ ch: ' ', i: -1 });\n current.push(...word);\n word = [];\n };\n for (const rc of line) {\n if (rc.ch === ' ') flushWord();\n else word.push(rc);\n }\n flushWord();\n rows.push(current);\n }\n\n const glyphs: PlacedGlyph[] = [];\n let maxW = 0;\n for (const row of rows) maxW = Math.max(maxW, measureLine(font, row));\n const boundW = options.maxWidth ?? maxW;\n\n let y = 0;\n for (const row of rows) {\n const rowW = measureLine(font, row);\n let x = options.align === 'center' ? Math.floor((boundW - rowW) / 2) : options.align === 'right' ? boundW - rowW : 0;\n for (const rc of row) {\n const w = glyphWidth(font, rc.ch);\n if (rc.ch !== ' ') glyphs.push({ ch: rc.ch, color: rc.color, i: rc.i, x, y, w });\n x += w + font.tracking;\n }\n y += font.height + lineSpacing;\n }\n\n return { glyphs, width: boundW, height: rows.length * (font.height + lineSpacing) - lineSpacing, lines: rows.length };\n}\n\n/** Typewriter: how many source characters are revealed after `elapsed` seconds. */\nexport function typewriterCount(total: number, elapsedSec: number, charsPerSec: number): number {\n if (charsPerSec <= 0) return total;\n const n = Math.floor(elapsedSec * charsPerSec);\n return n < 0 ? 0 : n > total ? total : n;\n}\n\nexport interface TextDrawOptions {\n /** Font-pixel cell size in design units. Default 2. */\n cell?: number;\n /** Top-left origin in local space. Default 0,0. */\n x?: number;\n y?: number;\n z?: number;\n /** Default fill for glyphs without an inline colour. Default '#000'. */\n color?: string;\n transform?: Transform;\n /** Draw only glyphs whose source index is `< reveal` (typewriter). */\n reveal?: number;\n}\n\n/**\n * Project a laid-out text to run-merged `rect` commands \u2014 one rect per\n * horizontal span of lit pixels. Pure; the commands belong under a `cosmetic`\n * node.\n */\nexport function textToCommands(\n font: BitmapFont,\n layout: TextLayout,\n options: TextDrawOptions = {},\n): RectCommand[] {\n const cell = options.cell ?? 2;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const defColor = options.color ?? '#000';\n const reveal = options.reveal;\n const out: RectCommand[] = [];\n for (const g of layout.glyphs) {\n if (reveal !== undefined && g.i >= reveal) continue;\n const rows = font.glyphs[g.ch];\n if (!rows) continue;\n const fill = g.color ?? defColor;\n for (let ry = 0; ry < rows.length; ry++) {\n const row = rows[ry];\n let cx = 0;\n while (cx < row.length) {\n if (row[cx] !== '#') {\n cx++;\n continue;\n }\n let run = 1;\n while (cx + run < row.length && row[cx + run] === '#') run++;\n out.push({\n kind: 'rect',\n x: ox + (g.x + cx) * cell,\n y: oy + (g.y + ry) * cell,\n w: run * cell,\n h: cell,\n transform,\n z,\n fill,\n });\n cx += run;\n }\n }\n }\n return out;\n}\n\nexport interface BitmapTextConfig extends NodeConfig {\n text: string;\n font?: BitmapFont;\n cell?: number;\n color?: string;\n /** Resolve `{tag}` markup names to colours. */\n colorMap?: Record<string, string>;\n /** Wrap width in font-pixels. */\n maxWidth?: number;\n lineSpacing?: number;\n align?: TextAlign;\n /** Typewriter speed in chars/sec (clock-driven). Omit to show all at once. */\n charsPerSec?: number;\n /** Center the block on the node origin instead of top-left. Default false. */\n center?: boolean;\n}\n\n/**\n * A scene node that renders bitmap text with optional inline colour and a\n * clock-driven typewriter reveal. Pure view \u2192 `cosmetic = true` (never hashed).\n */\nexport class BitmapText extends Node {\n override readonly type = 'BitmapText';\n text: string;\n font: BitmapFont;\n cell: number;\n color: string;\n colorMap: Record<string, string>;\n maxWidth?: number;\n lineSpacing: number;\n align: TextAlign;\n charsPerSec?: number;\n center: boolean;\n private startTime = 0;\n\n constructor(config: BitmapTextConfig) {\n super(config);\n this.text = config.text;\n this.font = config.font ?? FONT_5;\n this.cell = config.cell ?? 2;\n this.color = config.color ?? '#000';\n this.colorMap = config.colorMap ?? {};\n this.maxWidth = config.maxWidth;\n this.lineSpacing = config.lineSpacing ?? 1;\n this.align = config.align ?? 'left';\n this.charsPerSec = config.charsPerSec;\n this.center = config.center ?? false;\n this.cosmetic = true;\n }\n\n protected override onReady(): void {\n this.startTime = this.world?.time ?? 0;\n }\n\n /** Restart the typewriter from the current sim time. */\n restartReveal(): void {\n this.startTime = this.world?.time ?? 0;\n }\n\n private buildLayout(): TextLayout {\n const chars = parseRich(this.text, this.colorMap);\n return layoutText(this.font, chars, { maxWidth: this.maxWidth, lineSpacing: this.lineSpacing, align: this.align });\n }\n\n protected override draw(out: DrawCommand[], world: Transform): void {\n const layout = this.buildLayout();\n let reveal: number | undefined;\n if (this.charsPerSec !== undefined) {\n const elapsed = (this.world?.time ?? 0) - this.startTime;\n reveal = typewriterCount(this.text.length, elapsed, this.charsPerSec);\n }\n const x = this.center ? -(layout.width * this.cell) / 2 : 0;\n const y = this.center ? -(layout.height * this.cell) / 2 : 0;\n for (const cmd of textToCommands(this.font, layout, {\n cell: this.cell,\n x,\n y,\n z: this.z,\n color: this.color,\n transform: world,\n reveal,\n })) {\n out.push(cmd);\n }\n }\n}\n", "// Autotiling: turn a boolean/logical grid into seamless tile art. Two solvers,\n// both fully pure and deterministic (no RNG):\n// \u2022 4-/8-neighbour bitmask \u2192 a base `frame` + `rotation` (Wang tiles), the\n// dying-dreams/witchcat wall-and-edge trick.\n// \u2022 marching squares over the grid corners \u2192 a 0\u201315 case per dual cell, plus\n// iso-contour segments for smooth outlines.\n//\n// The classification is pure logic and MAY inform gameplay, but the *emitted*\n// draw commands are art \u2192 the caller places them under a `cosmetic` node so\n// they stay out of `world.hash()`. BoolGrid is row-major: `grid[y][x]`.\n\nimport { IDENTITY, type Transform } from '../core/math';\nimport type { PolyCommand, RectCommand } from '../render/commands';\n\nexport type BoolGrid = readonly (readonly boolean[])[];\n\n/** Build a grid from rows of text; a cell is solid when its char is in `solid`. */\nexport function gridFromRows(rows: readonly string[], solid = '#'): boolean[][] {\n return rows.map((r) => [...r].map((c) => solid.includes(c)));\n}\n\nfunction at(grid: BoolGrid, x: number, y: number): boolean {\n return y >= 0 && y < grid.length && x >= 0 && x < grid[y].length && grid[y][x];\n}\n\n// \u2500\u2500 4-neighbour Wang bitmask \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Bit order N=1, E=2, S=4, W=8 (set when that side connects to another solid).\n\nexport const Edge = { N: 1, E: 2, S: 4, W: 8 } as const;\nexport type Edge = (typeof Edge)[keyof typeof Edge];\n\n/** 4-bit edge mask of solid neighbours around a cell. */\nexport function mask4(grid: BoolGrid, x: number, y: number): number {\n return (\n (at(grid, x, y - 1) ? Edge.N : 0) |\n (at(grid, x + 1, y) ? Edge.E : 0) |\n (at(grid, x, y + 1) ? Edge.S : 0) |\n (at(grid, x - 1, y) ? Edge.W : 0)\n );\n}\n\n/** 8-bit neighbour mask, bit order N,NE,E,SE,S,SW,W,NW (1,2,4,\u2026,128). */\nexport function mask8(grid: BoolGrid, x: number, y: number): number {\n let m = 0;\n const dirs: ReadonlyArray<readonly [number, number]> = [\n [0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1],\n ];\n for (let i = 0; i < 8; i++) if (at(grid, x + dirs[i][0], y + dirs[i][1])) m |= 1 << i;\n return m;\n}\n\n/** Base tile shapes an edge mask resolves to (rotate `frame` by `rotation`\u00D790\u00B0 CW). */\nexport const WangFrame = { Isolated: 0, Cap: 1, Straight: 2, Bend: 3, Tee: 4, Cross: 5 } as const;\nexport type WangFrame = (typeof WangFrame)[keyof typeof WangFrame];\n\nexport interface WangTile {\n mask: number;\n frame: WangFrame;\n /** Quarter turns clockwise applied to the base frame (0\u20133). */\n rotation: number;\n}\n\nfunction rotateCW(m: number): number {\n let r = 0;\n if (m & Edge.N) r |= Edge.E;\n if (m & Edge.E) r |= Edge.S;\n if (m & Edge.S) r |= Edge.W;\n if (m & Edge.W) r |= Edge.N;\n return r;\n}\n\n// Precomputed 16-entry mask \u2192 {frame, rotation} table. Built by rotating one\n// canonical mask per frame through four quarter turns (pure, module-load once).\nconst WANG4: WangTile[] = (() => {\n const bases: ReadonlyArray<readonly [WangFrame, number]> = [\n [WangFrame.Isolated, 0b0000],\n [WangFrame.Cap, Edge.N],\n [WangFrame.Straight, Edge.N | Edge.S],\n [WangFrame.Bend, Edge.N | Edge.E],\n [WangFrame.Tee, Edge.N | Edge.E | Edge.S],\n [WangFrame.Cross, 0b1111],\n ];\n const table: WangTile[] = new Array(16);\n for (const [frame, mask0] of bases) {\n let m = mask0;\n for (let rotation = 0; rotation < 4; rotation++) {\n if (table[m] === undefined) table[m] = { mask: m, frame, rotation };\n m = rotateCW(m);\n }\n }\n return table;\n})();\n\n/** Resolve an edge mask (0\u201315) to its base frame + rotation. */\nexport function wangTile(mask: number): WangTile {\n return WANG4[mask & 15];\n}\n\n/** Classify every solid cell into a {frame, rotation}; empty cells are `null`. */\nexport function autotile4(grid: BoolGrid): (WangTile | null)[][] {\n return grid.map((row, y) => row.map((solid, x) => (solid ? wangTile(mask4(grid, x, y)) : null)));\n}\n\n// \u2500\u2500 Marching squares (corner-sampled dual grid) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Case bit order over a cell's corners: TL=1, TR=2, BR=4, BL=8.\n\n/** Per-dual-cell case index (0\u201315) over the grid corners; size (h-1)\u00D7(w-1). */\nexport function marchingSquaresCases(grid: BoolGrid): number[][] {\n const h = grid.length;\n const w = h ? grid[0].length : 0;\n const out: number[][] = [];\n for (let y = 0; y < h - 1; y++) {\n const row: number[] = [];\n for (let x = 0; x < w - 1; x++) {\n row.push(\n (at(grid, x, y) ? 1 : 0) |\n (at(grid, x + 1, y) ? 2 : 0) |\n (at(grid, x + 1, y + 1) ? 4 : 0) |\n (at(grid, x, y + 1) ? 8 : 0),\n );\n }\n out.push(row);\n }\n return out;\n}\n\n// Edge midpoints per case, referenced as pairs. T=top, R=right, B=bottom, L=left.\ntype MSEdge = 'T' | 'R' | 'B' | 'L';\nconst MS_SEGMENTS: ReadonlyArray<ReadonlyArray<readonly [MSEdge, MSEdge]>> = [\n [], // 0\n [['L', 'T']], // 1 TL\n [['T', 'R']], // 2 TR\n [['L', 'R']], // 3 TL,TR\n [['R', 'B']], // 4 BR\n [['L', 'T'], ['R', 'B']], // 5 saddle\n [['T', 'B']], // 6 TR,BR\n [['L', 'B']], // 7 TL,TR,BR\n [['B', 'L']], // 8 BL\n [['T', 'B']], // 9 TL,BL\n [['T', 'R'], ['B', 'L']], // 10 saddle\n [['R', 'B']], // 11 TL,TR,BL\n [['L', 'R']], // 12 BR,BL\n [['T', 'R']], // 13 TL,BR,BL\n [['L', 'T']], // 14 TR,BR,BL\n [], // 15\n];\n\nexport interface ContourSegment {\n a: { x: number; y: number };\n b: { x: number; y: number };\n}\n\nexport interface ContourOptions {\n /** Cell size in design units. Default 1. */\n cell?: number;\n x?: number;\n y?: number;\n}\n\n/** Iso-contour line segments tracing the solid/empty boundary (design units). */\nexport function marchingSquaresContours(grid: BoolGrid, options: ContourOptions = {}): ContourSegment[] {\n const cell = options.cell ?? 1;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const cases = marchingSquaresCases(grid);\n const segs: ContourSegment[] = [];\n const mid = (edge: MSEdge, cx: number, cy: number) => {\n switch (edge) {\n case 'T': return { x: cx + cell / 2, y: cy };\n case 'R': return { x: cx + cell, y: cy + cell / 2 };\n case 'B': return { x: cx + cell / 2, y: cy + cell };\n case 'L': return { x: cx, y: cy + cell / 2 };\n }\n };\n for (let y = 0; y < cases.length; y++) {\n for (let x = 0; x < cases[y].length; x++) {\n const cx = ox + x * cell;\n const cy = oy + y * cell;\n for (const [e1, e2] of MS_SEGMENTS[cases[y][x]]) segs.push({ a: mid(e1, cx, cy), b: mid(e2, cx, cy) });\n }\n }\n return segs;\n}\n\n// \u2500\u2500 Emitters (cosmetic draw data) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AutotileDrawOptions {\n /** Tile size in design units. Default 8. */\n tile?: number;\n x?: number;\n y?: number;\n z?: number;\n transform?: Transform;\n /** Fill colour of solid tiles. */\n fill?: string;\n /** Stroke colour drawn only on sides exposed to empty (the seam). */\n edge?: string;\n edgeWidth?: number;\n}\n\n/**\n * Draw a boolean grid as seamless tiles: a fill per solid cell plus an edge\n * stroke only on sides facing empty (derived from `mask4`). Pure draw data for\n * a `cosmetic` node.\n */\nexport function autotileToCommands(grid: BoolGrid, options: AutotileDrawOptions = {}): (RectCommand | PolyCommand)[] {\n const tile = options.tile ?? 8;\n const ox = options.x ?? 0;\n const oy = options.y ?? 0;\n const z = options.z ?? 0;\n const transform = options.transform ?? IDENTITY;\n const fill = options.fill ?? '#888';\n const edge = options.edge;\n const edgeWidth = options.edgeWidth ?? Math.max(1, tile / 8);\n const out: (RectCommand | PolyCommand)[] = [];\n for (let y = 0; y < grid.length; y++) {\n for (let x = 0; x < grid[y].length; x++) {\n if (!grid[y][x]) continue;\n const px = ox + x * tile;\n const py = oy + y * tile;\n out.push({ kind: 'rect', x: px, y: py, w: tile, h: tile, transform, z, fill });\n if (!edge) continue;\n const m = mask4(grid, x, y);\n const line = (points: number[]) =>\n out.push({ kind: 'poly', points, closed: false, transform, z: z + 1, stroke: edge, strokeWidth: edgeWidth });\n if (!(m & Edge.N)) line([px, py, px + tile, py]);\n if (!(m & Edge.E)) line([px + tile, py, px + tile, py + tile]);\n if (!(m & Edge.S)) line([px, py + tile, px + tile, py + tile]);\n if (!(m & Edge.W)) line([px, py, px, py + tile]);\n }\n }\n return out;\n}\n\n/** Draw the marching-squares iso-contour as open polylines (cosmetic draw data). */\nexport function contourToCommands(grid: BoolGrid, options: AutotileDrawOptions = {}): PolyCommand[] {\n const tile = options.tile ?? 8;\n const transform = options.transform ?? IDENTITY;\n const z = options.z ?? 0;\n const stroke = options.edge ?? options.fill ?? '#333';\n const strokeWidth = options.edgeWidth ?? Math.max(1, tile / 8);\n const segs = marchingSquaresContours(grid, { cell: tile, x: options.x ?? 0, y: options.y ?? 0 });\n return segs.map((s) => ({\n kind: 'poly',\n points: [s.a.x, s.a.y, s.b.x, s.b.y],\n closed: false,\n transform,\n z,\n stroke,\n strokeWidth,\n round: true,\n }));\n}\n", "// Shared boolean grid for procgen output. Plain data + pure functions (house\n// style) so generated levels serialize, hash, and diff cleanly. Convention:\n// `1` = solid/wall, `0` = open/floor \u2014 matching TILE.SOLID / TILE.EMPTY so a\n// grid drops straight into the collision tilemap.\n\nimport { TILE, type TilemapData } from '../physics/tilemap';\n\nexport interface Grid {\n cols: number;\n rows: number;\n /** Row-major cells, length cols*rows. 1 = solid, 0 = open. */\n cells: number[];\n}\n\n/** Allocate a grid filled with a single value (default open). */\nexport function makeGrid(cols: number, rows: number, fill = 0): Grid {\n return { cols, rows, cells: new Array<number>(cols * rows).fill(fill) };\n}\n\n/** Read a cell; out-of-bounds reads as solid (1) so borders seal naturally. */\nexport function gridAt(g: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= g.cols || y >= g.rows) return 1;\n return g.cells[y * g.cols + x];\n}\n\n/** Write a cell (no-op out of bounds). */\nexport function gridSet(g: Grid, x: number, y: number, v: number): void {\n if (x < 0 || y < 0 || x >= g.cols || y >= g.rows) return;\n g.cells[y * g.cols + x] = v;\n}\n\n/** Count solid cells in the 8-neighbourhood (Moore) around (x,y). */\nexport function solidNeighbours(g: Grid, x: number, y: number): number {\n let n = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n if (dx === 0 && dy === 0) continue;\n if (gridAt(g, x + dx, y + dy) === 1) n++;\n }\n }\n return n;\n}\n\n/**\n * Project a grid to collision geometry: 1 \u2192 SOLID, everything else \u2192 EMPTY.\n * The result is a logical, hash-relevant `TilemapData` \u2014 feed it straight to\n * the physics tilemap functions.\n */\nexport function gridToTilemap(g: Grid, tileSize = 32): TilemapData {\n const tiles = g.cells.map((c) => (c === 1 ? TILE.SOLID : TILE.EMPTY));\n return { cols: g.cols, rows: g.rows, tileSize, tiles };\n}\n", "// Coordinate-hash scatter + value noise \u2014 the corpus's actual \"procgen texture\"\n// need (witchcat / cat-survivors do `((x-812347*y)*928371)%17===0`), done right.\n//\n// Every function here is STATELESS and deterministic: the value at a cell is a\n// pure hash of (x, y, seed), so no PRNG stream is threaded and the same world\n// coordinate always decorates the same way \u2014 across frames, reloads, and peers.\n// Output is COSMETIC by intent (decoration placement, dithering, texture): keep\n// it out of `world.hash()`. For logical structure use the carving generators\n// (cave/terrain/rooms), which run off `world.rng`.\n\n/** 32-bit integer hash of a 2D cell + seed. Well-mixed; avalanche on any bit. */\nexport function cellHash(x: number, y: number, seed = 0): number {\n let h = (seed ^ 0x9e3779b9) >>> 0;\n h = Math.imul(h ^ (x | 0), 0x85ebca6b) >>> 0;\n h = Math.imul(h ^ (y | 0), 0xc2b2ae35) >>> 0;\n h ^= h >>> 13;\n h = Math.imul(h, 0x27d4eb2f) >>> 0;\n h ^= h >>> 15;\n return h >>> 0;\n}\n\n/** Deterministic float in [0,1) for a cell \u2014 hash normalized. */\nexport function cellFloat(x: number, y: number, seed = 0): number {\n return cellHash(x, y, seed) / 4294967296;\n}\n\n/** Deterministic integer in [0,n) for a cell (e.g. pick a decoration variant). */\nexport function cellInt(x: number, y: number, n: number, seed = 0): number {\n return Math.floor(cellFloat(x, y, seed) * n);\n}\n\n/** True with ~`probability` at this cell \u2014 the stateless scatter test. */\nexport function scatter(x: number, y: number, probability: number, seed = 0): boolean {\n return cellFloat(x, y, seed) < probability;\n}\n\n/**\n * Enumerate the chosen cells in a rectangle, row-major (ordered). Handy for\n * placing decoration nodes over a visible region without a PRNG. Cosmetic.\n */\nexport function scatterCells(\n x0: number,\n y0: number,\n cols: number,\n rows: number,\n probability: number,\n seed = 0,\n): { x: number; y: number }[] {\n const out: { x: number; y: number }[] = [];\n for (let y = y0; y < y0 + rows; y++) {\n for (let x = x0; x < x0 + cols; x++) {\n if (scatter(x, y, probability, seed)) out.push({ x, y });\n }\n }\n return out;\n}\n\nconst smooth = (t: number): number => t * t * (3 - 2 * t);\n\n/**\n * Value noise in [0,1] at a fractional coordinate \u2014 smooth bilinear blend of the\n * four surrounding integer-cell hashes. This is the deliberately-small\n * alternative to a simplex lib (see JS13K-MINING anti-recommendations): enough\n * for cosmetic terrain tint, cloud cover, wobble; not a gameplay dependency.\n */\nexport function valueNoise(x: number, y: number, seed = 0): number {\n const x0 = Math.floor(x);\n const y0 = Math.floor(y);\n const fx = smooth(x - x0);\n const fy = smooth(y - y0);\n const c00 = cellFloat(x0, y0, seed);\n const c10 = cellFloat(x0 + 1, y0, seed);\n const c01 = cellFloat(x0, y0 + 1, seed);\n const c11 = cellFloat(x0 + 1, y0 + 1, seed);\n const top = c00 + (c10 - c00) * fx;\n const bot = c01 + (c11 - c01) * fx;\n return top + (bot - top) * fy;\n}\n\nexport interface FractalOptions {\n octaves?: number;\n /** Frequency multiplier per octave (default 2). */\n lacunarity?: number;\n /** Amplitude multiplier per octave (default 0.5). */\n gain?: number;\n}\n\n/** Fractal (fBm) value noise \u2014 layered octaves, normalized to [0,1]. Cosmetic. */\nexport function fractalNoise(x: number, y: number, seed = 0, opts: FractalOptions = {}): number {\n const octaves = opts.octaves ?? 4;\n const lacunarity = opts.lacunarity ?? 2;\n const gain = opts.gain ?? 0.5;\n let amp = 1;\n let freq = 1;\n let sum = 0;\n let norm = 0;\n for (let o = 0; o < octaves; o++) {\n sum += amp * valueNoise(x * freq, y * freq, seed + o);\n norm += amp;\n amp *= gain;\n freq *= lacunarity;\n }\n return norm === 0 ? 0 : sum / norm;\n}\n", "// Cave / cavern carving via cellular automata \u2014 space-huggers-style organic\n// caverns. This is LOGICAL structure (it becomes collision geometry), so it is\n// fully deterministic and hash-relevant: all randomness draws from the passed\n// `world.rng`, and every loop iterates row-major (ordered). The knight-dreams\n// anti-pattern (raw `Math.random`) is exactly what this avoids \u2014 pass a seeded\n// `Rng` and the same seed always carves the same cave.\n\nimport type { Rng } from '../core/rng';\nimport { makeGrid, gridSet, solidNeighbours, type Grid } from './grid';\n\nexport interface CaveOptions {\n cols: number;\n rows: number;\n /** Initial solid-fill probability (0..1). ~0.45 gives balanced caverns. */\n fill?: number;\n /** Smoothing passes (more = rounder, larger chambers). Default 4. */\n steps?: number;\n /** A cell becomes solid if it has \u2265 this many solid neighbours. Default 5. */\n birth?: number;\n /** A solid cell survives if it has \u2265 this many solid neighbours. Default 4. */\n survive?: number;\n /** Force the outer ring solid so the cave is sealed. Default true. */\n border?: boolean;\n}\n\n/**\n * Generate a cave grid (1 = rock, 0 = open) with cellular automata. Deterministic\n * given `rng`'s state + options. Feed the result to `gridToTilemap` for physics.\n */\nexport function generateCave(rng: Rng, opts: CaveOptions): Grid {\n const { cols, rows } = opts;\n const fill = opts.fill ?? 0.45;\n const steps = opts.steps ?? 4;\n const birth = opts.birth ?? 5;\n const survive = opts.survive ?? 4;\n const border = opts.border ?? true;\n\n let g = makeGrid(cols, rows, 0);\n // Random seed fill \u2014 ordered draws from world.rng so replays match.\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n const edge = border && (x === 0 || y === 0 || x === cols - 1 || y === rows - 1);\n gridSet(g, x, y, edge || rng.chance(fill) ? 1 : 0);\n }\n }\n\n // Smoothing passes into a fresh grid (double-buffer; no in-place bias).\n for (let s = 0; s < steps; s++) {\n const next = makeGrid(cols, rows, 0);\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (border && (x === 0 || y === 0 || x === cols - 1 || y === rows - 1)) {\n gridSet(next, x, y, 1);\n continue;\n }\n const n = solidNeighbours(g, x, y);\n const wasSolid = g.cells[y * cols + x] === 1;\n gridSet(next, x, y, (wasSolid ? n >= survive : n >= birth) ? 1 : 0);\n }\n }\n g = next;\n }\n return g;\n}\n", "// Endless terrain surface \u2014 knight-dreams' infinite auto-runner terrain, done\n// deterministically. The ground height at a column is a PURE function of the\n// column index + seed (layered value noise), so it needs no PRNG stream and no\n// stored state: any column can be sampled in any order and an infinite world\n// stays perfectly reproducible across peers and reloads.\n//\n// This is LOGICAL structure (the surface is collision), so it belongs in the\n// hash \u2014 and because it is a stateless pure function of (col, seed), it is\n// deterministic by construction. Seed is explicit (derive it from `world.rng`\n// once at setup, e.g. `rng.int(1e9)`), never `Math.random`.\n\nimport { clamp } from '../core/math';\nimport { fractalNoise, type FractalOptions } from './scatter';\n\nexport interface TerrainOptions {\n /** Baseline ground row (tiles from the top). */\n base: number;\n /** Peak deviation above/below the baseline (tiles). */\n amplitude: number;\n /** Horizontal frequency \u2014 smaller = longer, smoother hills. Default 0.08. */\n scale?: number;\n /** Clamp ground into [minRow, maxRow] so it stays on-screen. */\n minRow?: number;\n maxRow?: number;\n seed?: number;\n fractal?: FractalOptions;\n}\n\n/**\n * Ground row (integer tile Y) for a column. Lower row = higher ground. Sampling\n * the same (col, opts) always returns the same height \u2014 the endless-terrain\n * contract.\n */\nexport function terrainHeight(col: number, opts: TerrainOptions): number {\n const scale = opts.scale ?? 0.08;\n const seed = opts.seed ?? 0;\n // valueNoise is [0,1]; center to [-1,1] so the surface undulates about `base`.\n const n = fractalNoise(col * scale, 0, seed, opts.fractal) * 2 - 1;\n let row = Math.round(opts.base + n * opts.amplitude);\n if (opts.minRow !== undefined || opts.maxRow !== undefined) {\n row = clamp(row, opts.minRow ?? -Infinity, opts.maxRow ?? Infinity);\n }\n return row;\n}\n\n/** Ground rows for a contiguous chunk `[startCol, startCol+count)` (ordered). */\nexport function terrainSlice(startCol: number, count: number, opts: TerrainOptions): number[] {\n const out = new Array<number>(count);\n for (let i = 0; i < count; i++) out[i] = terrainHeight(startCol + i, opts);\n return out;\n}\n\n/** True when a tile is solid ground (at or below the surface row) at (col,row). */\nexport function isGround(col: number, row: number, opts: TerrainOptions): boolean {\n return row >= terrainHeight(col, opts);\n}\n", "// Room / segment layout \u2014 space-huggers-style multi-floor bases. Places\n// non-overlapping rectangular rooms into a solid grid and links them with\n// L-shaped corridors, carving floor (0) out of rock (1). LOGICAL structure, so\n// it is hash-relevant: all randomness is drawn from the passed `world.rng` and\n// rooms connect in placement order (ordered iteration) \u2014 same seed, same base.\n\nimport type { Rng } from '../core/rng';\nimport { makeGrid, gridSet, type Grid } from './grid';\n\nexport interface Room {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport interface DungeonOptions {\n cols: number;\n rows: number;\n /** How many placement attempts to make (actual rooms \u2264 this). Default 12. */\n attempts?: number;\n /** Room side length range (tiles), inclusive. */\n minSize?: number;\n maxSize?: number;\n /** Keep a 1-tile solid margin around the grid. Default true. */\n border?: boolean;\n}\n\nexport interface Dungeon {\n rooms: Room[];\n grid: Grid;\n}\n\n/** Center tile of a room (floored). */\nexport function roomCenter(r: Room): { x: number; y: number } {\n return { x: Math.floor(r.x + r.w / 2), y: Math.floor(r.y + r.h / 2) };\n}\n\nfunction overlaps(a: Room, b: Room): boolean {\n // 1-tile gap between rooms so walls never merge.\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\n}\n\nfunction carveRoom(g: Grid, r: Room): void {\n for (let y = r.y; y < r.y + r.h; y++) {\n for (let x = r.x; x < r.x + r.w; x++) gridSet(g, x, y, 0);\n }\n}\n\nfunction carveHCorridor(g: Grid, x0: number, x1: number, y: number): void {\n for (let x = Math.min(x0, x1); x <= Math.max(x0, x1); x++) gridSet(g, x, y, 0);\n}\nfunction carveVCorridor(g: Grid, y0: number, y1: number, x: number): void {\n for (let y = Math.min(y0, y1); y <= Math.max(y0, y1); y++) gridSet(g, x, y, 0);\n}\n\n/**\n * Generate a room-and-corridor layout in a grid (1 = wall, 0 = floor).\n * Deterministic given `rng` state + options; consecutive rooms are joined so the\n * whole floor is connected. Feed `.grid` to `gridToTilemap` for physics.\n */\nexport function generateDungeon(rng: Rng, opts: DungeonOptions): Dungeon {\n const { cols, rows } = opts;\n const attempts = opts.attempts ?? 12;\n const minSize = opts.minSize ?? 4;\n const maxSize = opts.maxSize ?? 8;\n const margin = (opts.border ?? true) ? 1 : 0;\n\n const g = makeGrid(cols, rows, 1); // start solid, carve into it\n const rooms: Room[] = [];\n\n for (let i = 0; i < attempts; i++) {\n const w = rng.intRange(minSize, maxSize);\n const h = rng.intRange(minSize, maxSize);\n const x = rng.intRange(margin, cols - w - margin - 1);\n const y = rng.intRange(margin, rows - h - margin - 1);\n if (x < margin || y < margin) continue;\n const room: Room = { x, y, w, h };\n if (rooms.some((r) => overlaps(room, r))) continue;\n\n carveRoom(g, room);\n if (rooms.length > 0) {\n // Connect to the previous room with an L corridor; coin-flip the elbow.\n const prev = roomCenter(rooms[rooms.length - 1]);\n const cur = roomCenter(room);\n if (rng.chance(0.5)) {\n carveHCorridor(g, prev.x, cur.x, prev.y);\n carveVCorridor(g, prev.y, cur.y, cur.x);\n } else {\n carveVCorridor(g, prev.y, cur.y, prev.x);\n carveHCorridor(g, prev.x, cur.x, cur.y);\n }\n }\n rooms.push(room);\n }\n\n return { rooms, grid: g };\n}\n", "// Headless PCM substrate. Pure, deterministic, zero-dependency: a score renders\n// to Float32 sample buffers in plain Node \u2014 so audio becomes hashable and\n// verifiable like every other Hayao subsystem, not a browser-only black box.\n// All transcendental math routes through dmath (dsin/dcos/dexp2) so a rendered\n// buffer is bit-identical on every JS engine.\n\nimport { clamp } from '../core/math';\nimport { dsin, dcos } from '../core/dmath';\n\n/** Canonical render rate. 44.1 kHz \u2014 CD quality, ubiquitous. */\nexport const SAMPLE_RATE = 44100;\n\n/** A mono signal: Float32 samples, nominally in [-1, 1], at some sample rate. */\nexport type Samples = Float32Array;\n\n/** A stereo buffer: two channels sharing one sample rate. The mix target. */\nexport interface StereoBuffer {\n sampleRate: number;\n left: Float32Array;\n right: Float32Array;\n}\n\n/** Allocate a silent stereo buffer of the given duration. */\nexport function createStereo(durationSec: number, sampleRate = SAMPLE_RATE): StereoBuffer {\n const n = Math.max(0, Math.round(durationSec * sampleRate));\n return { sampleRate, left: new Float32Array(n), right: new Float32Array(n) };\n}\n\n/** Frame count (samples per channel). */\nexport function stereoFrames(buf: StereoBuffer): number {\n return buf.left.length;\n}\n\n/** Duration in seconds. */\nexport function stereoDuration(buf: StereoBuffer): number {\n return buf.left.length / buf.sampleRate;\n}\n\n/**\n * Equal-power pan law. pan \u2208 [-1, 1]: -1 = hard left, 0 = center, +1 = hard\n * right. Uses a quarter-sine curve so total power is constant across the sweep\n * (a linear pan would dip \u22123 dB in the middle).\n */\nexport function panGains(pan: number): { l: number; r: number } {\n const p = (clamp(pan, -1, 1) + 1) * 0.5; // 0..1\n const a = p * (Math.PI / 2); // 0..\u03C0/2\n return { l: dcos(a), r: dsin(a) };\n}\n\n/**\n * Mix a mono signal into a stereo bus at a start sample, with gain and pan.\n * Additive \u2014 many voices accumulate into one bus. Samples outside the bus are\n * clipped away (no reallocation), so callers size the bus for the whole score.\n */\nexport function mixMono(bus: StereoBuffer, sig: Samples, startSample: number, gain = 1, pan = 0): void {\n const { l, r } = panGains(pan);\n const gl = gain * l;\n const gr = gain * r;\n const N = bus.left.length;\n const start = Math.round(startSample);\n for (let i = 0; i < sig.length; i++) {\n const j = start + i;\n if (j < 0) continue;\n if (j >= N) break;\n const s = sig[i];\n bus.left[j] += s * gl;\n bus.right[j] += s * gr;\n }\n}\n\n/** Largest absolute sample across both channels \u2014 the true peak. */\nexport function peak(buf: StereoBuffer): number {\n let p = 0;\n const { left, right } = buf;\n for (let i = 0; i < left.length; i++) {\n const a = left[i] < 0 ? -left[i] : left[i];\n if (a > p) p = a;\n const b = right[i] < 0 ? -right[i] : right[i];\n if (b > p) p = b;\n }\n return p;\n}\n\n/**\n * Transparent soft-clip. Unity slope at the origin (quiet signals pass through\n * untouched) and asymptotes to \u00B11, so it tames peaks without hard-clipping and\n * without boosting quiet material. Only sqrt \u2014 stays deterministic.\n */\nexport function softClip(x: number): number {\n return x / Math.sqrt(1 + x * x);\n}\n\n/** Soft-clip a whole buffer in place. Tames additive overshoot on a busy mix. */\nexport function softClipInPlace(buf: StereoBuffer): void {\n const { left, right } = buf;\n for (let i = 0; i < left.length; i++) {\n left[i] = softClip(left[i]);\n right[i] = softClip(right[i]);\n }\n}\n\n/** Scale a buffer in place so its peak sits at `target` (default \u22121 dBFS-ish). */\nexport function normalize(buf: StereoBuffer, target = 0.89): void {\n const p = peak(buf);\n if (p < 1e-9) return;\n const g = target / p;\n const { left, right } = buf;\n for (let i = 0; i < left.length; i++) {\n left[i] *= g;\n right[i] *= g;\n }\n}\n\n/**\n * Encode a stereo buffer as a 16-bit PCM WAV (RIFF) byte array \u2014 a real,\n * playable artifact a human (or a golden-file test) can keep. Zero-dependency.\n */\nexport function encodeWav(buf: StereoBuffer): Uint8Array {\n const { left, right, sampleRate } = buf;\n const n = left.length;\n const channels = 2;\n const bytesPerSample = 2;\n const blockAlign = channels * bytesPerSample;\n const dataLen = n * blockAlign;\n const out = new Uint8Array(44 + dataLen);\n const dv = new DataView(out.buffer);\n const str = (off: number, s: string) => {\n for (let i = 0; i < s.length; i++) dv.setUint8(off + i, s.charCodeAt(i));\n };\n str(0, 'RIFF');\n dv.setUint32(4, 36 + dataLen, true);\n str(8, 'WAVE');\n str(12, 'fmt ');\n dv.setUint32(16, 16, true); // PCM fmt chunk size\n dv.setUint16(20, 1, true); // PCM\n dv.setUint16(22, channels, true);\n dv.setUint32(24, sampleRate, true);\n dv.setUint32(28, sampleRate * blockAlign, true);\n dv.setUint16(32, blockAlign, true);\n dv.setUint16(34, 16, true); // bits per sample\n str(36, 'data');\n dv.setUint32(40, dataLen, true);\n let off = 44;\n for (let i = 0; i < n; i++) {\n let sl = clamp(left[i], -1, 1);\n let sr = clamp(right[i], -1, 1);\n dv.setInt16(off, (sl < 0 ? sl * 0x8000 : sl * 0x7fff) | 0, true);\n dv.setInt16(off + 2, (sr < 0 ? sr * 0x8000 : sr * 0x7fff) | 0, true);\n off += 4;\n }\n return out;\n}\n\n/**\n * Deterministic 32-bit fingerprint of a signal \u2014 samples quantized to 16-bit\n * then FNV-1a hashed. Lets a test pin \"this synth produces exactly this sound\"\n * without storing the whole buffer, and detect any DSP regression.\n */\nexport function signalHash(sig: Samples): number {\n let h = 2166136261 >>> 0;\n for (let i = 0; i < sig.length; i++) {\n const q = (clamp(sig[i], -1, 1) * 32767) | 0;\n h ^= q & 0xff;\n h = Math.imul(h, 16777619);\n h ^= (q >> 8) & 0xff;\n h = Math.imul(h, 16777619);\n }\n return h >>> 0;\n}\n", "// SFX synthesis \u2014 sound as data. A SoundSpec is a plain, named object (ZzFX's\n// 20-knob vocabulary + jsfxr's filters, but with musical units: slides and\n// jumps in semitones, not raw per-sample deltas) that renders to a mono Float32\n// buffer by pure arithmetic. No Web Audio, no files. Deterministic: the only\n// randomness is the noise source, which draws from a seeded Rng, so the same\n// spec always yields the same samples \u2014 hashable and verifiable in Node.\n\nimport { TAU } from '../core/math';\nimport { dsin, dexp2, dpow } from '../core/dmath';\nimport { Rng } from '../core/rng';\nimport { SAMPLE_RATE, type Samples } from './pcm';\n\nexport type Wave = 'sine' | 'triangle' | 'saw' | 'square' | 'noise';\n\n/**\n * A one-shot sound, fully described by data. Every field is optional; omitted\n * fields take musical defaults. Times are seconds, pitch offsets are semitones,\n * depths are 0..1 unless noted.\n */\nexport interface SoundSpec {\n /** Base pitch in Hz. */\n freq?: number;\n /** Oscillator shape. */\n wave?: Wave;\n /** Square/pulse duty cycle 0..1 (square only). */\n duty?: number;\n\n // \u2500\u2500 amplitude envelope (ADSR), seconds \u2500\u2500\n attack?: number;\n decay?: number;\n sustain?: number; // hold time at sustainLevel\n release?: number;\n sustainLevel?: number; // 0..1 level after decay\n /** Percussive volume spike at onset (jsfxr \"punch\"), 0..1. */\n punch?: number;\n /** Overall output gain. */\n volume?: number;\n\n // \u2500\u2500 pitch dynamics \u2500\u2500\n slide?: number; // glide over the whole sound, semitones\n slideAccel?: number; // extra glide applied quadratically, semitones\n pitchJump?: number; // one-shot shift, semitones\n pitchJumpTime?: number; // when the jump fires, seconds\n vibrato?: number; // depth, semitones\n vibratoFreq?: number; // Hz\n /**\n * Pitch-envelope repeat period, seconds (ZzFX `repeatTime`). Every `repeat`\n * seconds the slide/slideAccel/pitchJump progression resets to its start\n * while the amplitude envelope keeps going \u2014 the classic ZzFX stutter/trill.\n * 0 or absent = off (bit-identical to the pre-`repeat` renderer).\n */\n repeat?: number;\n\n // \u2500\u2500 timbre / character \u2500\u2500\n /** Second detuned oscillator, cents (0 = off). Adds unison warmth/chorus. */\n detune?: number;\n /** Sub-oscillator: a sine one octave down, mixed at this level 0..1. Adds weight. */\n sub?: number;\n noise?: number; // 0..1 blend of white noise into the tone\n shapeCurve?: number; // waveshape exponent; >1 hardens, <1 softens\n fm?: number; // frequency-modulation depth, Hz\n fmFreq?: number; // FM rate, Hz\n tremolo?: number; // amplitude LFO depth 0..1\n tremoloFreq?: number; // Hz\n bitCrush?: number; // sample-and-hold every N samples (0 = off)\n\n // \u2500\u2500 filters (one-pole), Hz cutoff (0 = bypass) \u2500\u2500\n lowpass?: number;\n highpass?: number;\n\n // \u2500\u2500 echo \u2500\u2500\n delay?: number; // echo time, seconds\n delayFeedback?: number; // 0..1\n}\n\ninterface Resolved {\n freq: number;\n wave: Wave;\n duty: number;\n attack: number;\n decay: number;\n sustain: number;\n release: number;\n sustainLevel: number;\n punch: number;\n volume: number;\n slide: number;\n slideAccel: number;\n pitchJump: number;\n pitchJumpTime: number;\n vibrato: number;\n vibratoFreq: number;\n repeat: number;\n detune: number;\n sub: number;\n noise: number;\n shapeCurve: number;\n fm: number;\n fmFreq: number;\n tremolo: number;\n tremoloFreq: number;\n bitCrush: number;\n lowpass: number;\n highpass: number;\n delay: number;\n delayFeedback: number;\n}\n\nfunction resolve(s: SoundSpec): Resolved {\n return {\n freq: s.freq ?? 220,\n wave: s.wave ?? 'sine',\n duty: s.duty ?? 0.5,\n attack: Math.max(0, s.attack ?? 0.005),\n decay: Math.max(0, s.decay ?? 0),\n sustain: Math.max(0, s.sustain ?? 0.08),\n release: Math.max(0, s.release ?? 0.1),\n sustainLevel: s.sustainLevel ?? 1,\n punch: s.punch ?? 0,\n volume: s.volume ?? 0.5,\n slide: s.slide ?? 0,\n slideAccel: s.slideAccel ?? 0,\n pitchJump: s.pitchJump ?? 0,\n pitchJumpTime: s.pitchJumpTime ?? 0,\n vibrato: s.vibrato ?? 0,\n vibratoFreq: s.vibratoFreq ?? 6,\n repeat: Math.max(0, s.repeat ?? 0),\n detune: s.detune ?? 0,\n sub: Math.max(0, s.sub ?? 0),\n noise: s.noise ?? 0,\n shapeCurve: Math.max(0.01, s.shapeCurve ?? 1),\n fm: s.fm ?? 0,\n fmFreq: s.fmFreq ?? 0,\n tremolo: s.tremolo ?? 0,\n tremoloFreq: s.tremoloFreq ?? 8,\n bitCrush: Math.max(0, Math.floor(s.bitCrush ?? 0)),\n lowpass: s.lowpass ?? 0,\n highpass: s.highpass ?? 0,\n delay: Math.max(0, s.delay ?? 0),\n delayFeedback: Math.min(0.95, Math.max(0, s.delayFeedback ?? 0)),\n };\n}\n\n/** semitone offset \u2192 frequency multiplier. */\nfunction semis(n: number): number {\n return dexp2(n / 12);\n}\n\n/** Evaluate a waveform at phase p \u2208 [0,1). */\nfunction waveAt(wave: Wave, p: number, duty: number, rng: Rng): number {\n switch (wave) {\n case 'sine':\n return dsin(TAU * p);\n case 'saw':\n return 2 * p - 1;\n case 'square':\n return p < duty ? 1 : -1;\n case 'triangle': {\n const t = p < 0.5 ? p * 2 : 2 - p * 2; // 0..1..0\n return t * 2 - 1;\n }\n case 'noise':\n return rng.float() * 2 - 1;\n }\n}\n\n/**\n * Render a SoundSpec to a mono signal. Pure and deterministic: pass a seeded\n * `rng` for reproducible noise (defaults to a fixed seed so bare specs are\n * still bit-stable). The returned buffer is normalized only by `volume`, so a\n * caller can mix many at chosen gains.\n */\nexport function renderSound(spec: SoundSpec, opts: { rng?: Rng; sampleRate?: number } = {}): Samples {\n const r = resolve(spec);\n const sr = opts.sampleRate ?? SAMPLE_RATE;\n const rng = opts.rng ?? new Rng(0x5eed);\n\n const body = r.attack + r.decay + r.sustain + r.release;\n const tail = r.delay > 0 ? r.delay * 6 : 0; // let echoes ring out\n const totalSec = body + tail + 0.01;\n const n = Math.max(1, Math.round(totalSec * sr));\n const out = new Float32Array(n);\n\n const dt = 1 / sr;\n let phase = 0;\n let phase2 = 0; // detuned 2nd oscillator\n let phaseSub = 0; // sub-octave oscillator\n const detuneMul = r.detune !== 0 ? semis(r.detune / 100) : 1; // cents \u2192 ratio\n let held = 0; // bitcrush sample-and-hold\n // one-pole filter state\n let lpY = 0;\n let hpY = 0;\n let hpXPrev = 0;\n const lpA = r.lowpass > 0 ? cutoffCoeff(r.lowpass, sr) : 1;\n // HP (leaky DC-blocker y = R\u00B7(y + x \u2212 xPrev)) needs R\u21921 at a LOW cutoff and\n // R\u21920 at a HIGH cutoff \u2014 the inverse of the LP coefficient.\n const hpA = r.highpass > 0 ? 1 - cutoffCoeff(r.highpass, sr) : 0;\n const nyquist = sr * 0.5;\n\n for (let i = 0; i < n; i++) {\n const t = i * dt;\n\n // amplitude envelope (linear ADSR) with punch and tremolo\n let env = adsr(t, r);\n if (r.punch > 0) env *= 1 + r.punch * Math.max(0, 1 - t / Math.max(1e-4, r.attack + r.decay));\n if (r.tremolo > 0) env *= 1 - r.tremolo * 0.5 * (1 - dsin(TAU * r.tremoloFreq * t));\n\n // instantaneous frequency: base \u00D7 slide \u00D7 jump \u00D7 vibrato, with optional FM.\n // `repeat` (ZzFX repeatTime) resets the PITCH-envelope clock every period\n // while `t` (amplitude, vibrato, tremolo) runs on; when off, pt === t so\n // the arithmetic below is bit-identical to the pre-`repeat` renderer.\n const pt = r.repeat > 0 ? t - Math.floor(t / r.repeat) * r.repeat : t;\n const prog = body > 0 ? pt / body : 0;\n let f = r.freq * semis(r.slide * prog + r.slideAccel * prog * prog);\n if (r.pitchJump !== 0 && pt >= r.pitchJumpTime) f *= semis(r.pitchJump);\n if (r.vibrato > 0) f *= semis(r.vibrato * dsin(TAU * r.vibratoFreq * t));\n if (r.fm > 0) f += r.fm * dsin(TAU * r.fmFreq * t);\n // Clamp instantaneous frequency to [0, Nyquist]: deep FM/slide can otherwise\n // drive it negative (mirroring through DC) or past Nyquist (aliasing).\n if (f < 0) f = 0;\n else if (f > nyquist) f = nyquist;\n\n phase += f * dt;\n phase -= Math.floor(phase); // wrap to [0,1)\n\n // oscillator (with optional detuned 2nd osc + sub for warmth/weight)\n let s = waveAt(r.wave, phase, r.duty, rng);\n if (r.detune !== 0) {\n phase2 += f * detuneMul * dt;\n phase2 -= Math.floor(phase2);\n s = (s + waveAt(r.wave, phase2, r.duty, rng)) * 0.5;\n }\n if (r.sub > 0) {\n phaseSub += f * 0.5 * dt;\n phaseSub -= Math.floor(phaseSub);\n s = s * (1 - r.sub * 0.5) + dsin(TAU * phaseSub) * r.sub;\n }\n // noise blend\n if (r.noise > 0) s = s * (1 - r.noise) + (rng.float() * 2 - 1) * r.noise;\n\n // waveshaping (sign-preserving power)\n if (r.shapeCurve !== 1) s = (s < 0 ? -1 : 1) * dpow(s < 0 ? -s : s, r.shapeCurve);\n\n s *= env * r.volume;\n\n // bitcrush: hold the last emitted value for N samples\n if (r.bitCrush > 0) {\n if (i % r.bitCrush === 0) held = s;\n s = held;\n }\n\n out[i] = s;\n }\n\n // filters (post, so cutoff is stable across the whole sound)\n if (r.lowpass > 0) {\n for (let i = 0; i < n; i++) {\n lpY += lpA * (out[i] - lpY);\n out[i] = lpY;\n }\n }\n if (r.highpass > 0) {\n for (let i = 0; i < n; i++) {\n hpY = hpA * (hpY + out[i] - hpXPrev);\n hpXPrev = out[i];\n out[i] = hpY;\n }\n }\n\n // feedback delay (echo)\n if (r.delay > 0) {\n const d = Math.max(1, Math.round(r.delay * sr));\n for (let i = d; i < n; i++) out[i] += out[i - d] * r.delayFeedback;\n }\n\n return out;\n}\n\n/** One-pole cutoff coefficient for a given cutoff frequency. */\nfunction cutoffCoeff(fc: number, sr: number): number {\n const x = TAU * fc * (1 / sr);\n return x / (x + 1);\n}\n\n/** Linear ADSR envelope value at time t. */\nfunction adsr(t: number, r: Resolved): number {\n const a = r.attack;\n const d = r.decay;\n const s = r.sustain;\n const rel = r.release;\n if (t < a) return a > 0 ? t / a : 1;\n if (t < a + d) return d > 0 ? 1 + (r.sustainLevel - 1) * ((t - a) / d) : r.sustainLevel;\n if (t < a + d + s) return r.sustainLevel;\n const rt = t - a - d - s;\n if (rt < rel) return rel > 0 ? r.sustainLevel * (1 - rt / rel) : 0;\n return 0;\n}\n", "// Music theory as pure data \u2014 the deterministic \"oracle\" a composer (human or\n// LLM) leans on so it never has to invent harmony from scratch. Note\u2194MIDI\u2194freq,\n// scales, diatonic chords, and roman-numeral progressions. A hand-rolled subset\n// of tonal.js: zero dependencies, all pure, freq via dmath so it's bit-stable.\n\nimport { dexp2 } from '../core/dmath';\n\nconst NAMES: Record<string, number> = {\n C: 0, 'C#': 1, Db: 1, D: 2, 'D#': 3, Eb: 3, E: 4, Fb: 4, 'E#': 5,\n F: 5, 'F#': 6, Gb: 6, G: 7, 'G#': 8, Ab: 8, A: 9, 'A#': 10, Bb: 10, B: 11, Cb: 11, 'B#': 0,\n};\nconst SHARP_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];\n\n/**\n * Parse scientific pitch notation (\"C4\", \"F#3\", \"Bb5\", \"A4\") to a MIDI number.\n * Middle C (C4) = 60, A4 = 69. Throws on malformed input so bad authoring is\n * caught, not silently mis-sounded.\n */\nexport function noteToMidi(name: string): number {\n const m = /^([A-Ga-g])([#b]?)(-?\\d+)$/.exec(name.trim());\n if (!m) throw new Error(`bad note name: ${JSON.stringify(name)}`);\n const letter = m[1].toUpperCase();\n const pc = NAMES[letter + (m[2] || '')];\n if (pc === undefined) throw new Error(`bad note name: ${JSON.stringify(name)}`);\n const octave = parseInt(m[3], 10);\n return pc + (octave + 1) * 12;\n}\n\n/** MIDI number \u2192 name in sharps, e.g. 60 \u2192 \"C4\". */\nexport function midiToName(midi: number): string {\n const pc = ((midi % 12) + 12) % 12;\n const octave = Math.floor(midi / 12) - 1;\n return SHARP_NAMES[pc] + octave;\n}\n\n/** MIDI number \u2192 frequency in Hz (A4 = a4, default 440). Deterministic. */\nexport function midiToFreq(midi: number, a4 = 440): number {\n return a4 * dexp2((midi - 69) / 12);\n}\n\n/** Convenience: pitch name or MIDI number \u2192 Hz. */\nexport function pitchToFreq(pitch: string | number, a4 = 440): number {\n return midiToFreq(typeof pitch === 'number' ? pitch : noteToMidi(pitch), a4);\n}\n\n/** Scale (mode) interval tables in semitones from the tonic. */\nexport const SCALES = {\n major: [0, 2, 4, 5, 7, 9, 11],\n minor: [0, 2, 3, 5, 7, 8, 10], // natural minor / aeolian\n harmonicMinor: [0, 2, 3, 5, 7, 8, 11],\n melodicMinor: [0, 2, 3, 5, 7, 9, 11],\n dorian: [0, 2, 3, 5, 7, 9, 10],\n phrygian: [0, 1, 3, 5, 7, 8, 10],\n lydian: [0, 2, 4, 6, 7, 9, 11],\n mixolydian: [0, 2, 4, 5, 7, 9, 10],\n locrian: [0, 1, 3, 5, 6, 8, 10],\n majorPentatonic: [0, 2, 4, 7, 9],\n minorPentatonic: [0, 3, 5, 7, 10],\n blues: [0, 3, 5, 6, 7, 10],\n chromatic: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],\n} as const;\n\nexport type ScaleName = keyof typeof SCALES;\n\n/**\n * Scale degrees as MIDI numbers spanning `octaves` starting at `tonic`.\n * e.g. scaleMidis(noteToMidi('C4'), 'major', 2) \u2192 C4 D4 E4 \u2026 up two octaves.\n */\nexport function scaleMidis(tonic: number, mode: ScaleName = 'major', octaves = 1): number[] {\n const steps = SCALES[mode];\n const out: number[] = [];\n for (let o = 0; o < octaves; o++) for (const s of steps) out.push(tonic + o * 12 + s);\n out.push(tonic + octaves * 12); // include the top octave\n return out;\n}\n\n/** Pitch classes (0\u201311) of a scale \u2014 for in-key checks. */\nexport function scalePitchClasses(tonic: number, mode: ScaleName = 'major'): Set<number> {\n const pc = ((tonic % 12) + 12) % 12;\n return new Set(SCALES[mode].map((s) => (pc + s) % 12));\n}\n\n/**\n * Build a diatonic chord by stacking thirds on a scale degree. `degree` is\n * 0-based (0 = I/i). Returns MIDI numbers. `size` 3 = triad, 4 = seventh.\n * Because it stacks the actual scale, chord quality (maj/min/dim) falls out of\n * the mode automatically \u2014 no quality table to get wrong.\n */\nexport function diatonicChord(tonic: number, mode: ScaleName, degree: number, size = 3): number[] {\n const deg = ((degree % 7) + 7) % 7;\n const scale = scaleMidis(tonic, mode, 3); // enough headroom for stacked thirds\n const notes: number[] = [];\n for (let i = 0; i < size; i++) notes.push(scale[deg + i * 2]);\n return notes;\n}\n\nconst ROMAN: Record<string, number> = {\n i: 0, ii: 1, iii: 2, iv: 3, v: 4, vi: 5, vii: 6,\n};\n\n/**\n * Realize a roman-numeral progression in a key to concrete chords (arrays of\n * MIDI notes). Case-insensitive on the numeral; a trailing \"7\" adds a seventh.\n * e.g. progression(noteToMidi('C4'),'major',['I','V','vi','IV']).\n */\nexport function progression(tonic: number, mode: ScaleName, romans: string[]): number[][] {\n return romans.map((r) => {\n const mt = /^([iv]+|[IV]+)(7)?/i.exec(r.trim());\n if (!mt) throw new Error(`bad roman numeral: ${JSON.stringify(r)}`);\n const degree = ROMAN[mt[1].toLowerCase()];\n if (degree === undefined) throw new Error(`bad roman numeral: ${JSON.stringify(r)}`);\n return diatonicChord(tonic, mode, degree, mt[2] ? 4 : 3);\n });\n}\n\n/** Transpose a set of MIDI notes by semitones. */\nexport function transpose(notes: number[], semitones: number): number[] {\n return notes.map((n) => n + semitones);\n}\n\n/**\n * Open a close-position chord: drop the root an octave so the voicing spreads\n * out and the root/7th no longer clash in the same octave. Turns muddy stacked\n * sevenths into something that breathes.\n */\nexport function openVoicing(chord: number[]): number[] {\n if (chord.length < 2) return chord.slice();\n return [chord[0] - 12, ...chord.slice(1)].sort((a, b) => a - b);\n}\n\n/**\n * Smooth a progression's voice-leading. Each chord after the first is octave-\n * shifted so its notes sit near the previous chord's register \u2014 voices move by\n * small steps instead of leaping in parallel root position. The single biggest\n * cure for the \"MIDI demo\" sound. Returns new chords (MIDI, sorted low\u2192high).\n */\nexport function voiceLead(chords: number[][]): number[][] {\n if (chords.length === 0) return [];\n const out: number[][] = [chords[0].slice().sort((a, b) => a - b)];\n for (let i = 1; i < chords.length; i++) {\n const prev = out[i - 1];\n const center = prev.reduce((a, b) => a + b, 0) / prev.length;\n const voiced = chords[i]\n .map((note) => {\n let m = note;\n while (m - center > 6) m -= 12;\n while (center - m > 6) m += 12;\n return m;\n })\n .sort((a, b) => a - b);\n out.push(voiced);\n }\n return out;\n}\n", "// Reverb \u2014 a deterministic Freeverb (Schroeder/Moorer: parallel comb filters\n// into series allpass filters). Dry synth voices sound cheap; a little room\n// makes pads, pianos and strings bloom. Pure integer-delay-line arithmetic, so\n// it's bit-stable and headless like everything else. Applied to a whole mix.\n\nimport { clamp } from '../core/math';\nimport type { StereoBuffer } from './pcm';\n\n// Freeverb's tuned delay lengths (in samples @44.1kHz). Mutually prime-ish so\n// the comb resonances don't pile onto the same frequencies.\nconst COMB_TUNING = [1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617];\nconst ALLPASS_TUNING = [556, 441, 341, 225];\nconst STEREO_SPREAD = 23; // right-channel delay offset for width\nconst FIXED_GAIN = 0.015;\n\nclass Comb {\n private buf: Float32Array;\n private idx = 0;\n private store = 0;\n constructor(size: number, private feedback: number, private damp: number) {\n this.buf = new Float32Array(Math.max(1, size));\n }\n process(x: number): number {\n const y = this.buf[this.idx];\n this.store = y * (1 - this.damp) + this.store * this.damp;\n this.buf[this.idx] = x + this.store * this.feedback;\n this.idx = (this.idx + 1) % this.buf.length;\n return y;\n }\n}\n\nclass Allpass {\n private buf: Float32Array;\n private idx = 0;\n constructor(size: number, private feedback = 0.5) {\n this.buf = new Float32Array(Math.max(1, size));\n }\n process(x: number): number {\n const bufout = this.buf[this.idx];\n const y = -x + bufout;\n this.buf[this.idx] = x + bufout * this.feedback;\n this.idx = (this.idx + 1) % this.buf.length;\n return y;\n }\n}\n\nexport interface ReverbOptions {\n /** Wet/dry mix 0..1 (default 0.25). */\n wet?: number;\n /** Tail length / feedback 0..1 \u2014 bigger = longer, more cathedral (default 0.7). */\n roomSize?: number;\n /** High-frequency damping 0..1 \u2014 bigger = darker tail (default 0.5). */\n damp?: number;\n}\n\nfunction bank(sr: number, feedback: number, damp: number, spread: number): { combs: Comb[]; aps: Allpass[] } {\n const scale = sr / 44100;\n const combs = COMB_TUNING.map((t) => new Comb(Math.round((t + spread) * scale), feedback, damp));\n const aps = ALLPASS_TUNING.map((t) => new Allpass(Math.round((t + spread) * scale), 0.5));\n return { combs, aps };\n}\n\n/**\n * Apply reverb to a stereo buffer in place. A mono send (the L/R sum) feeds two\n * slightly offset comb/allpass banks to produce a stereo tail, mixed back with\n * the dry signal. Deterministic \u2014 pure delay-line arithmetic.\n */\nexport function applyReverb(buf: StereoBuffer, opts: ReverbOptions = {}): void {\n const wet = clamp(opts.wet ?? 0.25, 0, 1);\n const room = clamp(opts.roomSize ?? 0.7, 0, 1);\n const damp = clamp(opts.damp ?? 0.5, 0, 1) * 0.4;\n const feedback = 0.7 + room * 0.28; // 0.7..0.98\n const sr = buf.sampleRate;\n\n const L = bank(sr, feedback, damp, 0);\n const R = bank(sr, feedback, damp, STEREO_SPREAD);\n const n = buf.left.length;\n\n for (let i = 0; i < n; i++) {\n const send = (buf.left[i] + buf.right[i]) * FIXED_GAIN;\n let wl = 0;\n for (const c of L.combs) wl += c.process(send);\n for (const a of L.aps) wl = a.process(wl);\n let wr = 0;\n for (const c of R.combs) wr += c.process(send);\n for (const a of R.aps) wr = a.process(wr);\n buf.left[i] = buf.left[i] * (1 - wet) + wl * wet;\n buf.right[i] = buf.right[i] * (1 - wet) + wr * wet;\n }\n}\n", "// Music composition as data. A Song is a plain, LLM-authorable object: tracks,\n// each an Instrument (a SoundSpec voice template) plus reusable patterns of\n// {pitch, beats, vel} notes sequenced by index (the ZzFXM/tracker model, but\n// with named fields and TinyMusic-style note payloads). renderSong mixes it all\n// down to a StereoBuffer through the SAME deterministic synth core as SFX \u2014 no\n// Web Audio, no files, fully headless and hashable.\n\nimport { Rng } from '../core/rng';\nimport { TAU } from '../core/math';\nimport { dexp, dexp2, dpow } from '../core/dmath';\nimport { renderSound, type SoundSpec } from './synth';\nimport { pitchToFreq } from './theory';\nimport { applyReverb, type ReverbOptions } from './reverb';\nimport { createStereo, mixMono, normalize, softClipInPlace, type StereoBuffer, SAMPLE_RATE } from './pcm';\n\n/** A voice: everything a SoundSpec has except pitch, which each note supplies. */\nexport type Instrument = Omit<SoundSpec, 'freq'>;\n\nexport type Pitch = string | number;\n\n/** One note (or chord, or rest) in a pattern. */\nexport interface Note {\n /** A pitch, a chord (array of pitches), or null for a rest. */\n pitch: Pitch | Pitch[] | null;\n /** Duration in beats. */\n beats: number;\n /** Velocity 0..1 (default 1). */\n vel?: number;\n}\n\n/** A monophonic-per-note lane: an instrument playing sequenced patterns. */\nexport interface Track {\n name?: string;\n instrument: Instrument;\n /** Reusable note patterns, referenced by index in `sequence`. */\n patterns: Note[][];\n /** Order in which patterns play. */\n sequence: number[];\n /** Track mix level (default 0.7). */\n gain?: number;\n /** Stereo position -1..1 (default 0). */\n pan?: number;\n}\n\nexport interface Song {\n bpm: number;\n tracks: Track[];\n /** Concert-A reference (default 440). */\n a4?: number;\n /** Tail seconds appended so release/echo tails ring out (default 2). */\n tailSec?: number;\n /** Room reverb applied to the whole mix (space + glue). */\n reverb?: ReverbOptions;\n /** Swing 0..1 \u2014 delays off-beat 8th notes for a shuffled feel (jazz/lofi). */\n swing?: number;\n /** Humanize 0..1 \u2014 small seeded timing/velocity jitter so it doesn't feel robotic. */\n humanize?: number;\n /**\n * Velocity\u2192brightness 0..1 \u2014 how much a soft note darkens (like a real\n * instrument: harder = brighter). Scales each voice's lowpass by velocity.\n * Default 0.5. This is what turns a velocity map into actual phrasing.\n */\n velBrightness?: number;\n /**\n * Sidechain \"pump\": a beat-synced ducking of the whole mix \u2014 the breathing\n * signature of electronic music. depth 0..1, beatsPerCycle sets the pulse\n * (default 1 = every beat).\n */\n sidechain?: { depth?: number; beatsPerCycle?: number };\n /**\n * Master bus (a light mastering pass): `lowCut` tucks boomy sub/bass, and\n * `presence`/`air` lift high-mid clarity and top-end sparkle. `compress`\n * (0..1) applies a gentle glue compressor with makeup gain \u2014 evens dynamics\n * and lifts perceived loudness (esp. sparse ballads). Each field 0..1.\n */\n master?: { lowCut?: number; presence?: number; air?: number; compress?: number };\n}\n\nfunction patternBeats(pattern: Note[]): number {\n let b = 0;\n for (const n of pattern) b += n.beats;\n return b;\n}\n\nfunction trackBeats(track: Track): number {\n let b = 0;\n for (const idx of track.sequence) b += patternBeats(track.patterns[idx] ?? []);\n return b;\n}\n\n/** Total musical length of a song in beats (the longest track). */\nexport function songBeats(song: Song): number {\n let max = 0;\n for (const t of song.tracks) max = Math.max(max, trackBeats(t));\n return max;\n}\n\n/** Song duration in seconds, excluding the ring-out tail. */\nexport function songDuration(song: Song): number {\n return (songBeats(song) * 60) / song.bpm;\n}\n\n/**\n * Render a Song to a stereo buffer. Deterministic: a per-track seeded Rng feeds\n * any noise voices, so the same Song always produces the same mix. Notes are\n * synthesized via renderSound with the track's instrument, the note's pitch and\n * velocity, and a sustain sized to the note's beat length.\n */\nexport function renderSong(song: Song, opts: { sampleRate?: number; normalizePeak?: number } = {}): StereoBuffer {\n const sr = opts.sampleRate ?? SAMPLE_RATE;\n const a4 = song.a4 ?? 440;\n const secPerBeat = 60 / song.bpm;\n const tail = song.tailSec ?? 2;\n const durSec = songDuration(song) + tail;\n const bus = createStereo(durSec, sr);\n\n const swing = Math.max(0, Math.min(1, song.swing ?? 0));\n const humanize = Math.max(0, Math.min(1, song.humanize ?? 0));\n const velBright = Math.max(0, Math.min(1, song.velBrightness ?? 0.5));\n\n song.tracks.forEach((track, ti) => {\n const gain = track.gain ?? 0.7;\n const pan = track.pan ?? 0;\n const rng = new Rng(0x50c1a1 ^ (ti + 1) * 0x9e3779b9);\n let beat = 0;\n for (const idx of track.sequence) {\n const pattern = track.patterns[idx];\n if (!pattern) continue;\n for (const note of pattern) {\n if (note.pitch !== null && note.pitch !== undefined) {\n // Swing: push off-beat 8ths later (straight 8ths \u2192 shuffled feel).\n // A note on an odd 8th (the \"and\") slides toward the triplet grid.\n const eighth = Math.round(beat * 2);\n const onOff8 = Math.abs(beat * 2 - eighth) < 1e-4 && eighth % 2 === 1;\n const swingBeat = onOff8 ? beat + swing * 0.2 : beat;\n // Humanize: tiny seeded timing (\u00B1ms) and velocity nudges so it breathes.\n const timeJitter = humanize > 0 ? rng.range(-1, 1) * humanize * 0.012 : 0;\n const startSample = Math.round((swingBeat * secPerBeat + timeJitter) * sr);\n const noteSec = note.beats * secPerBeat;\n const velJitter = humanize > 0 ? rng.range(-1, 1) * humanize * 0.12 : 0;\n const vel = Math.max(0.05, Math.min(1, (note.vel ?? 1) + velJitter));\n const pitches = Array.isArray(note.pitch) ? note.pitch : [note.pitch];\n const attack = track.instrument.attack ?? 0.005;\n const decay = track.instrument.decay ?? 0;\n const sustain = Math.max(0.01, noteSec - attack - decay);\n // Velocity \u2192 brightness: soft notes get a lower cutoff, so a velocity\n // map reads as dynamics/timbre, not just loudness.\n const baseLp = track.instrument.lowpass;\n const lp = baseLp && velBright > 0 ? baseLp * (1 - velBright * (1 - vel)) : baseLp;\n for (const p of pitches) {\n const spec: SoundSpec = {\n ...track.instrument,\n freq: pitchToFreq(p, a4),\n sustain,\n volume: (track.instrument.volume ?? 0.5) * vel,\n ...(lp !== undefined ? { lowpass: lp } : {}),\n };\n const sig = renderSound(spec, { rng, sampleRate: sr });\n mixMono(bus, sig, Math.max(0, startSample), gain, pan);\n }\n }\n beat += note.beats;\n }\n }\n });\n\n if (song.sidechain) {\n const depth = Math.max(0, Math.min(1, song.sidechain.depth ?? 0.5));\n const cycleSec = (song.sidechain.beatsPerCycle ?? 1) * secPerBeat;\n applyPump(bus, cycleSec, depth);\n }\n if (song.reverb) applyReverb(bus, song.reverb);\n if (song.master) applyMasterEq(bus, song.master);\n if (song.master?.compress) applyCompressor(bus, song.master.compress);\n softClipInPlace(bus);\n normalize(bus, opts.normalizePeak ?? 0.89);\n return bus;\n}\n\n/**\n * Gentle glue compressor with auto makeup. A feed-forward peak follower drives\n * a soft-knee gain reduction; `amount` (0..1) scales how hard it works. Evens\n * out dynamics and lifts perceived loudness \u2014 the mastering move that keeps a\n * sparse ballad from sounding weak next to a dense funk cut. Deterministic.\n */\nfunction applyCompressor(bus: StereoBuffer, amount: number): void {\n const amt = Math.max(0, Math.min(1, amount));\n const sr = bus.sampleRate;\n const threshold = dbToLin(-20); // dB \u2192 linear\n const ratio = 2 + amt * 3; // 2:1 \u2026 5:1\n const aAtt = dexp(-1 / (sr * 0.005)); // 5 ms attack\n const aRel = dexp(-1 / (sr * 0.15)); // 150 ms release\n const makeup = dbToLin(amt * 6); // up to +6 dB makeup\n let env = 0;\n const L = bus.left;\n const R = bus.right;\n for (let i = 0; i < L.length; i++) {\n const x = Math.max(Math.abs(L[i]), Math.abs(R[i]));\n const coeff = x > env ? aAtt : aRel;\n env = coeff * env + (1 - coeff) * x;\n let gain = 1;\n if (env > threshold) {\n // soft-knee-ish: compress the amount over threshold by the ratio\n const over = env / threshold;\n const compressed = threshold * dpow(over, 1 / ratio);\n gain = compressed / env;\n }\n const g = gain * makeup;\n L[i] *= g;\n R[i] *= g;\n }\n}\n\n/** dB \u2192 linear amplitude (2^(dB/6.0206)); Math.pow is banned in src. */\nfunction dbToLin(db: number): number {\n return dexp2(db / 6.020599913);\n}\n\n/**\n * A light master-EQ pass: tuck lows and lift presence/air so a warm, lowpassed\n * synth mix doesn't turn boomy and the melody stays clear. Built from one-pole\n * shelves (subtract a lowpassed copy for the cut, add highpassed copies for the\n * lifts). Deterministic \u2014 pure per-sample arithmetic.\n */\nfunction applyMasterEq(bus: StereoBuffer, m: { lowCut?: number; presence?: number; air?: number }): void {\n const sr = bus.sampleRate;\n const lowCut = Math.max(0, m.lowCut ?? 0);\n const presence = Math.max(0, m.presence ?? 0);\n const air = Math.max(0, m.air ?? 0);\n const coeff = (fc: number) => {\n const x = TAU * fc * (1 / sr);\n return x / (x + 1);\n };\n const aLow = coeff(240); // tuck the boomy region below ~240 Hz\n const aPres = 1 - coeff(3200); // presence band above ~3.2 kHz\n const aAir = 1 - coeff(9000); // air above ~9 kHz\n for (const ch of [bus.left, bus.right]) {\n let lp = 0;\n let hpP = 0;\n let hpPx = 0;\n let hpA = 0;\n let hpAx = 0;\n for (let i = 0; i < ch.length; i++) {\n const x = ch[i];\n lp += aLow * (x - lp);\n hpP = aPres * (hpP + x - hpPx);\n hpPx = x;\n hpA = aAir * (hpA + x - hpAx);\n hpAx = x;\n ch[i] = x - lowCut * lp + presence * hpP + air * hpA;\n }\n }\n}\n\n/**\n * Apply a beat-synced ducking envelope (sidechain pump): the gain dips at each\n * cycle start and recovers over the cycle. Deterministic \u2014 a pure function of\n * sample index. The classic \"four-on-the-floor breathing\" without a compressor.\n */\nfunction applyPump(bus: StereoBuffer, cycleSec: number, depth: number): void {\n const sr = bus.sampleRate;\n const period = Math.max(1, cycleSec * sr);\n for (let i = 0; i < bus.left.length; i++) {\n const frac = (i % period) / period; // 0 at the beat \u2192 1 at the next\n const recover = 1 - frac;\n const duck = 1 - depth * recover * recover; // sharp dip, quick recover\n bus.left[i] *= duck;\n bus.right[i] *= duck;\n }\n}\n\n/**\n * A small library of ready-to-use instrument voices. These are the \"adopt a\n * timbre\" defaults so a composer starts from something musical, then tweaks.\n */\nexport const INSTRUMENTS: Record<string, Instrument> = {\n // \u2500\u2500 melodic \u2500\u2500\n lead: { wave: 'square', duty: 0.5, attack: 0.008, release: 0.08, volume: 0.4, lowpass: 4000, detune: 6 },\n pluck: { wave: 'triangle', attack: 0.002, decay: 0.06, sustainLevel: 0.3, release: 0.12, volume: 0.42 },\n pad: { wave: 'saw', attack: 0.12, release: 0.5, volume: 0.26, lowpass: 2200, vibrato: 0.08, vibratoFreq: 4, detune: 14 },\n bell: { wave: 'sine', attack: 0.002, decay: 0.3, sustainLevel: 0.2, release: 0.5, volume: 0.4, fm: 3, fmFreq: 220 },\n // piano-ish: bright mallet attack, harmonic decay to a low sustain\n piano: { wave: 'triangle', attack: 0.002, decay: 0.5, sustainLevel: 0.12, release: 0.35, volume: 0.42, lowpass: 3600, detune: 4 },\n // electric piano / Rhodes: FM tine bark + long bloom\n rhodes: { wave: 'sine', attack: 0.003, decay: 0.45, sustainLevel: 0.35, release: 0.4, volume: 0.4, fm: 2.2, fmFreq: 440, detune: 5 },\n // string ensemble: detuned saws, slow bow, gentle vibrato\n strings: { wave: 'saw', attack: 0.16, decay: 0.2, sustainLevel: 0.85, release: 0.6, volume: 0.24, lowpass: 2600, detune: 16, vibrato: 0.07, vibratoFreq: 5 },\n // brass: bright saw with a punchy front\n brass: { wave: 'saw', attack: 0.04, decay: 0.1, sustainLevel: 0.8, release: 0.16, volume: 0.3, lowpass: 3200, detune: 8, punch: 0.3 },\n // organ: sine with sub weight and drawbar-ish steadiness\n organ: { wave: 'sine', attack: 0.006, release: 0.05, sustainLevel: 1, volume: 0.32, sub: 0.5, detune: 3 },\n // choir \"aah\": soft, wide, slow\n choir: { wave: 'triangle', attack: 0.28, release: 0.9, sustainLevel: 0.9, volume: 0.22, lowpass: 2000, detune: 20, vibrato: 0.1, vibratoFreq: 4.5 },\n glocken: { wave: 'sine', attack: 0.001, decay: 0.6, sustainLevel: 0, release: 0.4, volume: 0.34, fm: 4, fmFreq: 1600 },\n // \u2500\u2500 jazz / funk voices \u2500\u2500\n // vibraphone: soft FM bell, slow bloom, gentle tremolo (motor)\n vibraphone: { wave: 'sine', attack: 0.002, decay: 0.5, sustainLevel: 0.25, release: 0.7, volume: 0.4, fm: 2, fmFreq: 880, tremolo: 0.25, tremoloFreq: 5 },\n // clavinet: bright, percussive, funky \u2014 square with a fast pluck\n clav: { wave: 'square', duty: 0.35, attack: 0.001, decay: 0.08, sustainLevel: 0.25, release: 0.08, volume: 0.32, lowpass: 3800, detune: 4 },\n // upright/electric bass: round, short, a little sub\n uprightBass: { wave: 'triangle', attack: 0.004, decay: 0.12, sustainLevel: 0.5, release: 0.1, volume: 0.5, lowpass: 1100, sub: 0.35 },\n // muted trumpet: reedy saw, filtered, a touch of vibrato\n mutedTrumpet: { wave: 'saw', attack: 0.03, decay: 0.08, sustainLevel: 0.75, release: 0.14, volume: 0.3, lowpass: 2600, detune: 4, vibrato: 0.09, vibratoFreq: 6 },\n // jazz guitar: warm triangle pluck\n jazzGuitar: { wave: 'triangle', attack: 0.004, decay: 0.35, sustainLevel: 0.2, release: 0.25, volume: 0.34, lowpass: 2400, detune: 5 },\n // horn section stab: brighter, punchier brass\n horns: { wave: 'saw', attack: 0.02, decay: 0.08, sustainLevel: 0.7, release: 0.12, volume: 0.3, lowpass: 3600, detune: 10, punch: 0.4 },\n // \u2500\u2500 bass \u2500\u2500\n bass: { wave: 'saw', attack: 0.006, release: 0.06, volume: 0.5, lowpass: 900, detune: 6, sub: 0.3 },\n subBass: { wave: 'sine', attack: 0.004, release: 0.08, volume: 0.6, lowpass: 400, sub: 0.5, punch: 0.2 },\n // \u2500\u2500 drums \u2500\u2500\n kick: { wave: 'sine', attack: 0.001, decay: 0.06, sustainLevel: 0, release: 0.08, slide: -24, volume: 0.7, sub: 0.3 },\n snare: { wave: 'noise', attack: 0.001, decay: 0.05, sustainLevel: 0.2, release: 0.12, highpass: 1200, volume: 0.5 },\n hat: { wave: 'noise', attack: 0.001, release: 0.04, highpass: 6000, volume: 0.28 },\n rimshot: { wave: 'noise', attack: 0.001, release: 0.03, highpass: 3000, lowpass: 7000, volume: 0.3 },\n // ride cymbal: a clear \"ping\" with a short decaying wash \u2014 body, not sizzle\n ride: { wave: 'noise', attack: 0.001, decay: 0.1, sustainLevel: 0.14, release: 0.32, volume: 0.2, highpass: 1600, lowpass: 7000 },\n};\n", "// Procedural audio bus. Code-as-sound: zzfx-style tone synthesis + an ambient\n// pad, no audio files. A no-op when there's no AudioContext (Node/headless), so\n// automated runs are silent by construction (a narrow-js invariant).\n//\n// The bus also plays the data-driven engine: renderSound (SoundSpec \u2192 samples)\n// and renderSong (Song \u2192 stereo mix) are pure and deterministic; here they're\n// rendered at the live context's sample rate and pushed through the SFX/music\n// buses as AudioBuffers, so the same specs that verify headlessly also sound.\n\nimport { renderSound, type SoundSpec } from './synth';\nimport { renderSong, songDuration, type Song } from './music';\n\nexport interface Volumes {\n master: number;\n music: number;\n sfx: number;\n muted: boolean;\n}\n\nconst DEFAULT_VOLUMES: Volumes = { master: 0.7, music: 0.6, sfx: 0.8, muted: false };\n\n/** A single zzfx-ish tone spec. */\nexport interface Tone {\n freq: number;\n duration: number;\n type?: OscillatorType;\n gain?: number;\n delay?: number;\n /** Stereo position -1 (left) \u2026 1 (right) \u2014 the spatial-audio hook. */\n pan?: number;\n}\n\nexport class AudioBus {\n private _ctx: AudioContext | null = null;\n private master: GainNode | null = null;\n private musicGain: GainNode | null = null;\n private sfxGain: GainNode | null = null;\n private vol: Volumes = { ...DEFAULT_VOLUMES };\n private padOn = false;\n\n /**\n * The live AudioContext (null until `start()` unlocks audio). External\n * synths being ported in (bundled ZzFX/ZzFXM, hand-rolled Web Audio) should\n * create their sources ON this context \u2014 never their own \u2014 so they inherit\n * the autoplay unlock the user gesture already paid for.\n */\n get ctx(): AudioContext | null {\n return this._ctx;\n }\n /**\n * The SFX mix bus (null until `start()`). Connect external one-shot sources\n * here instead of `ctx.destination` so master/sfx volume and mute apply.\n */\n get sfxBus(): AudioNode | null {\n return this.sfxGain;\n }\n /**\n * The music mix bus (null until `start()`). Connect external music sources\n * (e.g. a ZzFXM-rendered buffer) here so master/music volume and mute apply.\n */\n get musicBus(): AudioNode | null {\n return this.musicGain;\n }\n\n get available(): boolean {\n return typeof globalThis.AudioContext !== 'undefined' || 'webkitAudioContext' in globalThis;\n }\n get started(): boolean {\n return !!this._ctx;\n }\n\n /** Must be called from a user gesture (browser autoplay policy). */\n start(): void {\n if (this._ctx) {\n void this._ctx.resume();\n return;\n }\n if (!this.available) return;\n const Ctx =\n globalThis.AudioContext ||\n (globalThis as unknown as { webkitAudioContext: typeof AudioContext }).webkitAudioContext;\n this._ctx = new Ctx();\n this.master = this._ctx.createGain();\n this.musicGain = this._ctx.createGain();\n this.sfxGain = this._ctx.createGain();\n this.musicGain.connect(this.master);\n this.sfxGain.connect(this.master);\n this.master.connect(this._ctx.destination);\n this.applyVolumes();\n }\n\n setVolumes(v: Partial<Volumes>): void {\n this.vol = { ...this.vol, ...v };\n this.applyVolumes();\n }\n getVolumes(): Volumes {\n return { ...this.vol };\n }\n\n private applyVolumes(): void {\n if (!this._ctx || !this.master || !this.musicGain || !this.sfxGain) return;\n const t = this._ctx.currentTime;\n this.master.gain.setTargetAtTime(this.vol.muted ? 0 : this.vol.master, t, 0.04);\n this.musicGain.gain.setTargetAtTime(this.vol.music * 0.5, t, 0.04);\n this.sfxGain.gain.setTargetAtTime(this.vol.sfx, t, 0.04);\n }\n\n /** Play a single tone (no-op if audio unstarted). */\n tone(spec: Tone): void {\n if (!this._ctx || !this.sfxGain) return;\n const { freq, duration, type = 'sine', gain = 0.2, delay = 0, pan } = spec;\n const t = this._ctx.currentTime + delay;\n const osc = this._ctx.createOscillator();\n osc.type = type;\n osc.frequency.value = freq;\n const g = this._ctx.createGain();\n g.gain.setValueAtTime(0, t);\n g.gain.linearRampToValueAtTime(gain, t + 0.008);\n g.gain.exponentialRampToValueAtTime(0.0001, t + duration);\n osc.connect(g);\n if (pan !== undefined && typeof this._ctx.createStereoPanner === 'function') {\n const p = this._ctx.createStereoPanner();\n p.pan.value = Math.max(-1, Math.min(1, pan));\n g.connect(p);\n p.connect(this.sfxGain);\n } else {\n g.connect(this.sfxGain);\n }\n osc.start(t);\n osc.stop(t + duration + 0.05);\n }\n\n /**\n * A positional cue: gain falls with distance, pan follows the horizontal\n * offset. dx/dist in design-space px; hearing range sets the falloff.\n */\n spatial(freq: number, dx: number, dist: number, hearing = 600, duration = 0.18, type: OscillatorType = 'sawtooth'): void {\n if (dist > hearing) return;\n const near = 1 - dist / hearing;\n this.tone({ freq, duration, type, gain: 0.04 + near * near * 0.3, pan: Math.max(-1, Math.min(1, dx / (hearing * 0.6))) });\n }\n\n /** Play a sequence of tones as an arpeggio/chord. */\n play(tones: Tone[]): void {\n for (const t of tones) this.tone(t);\n }\n\n /**\n * Play a data-defined SoundSpec through the SFX bus. The spec is rendered to\n * samples (deterministically, at the context rate) and played as an\n * AudioBuffer \u2014 the same SoundSpec that a verify suite proves headlessly.\n * No-op without an AudioContext.\n */\n playSpec(spec: SoundSpec, opts: { pan?: number; gain?: number; when?: number } = {}): void {\n if (!this._ctx || !this.sfxGain) return;\n const sig = renderSound(spec, { sampleRate: this._ctx.sampleRate });\n const buf = this._ctx.createBuffer(1, sig.length, this._ctx.sampleRate);\n buf.copyToChannel(new Float32Array(sig), 0);\n const src = this._ctx.createBufferSource();\n src.buffer = buf;\n const g = this._ctx.createGain();\n g.gain.value = opts.gain ?? 1;\n src.connect(g);\n if (opts.pan !== undefined && typeof this._ctx.createStereoPanner === 'function') {\n const p = this._ctx.createStereoPanner();\n p.pan.value = Math.max(-1, Math.min(1, opts.pan));\n g.connect(p);\n p.connect(this.sfxGain);\n } else {\n g.connect(this.sfxGain);\n }\n src.start(this._ctx.currentTime + (opts.when ?? 0));\n }\n\n /**\n * Render a Song offline and play it on the music bus. Returns a stop handle.\n * `loop` repeats the musical body (excluding the ring-out tail). No-op without\n * an AudioContext.\n */\n playSong(song: Song, opts: { loop?: boolean } = {}): () => void {\n if (!this._ctx || !this.musicGain) return () => {};\n const mix = renderSong(song, { sampleRate: this._ctx.sampleRate });\n const buf = this._ctx.createBuffer(2, mix.left.length, this._ctx.sampleRate);\n buf.copyToChannel(new Float32Array(mix.left), 0);\n buf.copyToChannel(new Float32Array(mix.right), 1);\n const src = this._ctx.createBufferSource();\n src.buffer = buf;\n if (opts.loop) {\n src.loop = true;\n src.loopStart = 0;\n src.loopEnd = songDuration(song); // loop the body, not the tail\n }\n src.connect(this.musicGain);\n src.start();\n return () => {\n try {\n src.stop();\n } catch {\n /* already stopped */\n }\n };\n }\n\n /** Convenience SFX. */\n blip(freq = 520): void {\n this.tone({ freq, duration: 0.06, type: 'sine', gain: 0.18 });\n }\n chime(): void {\n [523.25, 659.25, 783.99].forEach((f, i) => this.tone({ freq: f, duration: 0.9 - i * 0.15, type: 'sine', gain: 0.15, delay: i * 0.04 }));\n }\n success(): void {\n [392, 493.88, 587.33, 783.99].forEach((f, i) => this.tone({ freq: f, duration: 0.4, type: 'triangle', gain: 0.15, delay: i * 0.08 }));\n }\n thud(): void {\n this.tone({ freq: 130, duration: 0.14, type: 'sine', gain: 0.22 });\n }\n\n /** Start a soft evolving ambient pad on the music bus. */\n startAmbient(root = 110, voices = [1, 1.5, 2, 2.5]): void {\n if (!this._ctx || !this.musicGain || this.padOn) return;\n this.padOn = true;\n const filter = this._ctx.createBiquadFilter();\n filter.type = 'lowpass';\n filter.frequency.value = 900;\n filter.connect(this.musicGain);\n const bus = this._ctx.createGain();\n bus.gain.value = 0;\n bus.connect(filter);\n for (const mult of voices) {\n const osc = this._ctx.createOscillator();\n osc.type = 'triangle';\n osc.frequency.value = root * mult;\n const g = this._ctx.createGain();\n g.gain.value = 0.1 / voices.length;\n osc.connect(g);\n g.connect(bus);\n osc.start();\n }\n bus.gain.setTargetAtTime(0.9, this._ctx.currentTime, 3);\n }\n}\n\n/** Shared default bus. */\nexport const audio = new AudioBus();\n", "// Audio analysis \u2014 the numeric \"ear\" a headless judge listens with. Pure,\n// deterministic feature extraction over a Float32 signal: loudness, peak,\n// zero-crossing rate, and a spectrum via an in-house radix-2 FFT (twiddles from\n// dmath, so results are bit-identical across engines). This is to a rendered\n// track what world.probe() is to a sim \u2014 the thing tests assert on.\n\nimport { dsin, dcos, dlog10 } from '../core/dmath';\nimport { TAU } from '../core/math';\nimport { SAMPLE_RATE, type Samples } from './pcm';\n\n/** Amplitude ratio \u2192 decibels full-scale. Silence maps to -Infinity. */\nexport function dbfs(amp: number): number {\n const a = amp < 0 ? -amp : amp;\n if (a < 1e-12) return -Infinity;\n return 20 * dlog10(a);\n}\n\n/** Root-mean-square level of a signal. */\nexport function rms(sig: Samples): number {\n if (sig.length === 0) return 0;\n let sum = 0;\n for (let i = 0; i < sig.length; i++) sum += sig[i] * sig[i];\n return Math.sqrt(sum / sig.length);\n}\n\n/** Peak absolute sample. */\nexport function peakAmp(sig: Samples): number {\n let p = 0;\n for (let i = 0; i < sig.length; i++) {\n const a = sig[i] < 0 ? -sig[i] : sig[i];\n if (a > p) p = a;\n }\n return p;\n}\n\n/** Zero crossings per second \u2014 a rough \"noisiness / brightness\" proxy. */\nexport function zcr(sig: Samples, sampleRate = SAMPLE_RATE): number {\n if (sig.length < 2) return 0;\n let crossings = 0;\n for (let i = 1; i < sig.length; i++) {\n if ((sig[i - 1] < 0 && sig[i] >= 0) || (sig[i - 1] >= 0 && sig[i] < 0)) crossings++;\n }\n return (crossings * sampleRate) / sig.length;\n}\n\n/** Largest power of two \u2264 n (n \u2265 1). */\nfunction prevPow2(n: number): number {\n let p = 1;\n while (p * 2 <= n) p *= 2;\n return p;\n}\n\n/**\n * In-place iterative radix-2 Cooley\u2013Tukey FFT. `re`/`im` length must be a power\n * of two. Deterministic: twiddle factors come from dcos/dsin.\n */\nexport function fft(re: Float32Array, im: Float32Array): void {\n const n = re.length;\n // bit-reversal permutation\n for (let i = 1, j = 0; i < n; i++) {\n let bit = n >> 1;\n for (; j & bit; bit >>= 1) j ^= bit;\n j ^= bit;\n if (i < j) {\n const tr = re[i];\n re[i] = re[j];\n re[j] = tr;\n const ti = im[i];\n im[i] = im[j];\n im[j] = ti;\n }\n }\n for (let len = 2; len <= n; len <<= 1) {\n const ang = -TAU / len;\n const wr = dcos(ang);\n const wi = dsin(ang);\n for (let i = 0; i < n; i += len) {\n let cr = 1;\n let ci = 0;\n for (let k = 0; k < len / 2; k++) {\n const a = i + k;\n const b = a + len / 2;\n const tr = cr * re[b] - ci * im[b];\n const ti = cr * im[b] + ci * re[b];\n re[b] = re[a] - tr;\n im[b] = im[a] - ti;\n re[a] += tr;\n im[a] += ti;\n const ncr = cr * wr - ci * wi;\n ci = cr * wi + ci * wr;\n cr = ncr;\n }\n }\n }\n}\n\n/** Hann-windowed magnitude spectrum of a frame (length rounded down to pow2). */\nexport function magnitudeSpectrum(frame: Samples): Float32Array {\n const n = prevPow2(frame.length);\n if (n < 2) return new Float32Array(0); // too short for a spectrum (avoids /0 Hann)\n const re = new Float32Array(n);\n const im = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const w = 0.5 - 0.5 * dcos((TAU * i) / (n - 1)); // Hann\n re[i] = frame[i] * w;\n }\n fft(re, im);\n const half = n >> 1;\n const mag = new Float32Array(half);\n for (let i = 0; i < half; i++) mag[i] = Math.sqrt(re[i] * re[i] + im[i] * im[i]);\n return mag;\n}\n\n/**\n * Spectral centroid (Hz) \u2014 the \"center of mass\" of the spectrum, a robust\n * brightness measure. Averaged over Hann frames across the whole signal.\n */\nexport function spectralCentroid(sig: Samples, sampleRate = SAMPLE_RATE): number {\n const frameSize = 2048;\n if (sig.length < 64) return 0;\n const hop = frameSize;\n let weighted = 0;\n let total = 0;\n for (let start = 0; start + 64 <= sig.length; start += hop) {\n const frame = sig.subarray(start, Math.min(start + frameSize, sig.length));\n const mag = magnitudeSpectrum(frame);\n const binHz = sampleRate / (mag.length * 2);\n for (let k = 0; k < mag.length; k++) {\n weighted += k * binHz * mag[k];\n total += mag[k];\n }\n }\n return total < 1e-9 ? 0 : weighted / total;\n}\n\n/**\n * Spectral flux onset envelope: per-frame sum of positive magnitude increases.\n * Peaks mark note onsets \u2014 the basis for tempo/onset-density features.\n */\nexport function fluxEnvelope(sig: Samples, frameSize = 1024, hop = 512): Float32Array {\n const frames: number[] = [];\n let prev: Float32Array | null = null;\n for (let start = 0; start + frameSize <= sig.length; start += hop) {\n const mag = magnitudeSpectrum(sig.subarray(start, start + frameSize));\n let flux = 0;\n if (prev) {\n const m = Math.min(mag.length, prev.length);\n for (let k = 0; k < m; k++) {\n const d = mag[k] - prev[k];\n if (d > 0) flux += d;\n }\n }\n frames.push(flux);\n prev = mag;\n }\n return Float32Array.from(frames);\n}\n\n/** Onsets per second \u2014 busy/percussive vs sparse/sustained. */\nexport function onsetDensity(sig: Samples, sampleRate = SAMPLE_RATE): number {\n const hop = 512;\n const env = fluxEnvelope(sig, 1024, hop);\n if (env.length < 3) return 0;\n let mean = 0;\n for (let i = 0; i < env.length; i++) mean += env[i];\n mean /= env.length;\n const thresh = mean * 1.5;\n let onsets = 0;\n for (let i = 1; i < env.length - 1; i++) {\n if (env[i] > thresh && env[i] >= env[i - 1] && env[i] > env[i + 1]) onsets++;\n }\n const durSec = sig.length / sampleRate;\n return durSec < 1e-6 ? 0 : onsets / durSec;\n}\n\n/**\n * Estimate tempo (BPM) by autocorrelating the flux onset envelope and picking\n * the strongest lag in the 60\u2013200 BPM band. Returns 0 if indeterminate.\n */\nexport function estimateTempo(sig: Samples, sampleRate = SAMPLE_RATE): number {\n const hop = 512;\n const env = fluxEnvelope(sig, 1024, hop);\n if (env.length < 8) return 0;\n const envRate = sampleRate / hop; // frames per second\n // ceil/floor chosen so the lag range stays INSIDE the 60\u2013200 BPM band.\n const minLag = Math.max(1, Math.ceil((envRate * 60) / 200)); // 200 BPM\n const maxLag = Math.min(env.length - 1, Math.floor((envRate * 60) / 60)); // 60 BPM\n let bestLag = 0;\n let best = -1;\n for (let lag = minLag; lag <= maxLag; lag++) {\n let sum = 0;\n for (let i = lag; i < env.length; i++) sum += env[i] * env[i - lag];\n // Normalize by the overlap count, else short lags (fast tempi) win on term\n // count alone, biasing the estimate high.\n sum /= env.length - lag;\n if (sum > best) {\n best = sum;\n bestLag = lag;\n }\n }\n if (bestLag === 0) return 0;\n // Autocorrelation readily locks onto a subdivision or a multiple; fold the\n // result into a musical range so a slow rubato piece doesn't read as 4\u00D7 tempo.\n let bpm = (60 * envRate) / bestLag;\n while (bpm > 150) bpm /= 2;\n while (bpm > 0 && bpm < 70) bpm *= 2;\n return bpm;\n}\n\n/** Crest factor in dB (peak / rms). Music usually lives ~8\u201320 dB; a tiny value\n * means it's squashed/distorted, a huge value means it's mostly silence. */\nexport function crestFactorDb(sig: Samples): number {\n const r = rms(sig);\n if (r < 1e-9) return 0;\n return dbfs(peakAmp(sig)) - dbfs(r);\n}\n\n/** Fractional energy in coarse frequency bands \u2014 the spectral balance of a mix.\n * Returns fractions (summing to ~1) for sub / bass / lowMid / mid / high / air. */\nexport interface BandBalance {\n sub: number; // 20\u201360 Hz\n bass: number; // 60\u2013250\n lowMid: number; // 250\u2013800\n mid: number; // 800\u20132500\n high: number; // 2500\u20138000\n air: number; // 8000+\n}\nexport function bandBalance(sig: Samples, sampleRate = SAMPLE_RATE): BandBalance {\n const frameSize = 2048;\n const edges = [20, 60, 250, 800, 2500, 8000, sampleRate / 2];\n const acc = new Float64Array(6);\n if (sig.length >= 64) {\n for (let start = 0; start + 64 <= sig.length; start += frameSize) {\n const mag = magnitudeSpectrum(sig.subarray(start, Math.min(start + frameSize, sig.length)));\n const binHz = sampleRate / (mag.length * 2);\n for (let k = 0; k < mag.length; k++) {\n const f = k * binHz;\n const p = mag[k] * mag[k];\n for (let b = 0; b < 6; b++) {\n if (f >= edges[b] && f < edges[b + 1]) {\n acc[b] += p;\n break;\n }\n }\n }\n }\n }\n const total = acc.reduce((a, b) => a + b, 0) || 1;\n return { sub: acc[0] / total, bass: acc[1] / total, lowMid: acc[2] / total, mid: acc[3] / total, high: acc[4] / total, air: acc[5] / total };\n}\n\n/** A compact numeric fingerprint of a signal \u2014 the audio-filmstrip's assertions. */\nexport interface AudioFeatures {\n durationSec: number;\n rms: number;\n peakDb: number;\n centroidHz: number;\n zcr: number;\n onsetDensity: number;\n tempoBpm: number;\n}\n\n/** Extract the full feature vector used by verification. */\nexport function features(sig: Samples, sampleRate = SAMPLE_RATE): AudioFeatures {\n return {\n durationSec: sig.length / sampleRate,\n rms: rms(sig),\n peakDb: dbfs(peakAmp(sig)),\n centroidHz: spectralCentroid(sig, sampleRate),\n zcr: zcr(sig, sampleRate),\n onsetDensity: onsetDensity(sig, sampleRate),\n tempoBpm: estimateTempo(sig, sampleRate),\n };\n}\n", "// Jazz harmony vocabulary \u2014 chord symbols \u2192 notes. This is what lets a composer\n// write real changes (\"Cm9 | F13 | Bbmaj7 | Ebmaj7#11 | Dm7b5 G7alt Cm6\") instead\n// of only diatonic triads. Pure and deterministic: a chord is a set of MIDI\n// numbers derived from a root + a quality table + optional slash bass.\n\nimport { noteToMidi } from './theory';\n\n/** Quality \u2192 chromatic intervals (semitones) from the root. Covers the common\n * jazz vocabulary; author with these exact quality strings so typos throw. */\nconst QUALITIES: Record<string, number[]> = {\n '': [0, 4, 7], maj: [0, 4, 7], M: [0, 4, 7],\n m: [0, 3, 7], min: [0, 3, 7], '-': [0, 3, 7],\n dim: [0, 3, 6], aug: [0, 4, 8], '+': [0, 4, 8],\n // sixths\n '6': [0, 4, 7, 9], m6: [0, 3, 7, 9], '-6': [0, 3, 7, 9],\n '69': [0, 4, 7, 9, 14], '6/9': [0, 4, 7, 9, 14],\n // major sevenths\n maj7: [0, 4, 7, 11], M7: [0, 4, 7, 11], maj9: [0, 4, 7, 11, 14],\n 'maj7#11': [0, 4, 7, 11, 18], maj13: [0, 4, 7, 11, 14, 21],\n // dominants\n '7': [0, 4, 7, 10], '9': [0, 4, 7, 10, 14], '11': [0, 7, 10, 14, 17], '13': [0, 4, 7, 10, 14, 21],\n '7b9': [0, 4, 7, 10, 13], '7#9': [0, 4, 7, 10, 15], '7#11': [0, 4, 7, 10, 18],\n '7b13': [0, 4, 7, 10, 20], '7b5': [0, 4, 6, 10], '7#5': [0, 4, 8, 10],\n '13b9': [0, 4, 7, 10, 13, 21], '13#11': [0, 4, 7, 10, 18, 21], '9#11': [0, 4, 7, 10, 14, 18],\n '7alt': [0, 4, 10, 13, 20], // 3, b7, b9, b13 \u2014 one alteration family, fifth omitted\n // minor sevenths\n m7: [0, 3, 7, 10], min7: [0, 3, 7, 10], '-7': [0, 3, 7, 10],\n m9: [0, 3, 7, 10, 14], m11: [0, 3, 7, 10, 14, 17], m13: [0, 3, 7, 10, 14, 21],\n m7b5: [0, 3, 6, 10], \u00F8: [0, 3, 6, 10], \u00F87: [0, 3, 6, 10],\n dim7: [0, 3, 6, 9], mMaj7: [0, 3, 7, 11], 'm(maj7)': [0, 3, 7, 11], mMaj9: [0, 3, 7, 11, 14],\n // suspensions & added\n sus4: [0, 5, 7], sus2: [0, 2, 7], '7sus4': [0, 5, 7, 10], '9sus4': [0, 5, 7, 10, 14],\n add9: [0, 4, 7, 14], madd9: [0, 3, 7, 14],\n};\n\n/**\n * Parse a chord symbol to MIDI notes at the given octave (default 4). Supports\n * a slash bass (\"C/E\", \"Dm7/G\"). Throws on an unknown quality so authoring\n * mistakes surface instead of sounding wrong.\n */\nexport function chordNotes(symbol: string, octave = 4): number[] {\n const sym = symbol.trim();\n const slash = sym.split('/');\n const head = slash[0];\n const m = /^([A-Ga-g][#b]?)(.*)$/.exec(head);\n if (!m) throw new Error(`bad chord symbol: ${JSON.stringify(symbol)}`);\n const rootName = m[1][0].toUpperCase() + (m[1][1] ?? '');\n const quality = m[2];\n const ints = QUALITIES[quality];\n if (!ints) throw new Error(`unknown chord quality ${JSON.stringify(quality)} in ${JSON.stringify(symbol)}`);\n const root = noteToMidi(rootName + octave);\n const notes = ints.map((i) => root + i);\n if (slash.length === 2) {\n // place the bass note below the chord\n const bm = /^([A-Ga-g][#b]?)$/.exec(slash[1].trim());\n if (bm) {\n const bassName = bm[1][0].toUpperCase() + (bm[1][1] ?? '');\n let bass = noteToMidi(bassName + (octave - 1));\n while (bass >= notes[0]) bass -= 12;\n notes.unshift(bass);\n }\n }\n return notes;\n}\n\n/**\n * Rootless voicing: drop the root (the bass covers it) and keep the colour\n * tones (3rd, 7th, extensions) in a tight register \u2014 the authentic sound of\n * jazz-piano/Rhodes comping. Optionally recenter near `targetMidi`.\n */\nexport function rootless(chord: number[], targetMidi?: number): number[] {\n const body = chord.slice(1); // drop the lowest (root/bass)\n if (targetMidi === undefined || body.length === 0) return body;\n const center = body.reduce((a, b) => a + b, 0) / body.length;\n const shift = Math.round((targetMidi - center) / 12) * 12;\n return body.map((n) => n + shift).sort((a, b) => a - b);\n}\n\n/**\n * Resolve a whole progression of chord symbols to note sets. Convenience for\n * writing changes as a string array: chordChanges(['Dm7','G7','Cmaj7']).\n */\nexport function chordChanges(symbols: string[], octave = 4): number[][] {\n return symbols.map((s) => chordNotes(s, octave));\n}\n", "// The music linter \u2014 a deterministic rule-checker for Songs. This is to music\n// what assertSolvable is to a puzzle: a machine proof that authored output is\n// well-formed and musically sane, run BEFORE anyone listens. The LLM-music\n// literature is unanimous that a rule-based gate (not an LLM \"judge\", which\n// reward-hacks) is what keeps generated music in-key and structured. Pure and\n// deterministic, so it slots into the verify harness like every other check.\n\nimport { noteToMidi, scalePitchClasses, type ScaleName } from './theory';\nimport type { Song, Note, Pitch } from './music';\n\nexport interface MusicLintResult {\n ok: boolean;\n /** Hard failures: malformed data that would render wrong or crash. */\n errors: string[];\n /** Musical smells: renders fine, but likely not what was intended. */\n warnings: string[];\n}\n\nfunction pitchToMidiSafe(p: Pitch): number | null {\n try {\n return typeof p === 'number' ? p : noteToMidi(p);\n } catch {\n return null;\n }\n}\n\nfunction eachPitch(note: Note): Pitch[] {\n if (note.pitch === null || note.pitch === undefined) return [];\n return Array.isArray(note.pitch) ? note.pitch : [note.pitch];\n}\n\nexport interface LintOptions {\n /** If given, flag notes outside this key/mode as out-of-key warnings. */\n key?: { tonic: Pitch; mode: ScaleName };\n /** Max fraction of out-of-key notes tolerated before it's an error (default 1 = never). */\n maxOutOfKey?: number;\n}\n\n/**\n * Lint a Song. Errors block (bad bpm, empty tracks, unparseable pitches, bad\n * pattern indices, non-positive durations, out-of-MIDI-range pitches). Warnings\n * flag musical smells (out-of-key notes, no structural repetition).\n */\nexport function lintSong(song: Song, opts: LintOptions = {}): MusicLintResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!(song.bpm > 0) || song.bpm < 20 || song.bpm > 400) {\n errors.push(`bpm ${song.bpm} out of sane range [20,400]`);\n }\n if (!song.tracks || song.tracks.length === 0) errors.push('song has no tracks');\n\n const inKey = opts.key ? scalePitchClasses(pitchToMidiSafe(opts.key.tonic) ?? 0, opts.key.mode) : null;\n let totalNotes = 0;\n let outOfKey = 0;\n const patternUse = new Map<string, number>();\n\n song.tracks.forEach((track, ti) => {\n const label = track.name ?? `track ${ti}`;\n if (!track.patterns || track.patterns.length === 0) errors.push(`${label}: no patterns`);\n if (!track.sequence || track.sequence.length === 0) errors.push(`${label}: empty sequence`);\n if (track.pan !== undefined && (track.pan < -1 || track.pan > 1)) {\n errors.push(`${label}: pan ${track.pan} out of [-1,1]`);\n }\n for (const idx of track.sequence ?? []) {\n if (idx < 0 || idx >= (track.patterns?.length ?? 0)) {\n errors.push(`${label}: sequence references missing pattern ${idx}`);\n continue;\n }\n const key = `${ti}:${idx}`;\n patternUse.set(key, (patternUse.get(key) ?? 0) + 1);\n for (const note of track.patterns[idx]) {\n if (!(note.beats > 0)) errors.push(`${label}: note with non-positive beats ${note.beats}`);\n if (note.vel !== undefined && (note.vel < 0 || note.vel > 1)) {\n errors.push(`${label}: velocity ${note.vel} out of [0,1]`);\n }\n for (const p of eachPitch(note)) {\n const midi = pitchToMidiSafe(p);\n if (midi === null) {\n errors.push(`${label}: unparseable pitch ${JSON.stringify(p)}`);\n continue;\n }\n if (midi < 0 || midi > 127) errors.push(`${label}: pitch ${p} outside MIDI 0..127`);\n totalNotes++;\n if (inKey && !inKey.has(((midi % 12) + 12) % 12)) outOfKey++;\n }\n }\n }\n });\n\n if (inKey && totalNotes > 0) {\n const frac = outOfKey / totalNotes;\n const limit = opts.maxOutOfKey ?? 1;\n const msg = `${outOfKey}/${totalNotes} notes (${Math.round(frac * 100)}%) out of key`;\n if (frac > limit) errors.push(msg);\n else if (outOfKey > 0) warnings.push(msg);\n }\n\n // Structure: if nothing repeats, the piece has no form \u2014 a smell, not an error.\n const anyReuse = [...patternUse.values()].some((c) => c > 1);\n if (!anyReuse && song.tracks.length > 0) {\n warnings.push('no pattern is reused \u2014 piece may lack structure/repetition');\n }\n\n return { ok: errors.length === 0, errors, warnings };\n}\n\n/**\n * Check that a roman-numeral progression resolves to tonic \u2014 a real cadence,\n * not a phrase left hanging. Accepts an ending on I/i, or a V(7)\u2192I/i cadence.\n */\nexport function cadenceResolves(romans: string[]): boolean {\n if (romans.length === 0) return false;\n const norm = (r: string) => r.trim().toLowerCase().replace(/7$/, '');\n const last = norm(romans[romans.length - 1]);\n return last === 'i';\n}\n", "// Feature matching \u2014 the engine of the AI-led improvement loop. Given a\n// reference track's measured features and a candidate render, compute how far\n// apart they are and, crucially, WHICH way each feature is off (\"too dark\",\n// \"too slow\", \"too quiet\"). That actionable diff is what lets an LLM recreate\n// good game music in the engine, discover where the synthesis falls short, and\n// drive what to build next. Pure and deterministic.\n\nimport type { AudioFeatures } from './analysis';\n\n/** Per-feature normalization scales \u2014 the \"how much is a lot\" for each axis. */\ninterface FeatureWeights {\n tempoBpm: number;\n centroidHz: number;\n rms: number;\n zcr: number;\n onsetDensity: number;\n peakDb: number;\n}\n\n// Denominators chosen so a \"musically noticeable\" difference is ~1.0 on each\n// axis: ~20 BPM, ~1200 Hz of brightness, a doubling of level, etc.\nconst DEFAULT_WEIGHTS: FeatureWeights = {\n tempoBpm: 20,\n centroidHz: 1200,\n rms: 0.1,\n zcr: 1500,\n onsetDensity: 4,\n peakDb: 6,\n};\n\nexport interface FeatureDelta {\n feature: keyof FeatureWeights;\n reference: number;\n candidate: number;\n /** Normalized signed error (candidate \u2212 reference) / scale. */\n normalized: number;\n /** Human/LLM-actionable direction, e.g. \"too dark\", \"too fast\". */\n note: string;\n}\n\nexport interface MatchResult {\n /** Overall distance (RMS of normalized per-feature errors). 0 = identical. */\n distance: number;\n /** Per-feature breakdown, largest error first. */\n deltas: FeatureDelta[];\n /** The single most-off feature's note, or 'close match'. */\n headline: string;\n}\n\nconst NOTES: Record<keyof FeatureWeights, [string, string]> = {\n // [candidate < reference, candidate > reference]\n tempoBpm: ['too slow', 'too fast'],\n centroidHz: ['too dark / muffled', 'too bright / harsh'],\n rms: ['too quiet', 'too loud'],\n zcr: ['too smooth / tonal', 'too noisy / gritty'],\n onsetDensity: ['too sparse', 'too busy'],\n peakDb: ['more headroom than reference', 'hotter / less headroom than reference'],\n};\n\n/**\n * Compare a candidate feature vector to a reference. Returns an overall\n * distance plus a per-feature, direction-aware breakdown sorted by severity.\n */\nexport function featureDistance(\n reference: AudioFeatures,\n candidate: AudioFeatures,\n weights: Partial<FeatureWeights> = {},\n): MatchResult {\n const w = { ...DEFAULT_WEIGHTS, ...weights };\n const keys = Object.keys(w) as (keyof FeatureWeights)[];\n const deltas: FeatureDelta[] = [];\n let sumSq = 0;\n\n for (const k of keys) {\n const ref = reference[k];\n const cand = candidate[k];\n // guard non-finite (e.g. peakDb = -Infinity on silence)\n const refN = Number.isFinite(ref) ? ref : 0;\n const candN = Number.isFinite(cand) ? cand : 0;\n const normalized = (candN - refN) / w[k];\n sumSq += normalized * normalized;\n const [lo, hi] = NOTES[k];\n const note = Math.abs(normalized) < 0.25 ? 'ok' : normalized < 0 ? lo : hi;\n deltas.push({ feature: k, reference: refN, candidate: candN, normalized, note });\n }\n\n deltas.sort((a, b) => Math.abs(b.normalized) - Math.abs(a.normalized));\n const distance = Math.sqrt(sumSq / keys.length);\n const worst = deltas[0];\n const headline =\n Math.abs(worst.normalized) < 0.25 ? 'close match' : `${worst.feature}: ${worst.note}`;\n\n return { distance, deltas, headline };\n}\n\n/**\n * A compact, printable report of the mismatch \u2014 the \"shortcomings\" surface an\n * AI loop reads to decide its next move.\n */\nexport function matchReport(reference: AudioFeatures, candidate: AudioFeatures): string {\n const r = featureDistance(reference, candidate);\n const lines = r.deltas\n .filter((d) => d.note !== 'ok')\n .map((d) => ` ${d.feature.padEnd(13)} ${d.candidate.toFixed(1)} vs ${d.reference.toFixed(1)} \u2192 ${d.note}`);\n return (\n `match distance ${r.distance.toFixed(3)} \u2014 ${r.headline}\\n` +\n (lines.length ? lines.join('\\n') : ' (all features within tolerance)')\n );\n}\n", "// Adaptive & spatial audio \u2014 FMOD/Wwise concepts in miniature, kept PURE so\n// they verify headlessly. The whole system stays deterministic because audio is\n// a projection of game state, never of wall-clock or Math.random:\n// \u2022 RTPC curves \u2014 map a game value (health, depth, speed) through an\n// authored breakpoint curve to an audio target.\n// \u2022 distance model \u2014 the exact Web Audio linear/inverse/exponential rolloff\n// formulas, so our headless gain matches live PannerNode.\n// \u2022 vertical layers \u2014 layer gains as a pure function of an intensity value\n// (the highest-leverage adaptive-music trick).\n// A thin driver (elsewhere) pushes these numbers into GainNode/PannerNode; the\n// numbers themselves are what tests assert on.\n\nimport { clamp } from '../core/math';\nimport { dexp2, dlog2 } from '../core/dmath';\n\n/** A breakpoint on an RTPC curve: at input `x`, the target is `y`. */\nexport interface Breakpoint {\n x: number;\n y: number;\n}\n\n/**\n * Evaluate a piecewise-linear RTPC curve at `x`. Breakpoints are sorted by x;\n * values outside the range clamp to the nearest endpoint. This one primitive\n * drives volume, filter cutoff, layer gain, and distance in a uniform, testable\n * way \u2014 exactly what a Wwise RTPC / FMOD parameter automation does.\n */\nexport function evalCurve(curve: Breakpoint[], x: number): number {\n if (curve.length === 0) return 0;\n const pts = curve.length > 1 ? [...curve].sort((a, b) => a.x - b.x) : curve;\n if (x <= pts[0].x) return pts[0].y;\n if (x >= pts[pts.length - 1].x) return pts[pts.length - 1].y;\n for (let i = 1; i < pts.length; i++) {\n if (x <= pts[i].x) {\n const a = pts[i - 1];\n const b = pts[i];\n const t = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);\n return a.y + (b.y - a.y) * t;\n }\n }\n return pts[pts.length - 1].y;\n}\n\nexport type DistanceModel = 'linear' | 'inverse' | 'exponential';\n\n/**\n * Distance-attenuation gain, matching the Web Audio PannerNode formulas exactly\n * so an offline render agrees with live playback. `refDistance` is full volume,\n * `maxDistance` is the floor, `rolloff` shapes the falloff.\n */\nexport function distanceGain(\n model: DistanceModel,\n distance: number,\n refDistance = 1,\n maxDistance = 10000,\n rolloff = 1,\n): number {\n const ref = Math.max(1e-6, refDistance);\n switch (model) {\n case 'linear': {\n const d = clamp(distance, ref, maxDistance);\n return 1 - (rolloff * (d - ref)) / Math.max(1e-6, maxDistance - ref);\n }\n case 'inverse': {\n const d = Math.max(distance, ref);\n return ref / (ref + rolloff * (Math.max(d, ref) - ref));\n }\n case 'exponential': {\n const d = Math.max(distance, ref);\n // (d/ref)^(-rolloff) via dexp2/dlog2 (Math.pow is banned in src)\n return dexp2(-rolloff * dlog2(d / ref));\n }\n }\n}\n\n/**\n * Equal-power stereo pan from a horizontal offset. dx is the source's screen-x\n * relative to the listener; `spread` is the half-width at which pan saturates.\n */\nexport function panFromOffset(dx: number, spread = 400): number {\n return clamp(dx / spread, -1, 1);\n}\n\n/**\n * A positional cue's mix: distance-attenuated gain \u00D7 pan. Combines the two\n * above into what a 2-D game actually needs. `hearing` is the cutoff beyond\n * which the source is inaudible.\n */\nexport interface SpatialMix {\n gain: number;\n pan: number;\n audible: boolean;\n}\nexport function spatialMix(dx: number, dy: number, hearing = 600, rolloff = 1): SpatialMix {\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist > hearing) return { gain: 0, pan: 0, audible: false };\n const gain = distanceGain('inverse', dist, hearing * 0.15, hearing, rolloff);\n return { gain, pan: panFromOffset(dx, hearing * 0.7), audible: true };\n}\n\n/** A named layer of vertical (stacked) adaptive music. */\nexport interface MusicLayer {\n name: string;\n /** The layer fades in from `fadeIn` and reaches full gain by `full` intensity. */\n fadeIn: number;\n full: number;\n /** Optional cap on this layer's gain (default 1). */\n maxGain?: number;\n}\n\n/**\n * Vertical layering: given an intensity value (0..1, e.g. combat proximity),\n * return each layer's gain. Layers fade in at their thresholds so texture\n * thickens with intensity without ever interrupting the flow \u2014 the single\n * biggest adaptive-music payoff per line, and trivially deterministic.\n */\nexport function layerGains(layers: MusicLayer[], intensity: number): Record<string, number> {\n const out: Record<string, number> = {};\n for (const l of layers) {\n const span = Math.max(1e-6, l.full - l.fadeIn);\n const g = clamp((intensity - l.fadeIn) / span, 0, 1) * (l.maxGain ?? 1);\n out[l.name] = g;\n }\n return out;\n}\n\n/**\n * A ducking envelope target: while a higher-priority bus (dialogue, a stinger)\n * is active, the ducked bus drops by `amount` dB. Returns a linear gain the\n * driver ramps toward with setTargetAtTime \u2014 deterministic because it's keyed\n * off game state, not an audio sidechain.\n */\nexport function duckGain(active: boolean, amountDb = -12): number {\n return active ? dexp2((amountDb / 6.0206) ) : 1; // dB \u2192 linear via 2^(dB/6.02)\n}\n", "// Objective quality scorer \u2014 turns \"is this track any good?\" into numbers so\n// the Build-Measure-Learn loop has a hard gate, not a vibe. Measures the things\n// that actually make a mix sound professional vs amateurish: loudness, headroom,\n// dynamics (crest factor), stereo width, spectral balance (mud/harshness), and\n// genre-fit (tempo/brightness/density). Pure and deterministic.\n\nimport { features, crestFactorDb, bandBalance, rms } from './analysis';\nimport type { StereoBuffer } from './pcm';\n\n/** Stereo width via mid/side energy ratio. 0 = mono, ~0.3+ = a wide mix. */\nexport function stereoWidth(buf: StereoBuffer): number {\n const n = buf.left.length;\n const mid = new Float32Array(n);\n const side = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n mid[i] = (buf.left[i] + buf.right[i]) * 0.5;\n side[i] = (buf.left[i] - buf.right[i]) * 0.5;\n }\n const m = rms(mid);\n return m < 1e-9 ? 0 : rms(side) / m;\n}\n\ntype Range = [number, number];\n\nexport interface GenreProfile {\n tempo: Range;\n centroid: Range; // Hz \u2014 spectral centroid of the FULL mix; bright percussion\n // (hats/cymbals/noise) legitimately raises this, so windows reflect the norm\n // for a *balanced* mix, not a bass-heavy one.\n onsets: Range; // per second\n rms: Range;\n crestDb: Range;\n width: Range;\n /** Max acceptable low-mid (250\u2013800 Hz) fraction \u2014 warm genres tolerate more. */\n maxMud?: number;\n}\n\n/** Target windows per genre \u2014 set to real genre norms for a balanced mix. */\nexport const GENRE_PROFILES: Record<string, GenreProfile> = {\n electronic: { tempo: [118, 132], centroid: [3000, 7200], onsets: [7, 15], rms: [0.16, 0.27], crestDb: [6, 15], width: [0.03, 0.6], maxMud: 0.34 },\n lofi: { tempo: [70, 88], centroid: [1600, 4300], onsets: [5, 13], rms: [0.12, 0.24], crestDb: [7, 17], width: [0.04, 0.6], maxMud: 0.5 },\n // rubato solo piano defeats autocorrelation tempo \u2014 window widened honestly.\n piano: { tempo: [58, 100], centroid: [700, 2100], onsets: [3, 11], rms: [0.1, 0.22], crestDb: [9, 22], width: [0.04, 0.7], maxMud: 0.42 },\n orchestral: { tempo: [80, 96], centroid: [1100, 3000], onsets: [4, 12], rms: [0.11, 0.22], crestDb: [8, 21], width: [0.05, 0.7], maxMud: 0.4 },\n jazzfunk: { tempo: [106, 126], centroid: [2200, 5600], onsets: [6, 16], rms: [0.13, 0.25], crestDb: [7, 18], width: [0.04, 0.6], maxMud: 0.4 },\n};\n\n/** 1.0 inside [lo,hi]; ramps linearly to 0 across `margin` (relative) outside. */\nfunction windowScore(x: number, [lo, hi]: Range): number {\n if (x >= lo && x <= hi) return 1;\n const span = Math.max(1e-6, hi - lo);\n const d = x < lo ? lo - x : x - hi;\n return Math.max(0, 1 - d / (span * 0.6));\n}\n\nexport interface QualityScore {\n score: number; // 0..100\n dims: Record<string, number>; // 0..1 each\n notes: string[]; // actionable failings\n}\n\n/**\n * Score a rendered track against a genre profile. Weighted mean of dimensions,\n * \u00D7100. `notes` lists any dimension below a comfortable threshold with the\n * measured value and direction, so a composer knows exactly what to fix.\n */\nexport function scoreTrack(buf: StereoBuffer, profile: GenreProfile): QualityScore {\n const mono = new Float32Array(buf.left.length);\n for (let i = 0; i < mono.length; i++) mono[i] = (buf.left[i] + buf.right[i]) * 0.5;\n const f = features(mono);\n const crest = crestFactorDb(mono);\n const bands = bandBalance(mono);\n const width = stereoWidth(buf);\n const mud = bands.lowMid; // energy piled in 250\u2013800 Hz reads as muddy\n const harsh = bands.high + bands.air; // 2.5 kHz+ excess reads as harsh/fatiguing\n const lowEnd = bands.sub + bands.bass;\n\n const dims: Record<string, number> = {\n loudness: windowScore(f.rms, profile.rms),\n headroom: f.peakDb <= -0.5 ? (f.peakDb >= -3 ? 1 : windowScore(f.peakDb, [-3, -0.5])) : 0, // no clipping\n dynamics: windowScore(crest, profile.crestDb),\n width: windowScore(width, profile.width),\n brightness: windowScore(f.centroidHz, profile.centroid),\n density: windowScore(f.onsetDensity, profile.onsets),\n tempo: windowScore(f.tempoBpm, profile.tempo),\n lowEnd: windowScore(lowEnd, [0.12, 0.7]), // present but not boomy\n clarity: windowScore(mud, [0, profile.maxMud ?? 0.34]), // not muddy (genre-aware)\n smoothness: windowScore(harsh, [0, 0.4]), // not harsh\n };\n\n const weights: Record<string, number> = {\n loudness: 1.2, headroom: 1.4, dynamics: 1, width: 0.7, brightness: 1.1,\n density: 0.9, tempo: 0.7, lowEnd: 1, clarity: 1.2, smoothness: 1.1,\n };\n let sum = 0;\n let wsum = 0;\n for (const k of Object.keys(dims)) {\n sum += dims[k] * weights[k];\n wsum += weights[k];\n }\n const score = Math.round((sum / wsum) * 100);\n\n const notes: string[] = [];\n const say = (dim: string, msg: string) => {\n if (dims[dim] < 0.75) notes.push(`${dim}: ${msg}`);\n };\n say('loudness', `rms ${f.rms.toFixed(3)} (target ${profile.rms.join('\u2013')})`);\n say('headroom', `peak ${f.peakDb.toFixed(1)}dB (want \u2264 \u22120.5, \u2265 \u22123)`);\n say('dynamics', `crest ${crest.toFixed(1)}dB (target ${profile.crestDb.join('\u2013')})`);\n say('width', `width ${width.toFixed(2)} (target ${profile.width.join('\u2013')})`);\n say('brightness', `centroid ${Math.round(f.centroidHz)}Hz (target ${profile.centroid.join('\u2013')})`);\n say('density', `onsets ${f.onsetDensity.toFixed(1)}/s (target ${profile.onsets.join('\u2013')})`);\n say('tempo', `tempo ${Math.round(f.tempoBpm)} (target ${profile.tempo.join('\u2013')})`);\n say('lowEnd', `low-end fraction ${lowEnd.toFixed(2)} (want 0.12\u20130.62)`);\n say('clarity', `low-mid mud ${mud.toFixed(2)} (want \u2264 ${(profile.maxMud ?? 0.34).toFixed(2)})`);\n say('smoothness', `high/air ${harsh.toFixed(2)} (want \u2264 0.40)`);\n\n return { score, dims, notes };\n}\n", "// Genre songbook \u2014 hand-composed reference tracks that show the composition\n// engine across styles: minimal electronic, lo-fi, melancholic piano, epic\n// orchestral, and jazz-funk. Each is plain data built with the theory helpers\n// (so it stays in-key, diatonic, and voice-led) and renders through renderSong.\n// These are both a demo and a fixture: the AI loop can measure them and try to\n// beat them. Revised after a producer critique \u2014 voice-leading, real swing,\n// velocity\u2192brightness, sidechain pump, darker lo-fi, expressive piano space.\n\nimport { INSTRUMENTS, type Song, type Note, type Track } from './music';\nimport { progression, voiceLead, openVoicing, scaleMidis, noteToMidi } from './theory';\n\nconst n = (pitch: Note['pitch'], beats: number, vel = 1): Note => ({ pitch, beats, vel });\nconst rest = (beats: number): Note => ({ pitch: null, beats });\n\n/** Arpeggiate a chord (MIDI notes) into `steps` notes of `beatsEach`, cycling up. */\nfunction arp(chord: number[], steps: number, beatsEach: number, vel = 0.9): Note[] {\n const out: Note[] = [];\n for (let i = 0; i < steps; i++) out.push(n(chord[i % chord.length] + Math.floor(i / chord.length) * 12, beatsEach, vel));\n return out;\n}\n\n/** Four-on-the-floor kick pattern of `beats` quarter-note hits. */\nfunction fourOnFloor(pitch: string, beats: number, vel = 1): Note[] {\n return Array.from({ length: beats }, () => n(pitch, 1, vel));\n}\n\nexport interface GenreTrack {\n id: string;\n name: string;\n description: string;\n make: () => Song;\n}\n\n// \u2500\u2500 1. Minimal bass-driven electronic \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A-minor drive, i\u2013VI\u2013III\u2013VII, pulsing sub, four-on-the-floor, sidechain pump,\n// a filtered pluck and a real lead hook with a non-chord tone.\nfunction minimalElectronic(): Song {\n const chords = progression(noteToMidi('A3'), 'minor', ['i', 'VI', 'III', 'VII']);\n const roots = chords.map((c) => c[0] - 12);\n const bass: Track = {\n name: 'sub', instrument: INSTRUMENTS.subBass, gain: 0.6,\n patterns: roots.map((r) => [n(r, 0.5, 1), n(r, 0.5, 0.6), n(r, 0.5, 0.85), n(r, 0.5, 0.6), n(r, 0.5, 1), n(r, 0.5, 0.6), n(r, 0.5, 0.85), n(r, 0.5, 0.7)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const kick: Track = { name: 'kick', instrument: INSTRUMENTS.kick, gain: 0.82, patterns: [fourOnFloor('A1', 4)], sequence: Array(8).fill(0) };\n const hat: Track = {\n name: 'hat', instrument: INSTRUMENTS.hat, gain: 0.42, pan: 0.15,\n patterns: [[rest(0.5), n('A6', 0.5, 0.7), rest(0.5), n('A6', 0.5, 0.5)]],\n sequence: Array(16).fill(0),\n };\n const pluck: Track = {\n name: 'pluck', instrument: { ...INSTRUMENTS.pluck, release: 0.16, lowpass: 2400 }, gain: 0.62, pan: -0.2,\n patterns: chords.map((c) => arp([c[0], c[1], c[2]], 4, 1, 0.7)),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const lead: Track = {\n name: 'lead', instrument: { ...INSTRUMENTS.lead, detune: 8, lowpass: 2800 }, gain: 0.52, pan: 0.1,\n patterns: [\n // a singable hook: 5th, b7 (passing tone), root, then a held 3rd\n [n(chords[0][2] + 12, 0.75), n(chords[0][2] + 14, 0.25), n(chords[0][0] + 12, 1), n(chords[0][1] + 12, 2)],\n [n(chords[1][2] + 12, 1), n(chords[1][1] + 12, 0.5), n(chords[1][2] + 12, 0.5), n(chords[1][0] + 24, 2)],\n [n(chords[2][2] + 12, 0.75), n(chords[2][1] + 12, 0.25), n(chords[2][0] + 12, 1), n(chords[2][2] + 12, 2)],\n [n(chords[3][0] + 24, 1), n(chords[3][2] + 12, 0.5), n(chords[3][1] + 12, 0.5), n(chords[3][0] + 12, 2)],\n ],\n sequence: [0, 1, 2, 3],\n };\n return {\n bpm: 126, tracks: [kick, bass, hat, pluck, lead],\n reverb: { wet: 0.15, roomSize: 0.6, damp: 0.5 }, humanize: 0.05,\n sidechain: { depth: 0.55, beatsPerCycle: 1 },\n master: { lowCut: 0.35, presence: 0.2, air: 0.08 },\n };\n}\n\n// \u2500\u2500 2. Easygoing lo-fi \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Swung, dusty jazz sevenths (Fmaj7\u2013Em7\u2013Dm7\u2013Cmaj7), voice-led + opened, warm\n// bass, brushed drums, a dull filtered hat, and a bed of vinyl crackle.\nfunction lofi(): Song {\n const key = noteToMidi('C4');\n const chords = voiceLead(progression(key, 'major', ['IV7', 'iii7', 'ii7', 'I7']).map(openVoicing));\n const bassRoots = chords.map((c) => c[0] - 12);\n const rhodes: Track = {\n name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.42, lowpass: 2600, fm: 1.6 }, gain: 0.66, pan: -0.1,\n patterns: chords.map((c) => [n(c.map((x) => x), 3.5, 0.75), rest(0.5)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.bass, lowpass: 650, sub: 0.28 }, gain: 0.72, pan: 0.05,\n patterns: bassRoots.map((r) => [n(r, 1.5, 0.9), rest(0.5), n(r + 7, 1, 0.7), n(r + 5, 1, 0.6)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const kick: Track = { name: 'kick', instrument: { ...INSTRUMENTS.kick, volume: 0.75 }, gain: 0.82, patterns: [[n('C2', 1, 0.9), rest(1), n('C2', 0.5, 0.6), rest(0.5), n('C2', 0.5, 0.4), rest(0.5)]], sequence: Array(8).fill(0) };\n const snare: Track = { name: 'snare', instrument: { ...INSTRUMENTS.rimshot, volume: 0.24, lowpass: 4000 }, gain: 0.6, patterns: [[rest(1), n('C4', 1, 0.7), rest(1), n('C4', 1, 0.7)]], sequence: Array(8).fill(0) };\n const hat: Track = { name: 'hat', instrument: { ...INSTRUMENTS.hat, volume: 0.14, highpass: 2500, lowpass: 6000 }, gain: 0.45, pan: 0.2, patterns: [[n('C6', 0.5, 0.5), n('C6', 0.5, 0.3)]], sequence: Array(16).fill(0) };\n // a whisper of vinyl warmth \u2014 much subtler than before (was too much hiss)\n const vinyl: Track = { name: 'vinyl', instrument: { wave: 'noise', attack: 0.5, release: 0.5, sustainLevel: 1, volume: 0.022, lowpass: 2800, highpass: 400 }, gain: 0.3, patterns: [[n('C4', 16, 1)]], sequence: [0] };\n const keys: Track = {\n name: 'keys', instrument: { ...INSTRUMENTS.piano, volume: 0.3, lowpass: 2800 }, gain: 0.48, pan: 0.15,\n patterns: [\n [n(chords[0][2] + 12, 1, 0.7), rest(1), n(chords[0][1] + 12, 0.5, 0.55), n(chords[0][2] + 12, 0.5, 0.5), rest(1)],\n [rest(0.5), n(chords[1][2] + 12, 1, 0.7), rest(0.5), n(chords[1][1] + 12, 2, 0.55)],\n [n(chords[2][2] + 12, 1.5, 0.7), n(chords[2][1] + 12, 0.5, 0.5), rest(2)],\n [rest(1), n(chords[3][2] + 12, 1, 0.7), n(chords[3][1] + 12, 1, 0.55), rest(1)],\n ],\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n return {\n bpm: 78, tracks: [vinyl, rhodes, bass, kick, snare, hat, keys],\n swing: 0.75, humanize: 0.4, velBrightness: 0.7, reverb: { wet: 0.24, roomSize: 0.7, damp: 0.65 },\n master: { lowCut: 0.26, presence: 0.22, air: 0.05 }, // keep it dusty but clear the mud\n };\n}\n\n// \u2500\u2500 3. Sad & melancholic piano \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Slow A-minor, sparse voice-led piano with rests + rubato, string bed, big room.\nfunction melancholicPiano(): Song {\n const key = noteToMidi('A3');\n const chords = voiceLead(progression(key, 'minor', ['i', 'VI', 'III', 'VII']));\n // sparser, varied arpeggios with rests \u2014 space is the expression\n const figs = [\n (c: number[]) => [n(c[0], 1, 0.85), n(c[2], 1, 0.55), rest(2)],\n (c: number[]) => [n(c[2], 1.5, 0.8), rest(0.5), n(c[1], 2, 0.5)],\n (c: number[]) => [rest(1), n(c[1] + 12, 1.5, 0.7), rest(1.5)],\n (c: number[]) => [n(c[0], 2, 0.8), n(c[2], 1, 0.55), rest(1)],\n ];\n const piano: Track = {\n name: 'piano', instrument: { ...INSTRUMENTS.piano, volume: 0.46 }, gain: 0.78, pan: -0.05,\n patterns: chords.map((c, i) => figs[i % figs.length](c)),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const strings: Track = {\n name: 'strings', instrument: { ...INSTRUMENTS.strings, attack: 0.4 }, gain: 0.5, pan: 0.1,\n patterns: chords.map((c) => [n(c.map((x) => x - 12), 4, 0.65)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const sub: Track = {\n name: 'sub', instrument: { ...INSTRUMENTS.subBass, volume: 0.4, attack: 0.03 }, gain: 0.55,\n patterns: chords.map((c) => [n(c[0] - 24, 4, 0.6)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const melody: Track = {\n name: 'melody', instrument: { ...INSTRUMENTS.piano, volume: 0.4, lowpass: 3000 }, gain: 0.5, pan: 0.12,\n patterns: [\n [rest(2), n(chords[0][2] + 12, 1, 0.75), n(chords[0][1] + 12, 1, 0.55)],\n [n(chords[1][2] + 12, 2, 0.8), n(chords[1][1] + 12, 1, 0.55), rest(1)],\n [rest(1.5), n(chords[2][2] + 12, 1.5, 0.75), n(chords[2][1] + 12, 1, 0.55)],\n [n(chords[3][1] + 12, 1.5, 0.7), n(chords[3][0] + 12, 2.5, 0.6)], // VII \u2192 resolve down to tonic feel\n ],\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n return { bpm: 66, tracks: [sub, strings, piano, melody], humanize: 0.5, velBrightness: 0.75, reverb: { wet: 0.38, roomSize: 0.86, damp: 0.55 }, master: { lowCut: 0.4, presence: 0.28, air: 0.12 } };\n}\n\n// \u2500\u2500 4. Epic & uplifting orchestral \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Driving D-minor with a lift, voice-led. Strings arpeggiate, brass carries an\n// actual stepwise THEME on top, choir + glockenspiel crown it, timpani drives.\nfunction epicOrchestral(): Song {\n const key = noteToMidi('D3');\n const all = voiceLead(progression(key, 'minor', ['i', 'VI', 'III', 'VII', 'VI', 'VII', 'i', 'i']));\n const scale = scaleMidis(noteToMidi('D4'), 'minor', 3);\n const deg = (i: number) => scale[((i % scale.length) + scale.length) % scale.length];\n const strings: Track = {\n name: 'strings', instrument: { ...INSTRUMENTS.strings, volume: 0.24 }, gain: 0.7, pan: -0.15,\n patterns: all.map((c) => arp([c[0], c[1], c[2], c[0] + 12], 8, 0.5, 0.75)),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n // a real soaring theme (scale-step melody), one bar each\n const themeBars: Note[][] = [\n [n(deg(0), 2, 0.9), n(deg(1), 1, 0.8), n(deg(2), 1, 0.85)],\n [n(deg(4), 3, 0.95), n(deg(2), 1, 0.8)],\n [n(deg(1), 2, 0.85), n(deg(0), 1, 0.8), n(deg(1), 1, 0.8)],\n [n(deg(4), 2, 0.9), n(deg(5), 2, 0.95)],\n [n(deg(5), 2, 0.95), n(deg(4), 1, 0.85), n(deg(2), 1, 0.8)],\n [n(deg(4), 2, 0.9), n(deg(6), 2, 0.95)],\n [n(deg(7), 3, 1), n(deg(6), 1, 0.85)],\n [n(deg(7), 4, 1)],\n ];\n const restBar: Note[] = [rest(4)];\n const brass: Track = {\n name: 'brass', instrument: { ...INSTRUMENTS.brass, volume: 0.32 }, gain: 0.62, pan: 0.15,\n // enters at bar 3 \u2014 a two-bar build before the theme lands (payoff > static)\n patterns: [restBar, ...themeBars], sequence: [0, 0, 1, 2, 3, 4, 5, 6],\n };\n const choir: Track = {\n name: 'choir', instrument: { ...INSTRUMENTS.choir, volume: 0.18 }, gain: 0.5, pan: 0.05,\n patterns: all.map((c) => [n([c[2] + 12, c[0] + 24], 4, 0.6)]),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const timp: Track = {\n name: 'timpani', instrument: { ...INSTRUMENTS.kick, decay: 0.14, release: 0.25, slide: -12, volume: 0.85, sub: 0.5 }, gain: 0.82,\n patterns: [[n('D2', 1, 1), n('D2', 1, 0.6), n('D2', 0.5, 0.85), n('D2', 0.5, 0.6), n('D2', 1, 0.9)]],\n sequence: Array(8).fill(0),\n };\n const glock: Track = {\n name: 'glocken', instrument: INSTRUMENTS.glocken, gain: 0.32, pan: 0.25,\n // sparkles in only from bar 3, with the theme\n patterns: [restBar, ...all.map((c) => [rest(1), n(c[2] + 24, 1, 0.55), rest(1), n(c[1] + 24, 1, 0.5)])],\n sequence: [0, 0, 3, 4, 5, 6, 7, 8],\n };\n return { bpm: 88, tracks: [timp, strings, brass, choir, glock], humanize: 0.14, velBrightness: 0.5, reverb: { wet: 0.32, roomSize: 0.9, damp: 0.4 }, master: { lowCut: 0.4, presence: 0.32, air: 0.14 } };\n}\n\n// \u2500\u2500 5. Jazzy & funky \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Swung ii\u2013V\u2013I\u2013vi in C with 7ths, a real walking bass that approaches the next\n// root chromatically, syncopated Rhodes comps, brass stabs, a swung ride.\nfunction jazzFunk(): Song {\n const key = noteToMidi('C4');\n const chords = progression(key, 'major', ['ii7', 'V7', 'I7', 'vi7']);\n const voiced = voiceLead(chords.map(openVoicing));\n // walking bass: root, chord 3rd, chord 5th, then chromatic approach to next root\n const bassPats = chords.map((c, i) => {\n const next = chords[(i + 1) % chords.length][0] - 24;\n const root = c[0] - 24;\n const third = c[1] - 24;\n const fifth = c[2] - 24;\n const approach = next + (root < next ? -1 : 1); // lean into the next root\n return [n(root, 1, 0.95), n(third, 1, 0.75), n(fifth, 1, 0.8), n(approach, 1, 0.7)];\n });\n const bass: Track = { name: 'bass', instrument: { ...INSTRUMENTS.bass, lowpass: 1000, sub: 0.35, release: 0.12 }, gain: 0.74, patterns: bassPats, sequence: [0, 1, 2, 3, 0, 1, 2, 3] };\n const rhodes: Track = {\n name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.3 }, gain: 0.62, pan: -0.15,\n patterns: voiced.map((c) => [rest(0.5), n(c.map((x) => x), 0.75, 0.7), rest(0.75), n(c.map((x) => x), 0.5, 0.55), rest(1.5)]),\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const stab: Track = {\n name: 'brass', instrument: { ...INSTRUMENTS.brass, release: 0.1, volume: 0.24 }, gain: 0.55, pan: 0.2,\n patterns: [\n [rest(2), n(voiced[0].map((x) => x + 12), 0.5, 0.85), rest(1.5)],\n [rest(3), n(voiced[1].map((x) => x + 12), 0.5, 0.85), rest(0.5)],\n [n(voiced[2].map((x) => x + 12), 0.5, 0.8), rest(3.5)],\n [rest(2.5), n(voiced[3].map((x) => x + 12), 0.5, 0.8), rest(1)],\n ],\n sequence: [0, 1, 2, 3, 0, 1, 2, 3],\n };\n const ride: Track = { name: 'ride', instrument: { ...INSTRUMENTS.hat, volume: 0.13, highpass: 3000, lowpass: 9000, release: 0.08 }, gain: 0.5, pan: 0.1, patterns: [[n('C6', 0.5, 0.6), n('C6', 0.5, 0.35), n('C6', 0.5, 0.5), n('C6', 0.5, 0.35)]], sequence: Array(16).fill(0) };\n const snare: Track = { name: 'snare', instrument: { ...INSTRUMENTS.snare, volume: 0.28, highpass: 900 }, gain: 0.5, patterns: [[rest(1), n('D4', 1, 0.6), rest(1), n('D4', 1, 0.7)]], sequence: Array(8).fill(0) };\n const kick: Track = { name: 'kick', instrument: { ...INSTRUMENTS.kick, volume: 0.55 }, gain: 0.62, patterns: [[n('C2', 1, 0.85), rest(1.5), n('C2', 0.5, 0.6), rest(1)]], sequence: Array(8).fill(0) };\n return { bpm: 116, tracks: [bass, rhodes, stab, kick, snare, ride], swing: 0.66, humanize: 0.35, velBrightness: 0.6, reverb: { wet: 0.16, roomSize: 0.55, damp: 0.5 }, master: { lowCut: 0.5, presence: 0.18, air: 0.07 } };\n}\n\n/** The genre songbook \u2014 the demo set. */\nexport const GENRES: GenreTrack[] = [\n { id: 'electronic', name: 'Minimal Electronic', description: 'Bass-driven four-on-the-floor in A minor \u2014 pulsing sidechained sub, offbeat hats, a synth hook.', make: minimalElectronic },\n { id: 'lofi', name: 'Lo-fi Beats', description: 'Swung, dusty jazz sevenths on a Rhodes with warm bass, brushed drums and vinyl crackle.', make: lofi },\n { id: 'piano', name: 'Melancholic Piano', description: 'Slow, sad A-minor piano with space and rubato over a string bed in a big room.', make: melancholicPiano },\n { id: 'orchestral', name: 'Epic Orchestral', description: 'Uplifting D-minor with a soaring brass theme, arpeggiated strings, choir, timpani and glockenspiel.', make: epicOrchestral },\n { id: 'jazzfunk', name: 'Jazz Funk', description: 'Swung ii\u2013V\u2013I with a walking bass that chromatically approaches each chord, Rhodes comping and brass stabs.', make: jazzFunk },\n];\n\n/** Look up a genre by id. */\nexport function genre(id: string): GenreTrack | undefined {\n return GENRES.find((g) => g.id === id);\n}\n", "// ZzFX bridge \u2014 convert a positional ZzFX parameter array (the 20-knob\n// `zzfx(...)` call you copy out of the ZzFX sound designer) into a named,\n// unit-sane hayao SoundSpec. This is a PORTING seam: paste the array, get a\n// spec, keep hayao's deterministic renderer \u2014 no second AudioContext, no\n// bundled zzfx. The conversions below encode the unit mismatches found while\n// recreating js13k games (docs/TRIAGE-2026-07-recreations.md, ninja-cat 2.x):\n//\n// \u2022 slide ZzFX slides in semitones/SECOND; hayao's `slide` is total\n// semitones over the whole body \u2192 slide \u00D7 bodyDuration.\n// \u2022 deltaSlide slide acceleration (semitones/s\u00B2) \u2192 hayao's quadratic\n// `slideAccel` term \u2248 deltaSlide \u00D7 body\u00B2 / 2.\n// \u2022 pitchJump an absolute Hz ADDEND in ZzFX; hayao jumps in semitones \u2192\n// 12\u00B7log2((freq + jump) / freq).\n// \u2022 filter one signed knob: positive = lowpass cutoff Hz, negative =\n// highpass cutoff Hz.\n// \u2022 shape index \u2192 wave name (3, \"tan\", has no hayao equivalent and\n// approximates to a hard-shaped square).\n// \u2022 randomness DROPPED: hayao specs are deterministic by design \u2014 the same\n// spec must hash to the same samples. Warned once.\n// \u2022 modulation approximated as vibrato (pitch LFO at |modulation| Hz);\n// ZzFX's FM feedback shape has no exact match. Warned once.\n// \u2022 repeatTime \u2192 SoundSpec `repeat` (the pitch envelope resets each period\n// while the amplitude envelope runs on \u2014 see synth.ts).\n//\n// Parameters with no faithful mapping warn once per parameter name (not per\n// call), then approximate \u2014 a port should sound close first, exact later.\n\nimport { dlog2 } from '../core/dmath';\nimport type { SoundSpec, Wave } from './synth';\n\n/** ZzFX shape index \u2192 hayao wave. Index 3 (\"tan\") is approximated. */\nconst SHAPES: readonly Wave[] = ['sine', 'triangle', 'saw', 'square', 'noise'];\n\n/** Warn once per parameter name, ever \u2014 ports call this per-sfx in a loop. */\nconst warned = new Set<string>();\nfunction warnOnce(param: string, msg: string): void {\n if (warned.has(param)) return;\n warned.add(param);\n console.warn(`[hayao] specFromZzfx: ${param} ${msg}`);\n}\n\n/** Test hook: clear the warn-once memory. */\nexport function resetZzfxWarnings(): void {\n warned.clear();\n}\n\n/**\n * Convert a positional ZzFX parameter array to a hayao SoundSpec.\n * Argument order (defaults in parens) is ZzFX's `zzfx(...)` signature:\n * volume(1), randomness(.05), frequency(220), attack(0), sustain(0),\n * release(.1), shape(0), shapeCurve(1), slide(0), deltaSlide(0), pitchJump(0),\n * pitchJumpTime(0), repeatTime(0), noise(0), modulation(0), bitCrush(0),\n * delay(0), sustainVolume(1), decay(0), tremolo(0), filter(0).\n * Holes/undefined take the ZzFX defaults, so `[,,1675,,.06,.24,1,1.82,,,837,.06]`\n * pastes straight in.\n */\nexport function specFromZzfx(p: readonly (number | undefined)[]): SoundSpec {\n const volume = p[0] ?? 1;\n const randomness = p[1] ?? 0.05;\n const frequency = p[2] ?? 220;\n const attack = p[3] ?? 0;\n const sustain = p[4] ?? 0;\n const release = p[5] ?? 0.1;\n const shape = p[6] ?? 0;\n const shapeCurve = p[7] ?? 1;\n const slide = p[8] ?? 0;\n const deltaSlide = p[9] ?? 0;\n const pitchJump = p[10] ?? 0;\n const pitchJumpTime = p[11] ?? 0;\n const repeatTime = p[12] ?? 0;\n const noise = p[13] ?? 0;\n const modulation = p[14] ?? 0;\n const bitCrush = p[15] ?? 0;\n const delay = p[16] ?? 0;\n const sustainVolume = p[17] ?? 1;\n const decay = p[18] ?? 0;\n const tremolo = p[19] ?? 0;\n const filter = p[20] ?? 0;\n\n // Both envelopes are attack\u2192decay\u2192sustain\u2192release in seconds; the pitch\n // conversions below normalize per-second ZzFX rates over this body.\n const body = attack + decay + sustain + release;\n\n const spec: SoundSpec = {\n freq: frequency,\n volume,\n attack,\n decay,\n sustain,\n release,\n sustainLevel: sustainVolume,\n };\n\n // Wave shape.\n const shapeIdx = Math.max(0, Math.min(SHAPES.length - 1, Math.round(shape)));\n spec.wave = SHAPES[shapeIdx];\n if (Math.round(shape) === 3) warnOnce('shape=3 (tan)', 'has no hayao wave; approximated as a hard square.');\n if (shapeCurve !== 1) spec.shapeCurve = shapeCurve;\n\n // Randomness: hayao specs are deterministic \u2014 same spec, same samples, same\n // hash. Per-play detune would break golden audio verification. Dropped.\n if (randomness !== 0) warnOnce('randomness', 'is dropped: hayao specs are deterministic (same spec \u2192 same samples).');\n\n // Pitch dynamics (see header for the unit derivations).\n if (slide !== 0) spec.slide = slide * body;\n if (deltaSlide !== 0) spec.slideAccel = (deltaSlide * body * body) / 2;\n if (pitchJump !== 0) {\n const target = frequency + pitchJump;\n if (target > 0 && frequency > 0) {\n spec.pitchJump = 12 * dlog2(target / frequency);\n spec.pitchJumpTime = pitchJumpTime;\n } else {\n warnOnce('pitchJump', 'would drive frequency to \u2264 0 Hz; dropped.');\n }\n }\n if (repeatTime > 0) spec.repeat = repeatTime;\n\n // Timbre.\n if (noise !== 0) spec.noise = Math.max(0, Math.min(1, noise));\n if (modulation !== 0) {\n // ZzFX FM-feedback has no exact hayao analogue; a pitch LFO at the same\n // rate lands in the same perceptual family (warble/ring).\n warnOnce('modulation', 'is approximated as vibrato (pitch LFO at |modulation| Hz).');\n spec.vibrato = 0.6;\n spec.vibratoFreq = Math.abs(modulation);\n }\n // ZzFX holds every bitCrush\u00D7100 samples; hayao's knob is the sample count.\n if (bitCrush > 0) spec.bitCrush = Math.max(1, Math.round(bitCrush * 100));\n if (tremolo !== 0) spec.tremolo = Math.max(0, Math.min(1, tremolo));\n\n // Echo: ZzFX mixes one delayed copy at half gain; a feedback delay at 0.5\n // starts identically and rings out \u2014 close enough not to warn.\n if (delay > 0) {\n spec.delay = delay;\n spec.delayFeedback = 0.5;\n }\n\n // Filter: one signed Hz knob \u2192 the matching one-pole.\n if (filter > 0) spec.lowpass = filter;\n else if (filter < 0) spec.highpass = -filter;\n\n return spec;\n}\n", "// \"Neon Precinct\" \u2014 an original jazz-funk album: the soundtrack to an imaginary\n// neo-noir detective game. You work the night beat in a rain-slicked retro-\n// future city; each cue scores a scene. The tracks share an instrument palette\n// (Rhodes, upright bass, muted trumpet, vibraphone, clav, horns), an extended/\n// altered jazz harmonic language, and a recurring four-note motif that opens the\n// main theme and returns \u2014 resolved \u2014 in the closer.\n//\n// This is authored music, not a generator: real changes, written melodies, and\n// opinionated arrangement. It reuses the engine's chord vocabulary, comping and\n// walking-bass helpers, and the mastering chain.\n\nimport { INSTRUMENTS, type Song, type Note, type Track } from './music';\nimport { chordNotes, rootless } from './chord';\nimport { noteToMidi } from './theory';\n\nconst n = (pitch: Note['pitch'], beats: number, vel = 1): Note => ({ pitch, beats, vel });\nconst rest = (beats: number): Note => ({ pitch: null, beats });\n\n// \u2500\u2500 shared arrangement helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Walking bass: four quarter notes per bar \u2014 root, a chord tone, a chord tone,\n * then a chromatic approach note leaning into the NEXT bar's root. */\nfunction walk(changes: string[], oct = 2): Note[][] {\n return changes.map((sym, i) => {\n const c = chordNotes(sym, oct);\n const root = c[0];\n const third = c[1] ?? root + 3;\n const fifth = c[2] ?? root + 7;\n const nextRoot = chordNotes(changes[(i + 1) % changes.length], oct)[0];\n const approach = nextRoot + (root <= nextRoot ? -1 : 1);\n return [n(root, 1, 0.92), n(third, 1, 0.72), n(fifth, 1, 0.78), n(approach, 1, 0.7)];\n });\n}\n\n/** Rootless comping: one voicing per bar, hit with a syncopated Charleston\n * figure (on 1 and the \"and\" of 2). `target` recenters the voicing. */\nfunction comp(changes: string[], oct = 4, target = 'F4', vel = 0.66): Note[][] {\n const t = noteToMidi(target);\n return changes.map((sym, i) => {\n const v = rootless(chordNotes(sym, oct), t);\n // alternate two comp rhythms so the groove breathes instead of looping:\n // a Charleston (1, & of 2) and a pushed answer (& of 2, & of 3).\n return i % 2 === 0\n ? [n(v, 1, vel), rest(0.5), n(v, 0.5, vel * 0.8), rest(2)]\n : [rest(1.5), n(v, 0.5, vel * 0.85), rest(1), n(v, 0.5, vel * 0.7), rest(0.5)];\n });\n}\n\n/** Sustained-pad comping (for ballads): hold the voicing across the bar. */\nfunction pad(changes: string[], oct = 4, target = 'F4', vel = 0.6): Note[][] {\n const t = noteToMidi(target);\n return changes.map((sym) => [n(rootless(chordNotes(sym, oct), t), 4, vel)]);\n}\n\n/** The jazz ride \"spang-a-lang\": ding, ding-a, ding, ding-a per bar. The off-8ths\n * get swung by renderSong. */\nconst rideBar = (): Note[] => [\n n('C6', 1, 0.55), n('C6', 0.5, 0.35), n('C6', 0.5, 0.5),\n n('C6', 1, 0.55), n('C6', 0.5, 0.35), n('C6', 0.5, 0.5),\n];\n/** Hi-hat foot on 2 and 4. */\nconst hatFoot = (): Note[] => [rest(1), n('C6', 1, 0.5), rest(1), n('C6', 1, 0.5)];\n\nfunction ride(gain = 0.42, bars = 8): Track {\n return { name: 'ride', instrument: INSTRUMENTS.ride, gain, pan: 0.12, patterns: [rideBar()], sequence: Array(bars).fill(0) };\n}\nfunction hats(gain = 0.4, bars = 8): Track {\n return { name: 'hat', instrument: { ...INSTRUMENTS.hat, highpass: 5000, volume: 0.2 }, gain, pan: -0.1, patterns: [hatFoot()], sequence: Array(bars).fill(0) };\n}\n/** A whisper of vinyl/room warmth \u2014 the noir-record patina. Tasteful: a warm,\n * low noise bed, not hiss (vinyl \"works well in jazzy funk\", used sparingly). */\nfunction vinyl(gain = 0.32, bars = 8): Track {\n return { name: 'vinyl', instrument: { wave: 'noise', attack: 0.6, release: 0.6, sustainLevel: 1, volume: 0.03, lowpass: 3000, highpass: 380 }, gain, patterns: [[n('C4', bars * 4, 1)]], sequence: [0] };\n}\n\nexport interface AlbumTrack {\n id: string;\n title: string;\n intent: string;\n make: () => Song;\n}\n\n// \u2500\u2500 1. Neon Precinct (main theme) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Confident medium funk in Bb minor. A swaggering, syncopated head over a hip\n// groove. The four-note motif (F\u2013Gb\u2013Bb\u2013Ab, the \u266D5/\u266D6 colour of the city) is the\n// album's signature.\nconst MOTIF = ['F5', 'Gb5', 'Bb5', 'Ab5'];\nfunction neonPrecinct(): Song {\n const A = ['Bbm9', 'Bbm9', 'Ebm9', 'Ab13', 'Dbmaj7', 'Gm7b5', 'C7alt', 'Fm7'];\n const bassOct = 2;\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.uprightBass, volume: 0.5 }, gain: 0.7,\n patterns: [\n // a funky riff for the vamp bars, walking for the turnaround\n [n('Bb1', 0.75, 0.95), n('Bb1', 0.25, 0.5), rest(0.5), n('Db2', 0.5, 0.7), n('F2', 0.5, 0.75), n('Ab1', 0.5, 0.6), n('Bb1', 1, 0.7)],\n ...walk(A.slice(2), bassOct),\n ],\n sequence: [0, 0, 1, 2, 3, 4, 5, 6],\n };\n const rhodes: Track = {\n name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.32 }, gain: 0.6, pan: -0.18,\n patterns: comp(A, 4, 'Ab4', 0.62),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const lead: Track = {\n name: 'trumpet', instrument: { ...INSTRUMENTS.mutedTrumpet, volume: 0.34 }, gain: 0.62, pan: 0.14,\n patterns: [\n // the motif, stated and answered\n [n(MOTIF[0], 0.5, 0.85), n(MOTIF[1], 0.5, 0.7), n(MOTIF[2], 1, 0.9), n(MOTIF[3], 0.5, 0.75), rest(1.5)],\n [n('F5', 0.5, 0.8), n('Db5', 0.5, 0.7), n('Bb4', 1.5, 0.85), rest(1.5)],\n // the motif restated a 4th down (C\u2013Db\u2013F\u2013Eb) \u2014 the hook recurs\n [n('C5', 0.5, 0.85), n('Db5', 0.5, 0.72), n('F5', 1, 0.9), n('Eb5', 0.5, 0.75), rest(1.5)],\n [n('Db5', 1, 0.8), n('C5', 0.5, 0.7), n('Bb4', 0.5, 0.7), n('Ab4', 2, 0.72)],\n [n('Db5', 0.5, 0.8), n('F5', 0.5, 0.8), n('Ab5', 1.5, 0.85), n('Gb5', 1.5, 0.75)],\n [n('D5', 1, 0.8), n('F5', 1, 0.8), n('Ab5', 1, 0.85), rest(1)], // Gm7b5\n [n('E5', 0.5, 0.85), n('Eb5', 0.5, 0.8), n('Db5', 1, 0.8), n('C5', 2, 0.78)], // C7alt tension\n [n('F5', 1, 0.85), n('Ab5', 1, 0.8), n('C6', 2, 0.9)], // Fm7 landing\n ],\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const kick: Track = { name: 'kick', instrument: { ...INSTRUMENTS.kick, volume: 0.5 }, gain: 0.6, patterns: [[n('Bb1', 1, 0.8), rest(1.5), n('Bb1', 0.5, 0.55), rest(1)]], sequence: Array(8).fill(0) };\n const snare: Track = { name: 'snare', instrument: { ...INSTRUMENTS.snare, volume: 0.3, highpass: 1000 }, gain: 0.5, patterns: [[rest(1), n('D4', 1, 0.7), rest(1), n('D4', 1, 0.75)]], sequence: Array(8).fill(0) };\n return {\n bpm: 100, tracks: [bass, rhodes, lead, kick, snare, ride(0.42), hats(0.35)],\n swing: 0.6, humanize: 0.32, velBrightness: 0.6,\n reverb: { wet: 0.17, roomSize: 0.6, damp: 0.5 }, master: { lowCut: 0.24, presence: 0.14, air: 0.04, compress: 0.45 },\n };\n}\n\n// \u2500\u2500 2. Rain on the Avenue (ballad) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A smoky, slow torch ballad in Eb. Muted trumpet over Rhodes and brushes; a lot\n// of room. Late-night, melancholic, cool.\nfunction rainOnTheAvenue(): Song {\n const A = ['Ebmaj7', 'Cm7', 'Fm7', 'Bb13', 'Gm7', 'C7b9', 'Fm7', 'Bb7alt'];\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.uprightBass, volume: 0.54, release: 0.2 }, gain: 0.74,\n patterns: A.map((sym) => { const r = chordNotes(sym, 2)[0]; return [n(r, 2, 0.85), n(r + 7, 1, 0.6), n(r + 12, 1, 0.55)]; }),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const rhodes: Track = {\n name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.34, release: 0.6 }, gain: 0.62, pan: -0.15,\n patterns: pad(A, 4, 'G4', 0.62),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const lead: Track = {\n name: 'trumpet', instrument: { ...INSTRUMENTS.mutedTrumpet, volume: 0.36, attack: 0.05, vibrato: 0.11 }, gain: 0.62, pan: 0.12,\n patterns: [\n [rest(1), n('G4', 1.5, 0.7), n('Bb4', 1, 0.75), n('G4', 0.5, 0.6)], // Ebmaj7\n [n('Eb4', 2, 0.7), n('G4', 1, 0.65), rest(1)], // Cm7\n [rest(0.5), n('Ab4', 1.5, 0.72), n('C5', 1, 0.75), n('Ab4', 1, 0.62)], // Fm7\n [n('D5', 2.5, 0.78), n('Bb4', 1.5, 0.65)], // Bb13\n [n('Bb4', 1.5, 0.7), n('G4', 1, 0.65), n('D5', 1.5, 0.72)], // Gm7\n [n('Db5', 2, 0.75), n('C5', 1, 0.68), n('Bb4', 1, 0.62)], // C7b9\n [n('Ab4', 2, 0.72), n('F4', 1, 0.62), rest(1)], // Fm7\n [n('Ab4', 1, 0.72), n('Db5', 1, 0.7), n('D5', 2, 0.72)], // Bb7alt \u2192 lands on D (Ebmaj7's 7th)\n ],\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const brush: Track = { name: 'brush', instrument: { ...INSTRUMENTS.snare, volume: 0.12, highpass: 1500, release: 0.16 }, gain: 0.4, patterns: [[rest(1), n('D4', 1, 0.4), rest(1), n('D4', 1, 0.45)]], sequence: Array(8).fill(0) };\n return {\n bpm: 62, tracks: [vinyl(0.3), bass, rhodes, lead, brush, ride(0.24)],\n swing: 0.5, humanize: 0.4, velBrightness: 0.6,\n reverb: { wet: 0.34, roomSize: 0.85, damp: 0.55 }, master: { lowCut: 0.24, presence: 0.16, air: 0.05, compress: 0.65 },\n };\n}\n\n// \u2500\u2500 3. Stakeout (cool tension) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Minimal, nervous cool-jazz in C minor. Walking bass under a sparse vibraphone\n// motif; quiet, unresolved, watchful.\nfunction stakeout(): Song {\n const A = ['Cm9', 'Cm9', 'Fm9', 'Dm7b5', 'G7alt', 'Cm9', 'Ab13', 'G7alt'];\n const bass: Track = { name: 'bass', instrument: { ...INSTRUMENTS.uprightBass, volume: 0.48 }, gain: 0.68, patterns: walk(A, 2), sequence: [0, 1, 2, 3, 4, 5, 6, 7] };\n const vibe: Track = {\n name: 'vibes', instrument: { ...INSTRUMENTS.vibraphone, volume: 0.34 }, gain: 0.6, pan: 0.1,\n patterns: [\n [n('G4', 1, 0.7), rest(1), n('Eb5', 1, 0.65), rest(1)],\n [rest(2), n('D5', 1, 0.68), n('C5', 1, 0.6)],\n [n('Ab4', 1, 0.7), rest(1.5), n('F5', 1.5, 0.6)],\n [n('F4', 1, 0.7), n('Ab4', 1, 0.6), rest(2)], // Dm7b5\n [rest(1), n('B4', 1, 0.72), n('Ab4', 1, 0.6), n('F4', 1, 0.55)], // G7alt\n [n('Eb5', 2, 0.68), n('C5', 2, 0.6)],\n [n('C5', 1, 0.7), n('Gb5', 1, 0.68), rest(2)], // Ab13 colour\n [n('B4', 1, 0.7), n('Db5', 1, 0.62), n('Ab4', 2, 0.58)], // G7alt \u2014 left hanging on the b9, unresolved\n ],\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const comping: Track = { name: 'guitar', instrument: { ...INSTRUMENTS.jazzGuitar, volume: 0.22 }, gain: 0.5, pan: -0.2, patterns: comp(A, 4, 'Eb4', 0.5), sequence: [0, 1, 2, 3, 4, 5, 6, 7] };\n return {\n bpm: 96, tracks: [vinyl(0.28), bass, comping, vibe, ride(0.3), hats(0.28)],\n swing: 0.62, humanize: 0.34, velBrightness: 0.6,\n reverb: { wet: 0.22, roomSize: 0.65, damp: 0.5 }, master: { lowCut: 0.24, presence: 0.13, air: 0.04, compress: 0.45 },\n };\n}\n\n// \u2500\u2500 4. The Chase (driving funk) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Fast, aggressive F-minor funk. A clav riff, horn stabs, busy drums, a hard\n// sidechain pump. The action cue.\nfunction theChase(): Song {\n // changes: | Fm7 | Fm7 | Bbm7 | C7#9 | (horns spell them below)\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.bass, volume: 0.52, lowpass: 1000, sub: 0.35 }, gain: 0.75,\n patterns: [\n [n('F1', 0.5, 0.95), n('F1', 0.5, 0.6), rest(0.5), n('F1', 0.5, 0.7), n('Ab1', 0.5, 0.7), n('C2', 0.5, 0.7), n('F1', 0.5, 0.65), n('Eb2', 0.5, 0.7)],\n [n('Bb1', 0.5, 0.9), n('Bb1', 0.5, 0.6), rest(0.5), n('Bb1', 0.5, 0.7), n('Db2', 0.5, 0.7), n('F2', 0.5, 0.7), n('Bb1', 1, 0.65)],\n [n('C2', 0.5, 0.9), n('C2', 0.5, 0.6), n('Eb2', 0.5, 0.7), n('D2', 0.5, 0.7), n('C2', 0.5, 0.7), n('Bb1', 0.5, 0.7), n('G1', 1, 0.7)],\n ],\n sequence: [0, 0, 1, 2],\n };\n const clav: Track = {\n name: 'clav', instrument: { ...INSTRUMENTS.clav, volume: 0.3, lowpass: 2700 }, gain: 0.55, pan: -0.16,\n patterns: [\n [n('F4', 0.25, 0.8), rest(0.25), n('Ab4', 0.25, 0.6), rest(0.25), n('F4', 0.25, 0.7), n('C5', 0.25, 0.6), rest(0.5), n('Eb5', 0.5, 0.7), rest(1)],\n [n('Bb3', 0.25, 0.8), rest(0.25), n('Db4', 0.25, 0.6), rest(0.25), n('F4', 0.5, 0.7), rest(0.5), n('Bb4', 0.5, 0.65), rest(1)],\n [n('C4', 0.25, 0.8), n('Eb4', 0.25, 0.6), n('G4', 0.5, 0.7), rest(0.5), n('C5', 0.5, 0.7), n('Bb4', 0.5, 0.65), rest(1)],\n ],\n sequence: [0, 0, 1, 2],\n };\n const hstab = (sym: string) => rootless(chordNotes(sym, 4), noteToMidi('C5'));\n const horns: Track = {\n name: 'horns', instrument: { ...INSTRUMENTS.horns, volume: 0.26 }, gain: 0.55, pan: 0.15,\n patterns: [\n // punchy: hit the & of 2 and an & of 4 pickup that drives into the next bar\n [rest(1.5), n(hstab('Fm7'), 0.5, 0.8), rest(1.5), n(hstab('Fm7'), 0.5, 0.9)],\n [rest(1.5), n(hstab('Fm7'), 0.5, 0.8), rest(1.5), n(hstab('Bbm7'), 0.5, 0.9)],\n [rest(2), n(hstab('Bbm7'), 0.5, 0.82), rest(1), n(hstab('Bbm7'), 0.5, 0.88)],\n [n(hstab('C7#9'), 0.5, 0.92), rest(1), n(hstab('C7#9'), 0.5, 0.82), rest(1), n(hstab('C7#9'), 0.5, 0.9)],\n ],\n sequence: [0, 1, 2, 3],\n };\n const kick: Track = { name: 'kick', instrument: INSTRUMENTS.kick, gain: 0.85, patterns: [[n('F1', 1, 0.95), n('F1', 0.5, 0.6), rest(0.5), n('F1', 0.5, 0.7), rest(0.5), n('F1', 1, 0.8)]], sequence: Array(4).fill(0) };\n const snare: Track = { name: 'snare', instrument: { ...INSTRUMENTS.snare, volume: 0.42 }, gain: 0.6, patterns: [[rest(1), n('D4', 1, 0.85), rest(1), n('D4', 1, 0.9)]], sequence: Array(4).fill(0) };\n const hat: Track = { name: 'hat', instrument: { ...INSTRUMENTS.hat, volume: 0.18, highpass: 5000, lowpass: 9000 }, gain: 0.38, pan: 0.1, patterns: [[n('C6', 0.5, 0.6), n('C6', 0.5, 0.35)]], sequence: Array(8).fill(0) };\n return {\n bpm: 128, tracks: [kick, bass, clav, horns, snare, hat],\n humanize: 0.14, velBrightness: 0.55,\n sidechain: { depth: 0.5, beatsPerCycle: 1 },\n reverb: { wet: 0.12, roomSize: 0.5, damp: 0.5 }, master: { lowCut: 0.3, presence: 0.16, air: 0.05, compress: 0.4 },\n };\n}\n\n// \u2500\u2500 5. Smoke & Mirrors (slinky noir) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Half-time, sultry, ambiguous. Ab tonal centre with altered colours. Vibraphone\n// and muted trumpet trade a slinky line over a laid-back groove.\nfunction smokeAndMirrors(): Song {\n const A = ['Abmaj7#11', 'Db9', 'Bbm7', 'Eb7alt', 'Cm7', 'F7b9', 'Bbm7', 'Eb13'];\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.uprightBass, volume: 0.5, sub: 0.4 }, gain: 0.72,\n patterns: A.map((sym, i) => {\n const r = chordNotes(sym, 2)[0];\n const nextR = chordNotes(A[(i + 1) % A.length], 2)[0];\n const approach = nextR + (r <= nextR ? -1 : 1); // chromatic lead-in to the next root\n return [n(r, 1.5, 0.9), rest(0.5), n(r + 7, 1, 0.62), n(approach, 1, 0.62)];\n }),\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const rhodes: Track = { name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.28 }, gain: 0.55, pan: -0.18, patterns: comp(A, 4, 'Ab4', 0.6), sequence: [0, 1, 2, 3, 4, 5, 6, 7] };\n const vibe: Track = {\n name: 'vibes', instrument: { ...INSTRUMENTS.vibraphone, volume: 0.3 }, gain: 0.55, pan: 0.18,\n patterns: [\n [rest(1), n('C5', 1, 0.7), n('D5', 1, 0.65), n('Eb5', 1, 0.62)], // maj7#11 colour (D=#11)\n [n('F5', 2, 0.7), n('Eb5', 1, 0.62), n('C5', 1, 0.58)],\n [n('Db5', 1.5, 0.7), n('F5', 1.5, 0.65), n('Ab5', 1, 0.62)],\n [n('G5', 1, 0.72), n('Gb5', 1, 0.66), n('Db5', 2, 0.6)], // Eb7alt\n [rest(1), n('Eb5', 1.5, 0.68), n('G5', 1.5, 0.62)],\n [n('Ab5', 1, 0.72), n('Gb5', 1, 0.66), n('F5', 2, 0.6)], // F7b9\n [n('Db5', 2, 0.68), n('Bb4', 2, 0.6)],\n [n('C5', 1, 0.7), n('G5', 1, 0.66), n('Eb5', 2, 0.6)],\n ],\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const kick: Track = { name: 'kick', instrument: { ...INSTRUMENTS.kick, volume: 0.55 }, gain: 0.62, patterns: [[n('Ab1', 1, 0.85), rest(2), n('Ab1', 0.5, 0.55), rest(0.5)]], sequence: Array(8).fill(0) };\n const snare: Track = { name: 'snare', instrument: { ...INSTRUMENTS.rimshot, volume: 0.22 }, gain: 0.5, patterns: [[rest(2), n('D4', 1, 0.7), rest(1)]], sequence: Array(8).fill(0) };\n return {\n bpm: 84, tracks: [vinyl(0.32), bass, rhodes, vibe, kick, snare, ride(0.28), hats(0.24)],\n swing: 0.56, humanize: 0.3, velBrightness: 0.62,\n reverb: { wet: 0.26, roomSize: 0.72, damp: 0.55 }, master: { lowCut: 0.24, presence: 0.14, air: 0.04, compress: 0.45 },\n };\n}\n\n// \u2500\u2500 6. Last Call (warm closer) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Bittersweet resolution in C major. A ii\u2013V\u2013I that finally lands, reprising the\n// main-theme motif transposed and resolved. Rhodes-led, warm, the credits roll.\nfunction lastCall(): Song {\n const A = ['Dm7', 'G13', 'Cmaj9', 'A7b9', 'Dm7', 'G7', 'Cmaj9', 'Cmaj9'];\n const bass: Track = {\n name: 'bass', instrument: { ...INSTRUMENTS.uprightBass, volume: 0.5 }, gain: 0.66,\n patterns: walk(A, 2), sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const rhodes: Track = { name: 'rhodes', instrument: { ...INSTRUMENTS.rhodes, volume: 0.32, release: 0.5 }, gain: 0.6, pan: -0.14, patterns: comp(A, 4, 'E4', 0.6), sequence: [0, 1, 2, 3, 4, 5, 6, 7] };\n const lead: Track = {\n name: 'trumpet', instrument: { ...INSTRUMENTS.mutedTrumpet, volume: 0.36, vibrato: 0.1 }, gain: 0.62, pan: 0.12,\n patterns: [\n [rest(1), n('A4', 1, 0.72), n('C5', 1, 0.75), n('D5', 1, 0.7)], // Dm7\n [n('B4', 2, 0.75), n('G4', 1, 0.65), n('F4', 1, 0.6)], // G13\n [n('E5', 2, 0.78), n('G4', 1, 0.62), n('E4', 1, 0.6)], // Cmaj9 \u2014 arrival\n [n('C5', 1, 0.72), n('Bb4', 1, 0.68), n('A4', 1, 0.65), n('D5', 1, 0.62)], // A7b9 \u2192 resolves A up to D (into Dm7)\n // the motif reprised in C major, resolved (was F\u2013Gb\u2013Bb\u2013Ab; now G\u2013A\u2013C\u2013B \u2192 resolves up)\n [n('G4', 0.5, 0.78), n('A4', 0.5, 0.72), n('C5', 1, 0.82), n('B4', 0.5, 0.7), rest(1.5)],\n [n('D5', 1, 0.75), n('B4', 1, 0.68), n('G4', 2, 0.62)], // G7\n [n('E5', 2, 0.8), n('C5', 2, 0.72)], // Cmaj9\n [n('E4', 4, 0.6)], // long resolved tonic\n ],\n sequence: [0, 1, 2, 3, 4, 5, 6, 7],\n };\n const brush: Track = { name: 'brush', instrument: { ...INSTRUMENTS.snare, volume: 0.12, highpass: 1500, release: 0.15 }, gain: 0.42, patterns: [[rest(1), n('D4', 1, 0.42), rest(1), n('D4', 1, 0.46)]], sequence: Array(8).fill(0) };\n return {\n bpm: 76, tracks: [vinyl(0.3), bass, rhodes, lead, brush, ride(0.26)],\n swing: 0.56, humanize: 0.36, velBrightness: 0.6,\n reverb: { wet: 0.3, roomSize: 0.8, damp: 0.5 }, master: { lowCut: 0.38, presence: 0.28, air: 0.09, compress: 0.65 },\n };\n}\n\n/** The album. */\nexport const ALBUM = {\n title: 'Neon Precinct',\n subtitle: 'Original Soundtrack',\n concept:\n 'The score to an imaginary neo-noir detective game. You work the night beat in a rain-slicked ' +\n 'retro-future city \u2014 jazz-funk with a noir heart. Six cues, one motif, a long night.',\n tracks: [\n { id: 'neon-precinct', title: 'Neon Precinct', intent: 'Main theme \u2014 swaggering medium funk, the city announcing itself.', make: neonPrecinct },\n { id: 'rain-avenue', title: 'Rain on the Avenue', intent: 'A smoky, slow torch ballad. Muted trumpet in the rain.', make: rainOnTheAvenue },\n { id: 'stakeout', title: 'Stakeout', intent: 'Minimal, nervous cool-jazz. Watching, waiting, unresolved.', make: stakeout },\n { id: 'the-chase', title: 'The Chase', intent: 'Driving F-minor funk \u2014 clav, horn stabs, a hard pulse.', make: theChase },\n { id: 'smoke-mirrors', title: 'Smoke & Mirrors', intent: 'Slinky half-time noir; altered colours, nothing as it seems.', make: smokeAndMirrors },\n { id: 'last-call', title: 'Last Call', intent: 'The warm closer \u2014 a ii\u2013V\u2013I that finally lands, the motif resolved.', make: lastCall },\n ] as AlbumTrack[],\n};\n\n/** Look up an album track by id. */\nexport function albumTrack(id: string): AlbumTrack | undefined {\n return ALBUM.tracks.find((t) => t.id === id);\n}\n", "// DOM overlay screens \u2014 titles, menus, game-over, HUD. Crisp DOM type instead of\n// canvas text (narrow-js lesson: humans compare canvas text to DOM and canvas\n// loses). Keyboard-navigable by construction. Browser-only; no-op guards for SSR.\n\nexport interface MenuAction {\n label: string;\n onSelect: () => void;\n primary?: boolean;\n}\n\nexport interface ScreenSpec {\n title?: string;\n /** Subtitle / body text (plain text or HTML string). */\n body?: string;\n /** Menu actions, navigable with up/down + Enter. */\n actions?: MenuAction[];\n /** Dim the game behind the screen. */\n dim?: boolean;\n /** Extra class for theming. */\n className?: string;\n}\n\nexport interface ScreenHandle {\n close(): void;\n readonly element: HTMLElement;\n}\n\nlet active: ScreenHandle | null = null;\n\nconst STYLE_ID = 'hayao-overlay-style';\nconst CSS = `\n.hy-scrim{position:absolute;inset:0;display:grid;place-items:center;z-index:50;font-family:var(--hy-serif,Georgia,serif)}\n.hy-scrim.dim{background:rgba(30,24,14,.5);backdrop-filter:blur(2px)}\n.hy-card{background:var(--hy-paper,#fbf6ea);color:var(--hy-ink,#3d3323);border:1px solid var(--hy-line,#d9ccae);border-radius:14px;box-shadow:0 14px 44px rgba(40,30,15,.3);padding:26px 30px;max-width:440px;text-align:center}\n.hy-card h1{margin:0 0 6px;font-size:30px}\n.hy-card .hy-body{color:var(--hy-ink-soft,#6f6047);font-size:15px;line-height:1.5;margin-bottom:18px}\n.hy-menu{display:flex;flex-direction:column;gap:8px;align-items:stretch}\n.hy-item{font:inherit;font-size:16px;padding:9px 16px;border-radius:9px;border:1px solid var(--hy-line,#d9ccae);background:transparent;color:inherit;cursor:pointer;transition:transform .1s,background .1s}\n.hy-item:hover,.hy-item.sel{background:var(--hy-accent,#a11d3a);color:#fdf3ee;border-color:transparent;transform:translateY(-1px)}\n.hy-item.primary{background:var(--hy-accent,#a11d3a);color:#fdf3ee;border-color:transparent}\n`;\n\nfunction ensureStyle(): void {\n if (typeof document === 'undefined' || document.getElementById(STYLE_ID)) return;\n const s = document.createElement('style');\n s.id = STYLE_ID;\n s.textContent = CSS;\n document.head.appendChild(s);\n}\n\nlet host: HTMLElement | null = null;\n/** Set the element overlays mount into (defaults to document.body). */\nexport function setOverlayHost(el: HTMLElement): void {\n host = el;\n}\n\nlet screenObserver: ((kind: 'show' | 'hide', title?: string) => void) | null = null;\n/**\n * Observe DOM screen chrome (menus/title/game-over) opening and closing \u2014\n * Studio's session recorder uses this to time menu dwell, which the sim can't\n * see. Observer only; it must never mutate.\n */\nexport function setScreenObserver(cb: ((kind: 'show' | 'hide', title?: string) => void) | null): void {\n screenObserver = cb;\n}\n\n/** Show a screen (replaces any current one). Returns a handle. */\nexport function showScreen(spec: ScreenSpec): ScreenHandle {\n if (typeof document === 'undefined') {\n return { close() {}, element: null as unknown as HTMLElement };\n }\n ensureStyle();\n hideScreen();\n screenObserver?.('show', spec.title);\n\n const scrim = document.createElement('div');\n scrim.className = `hy-scrim${spec.dim === false ? '' : ' dim'}${spec.className ? ' ' + spec.className : ''}`;\n const card = document.createElement('div');\n card.className = 'hy-card';\n\n if (spec.title) {\n const h = document.createElement('h1');\n h.textContent = spec.title;\n card.appendChild(h);\n }\n if (spec.body) {\n const b = document.createElement('div');\n b.className = 'hy-body';\n b.innerHTML = spec.body;\n card.appendChild(b);\n }\n\n const actions = spec.actions ?? [];\n let sel = Math.max(0, actions.findIndex((a) => a.primary));\n if (sel < 0) sel = 0;\n const items: HTMLButtonElement[] = [];\n if (actions.length) {\n const menu = document.createElement('div');\n menu.className = 'hy-menu';\n actions.forEach((a, i) => {\n const btn = document.createElement('button');\n btn.className = `hy-item${a.primary ? ' primary' : ''}`;\n btn.textContent = a.label;\n btn.addEventListener('click', () => a.onSelect());\n btn.addEventListener('mouseenter', () => setSel(i));\n menu.appendChild(btn);\n items.push(btn);\n });\n card.appendChild(menu);\n }\n\n function setSel(i: number): void {\n sel = (i + items.length) % items.length;\n items.forEach((el, k) => el.classList.toggle('sel', k === sel));\n }\n if (items.length) setSel(sel);\n\n const onKey = (e: KeyboardEvent) => {\n if (!items.length) return;\n if (e.code === 'ArrowDown') { setSel(sel + 1); e.preventDefault(); }\n else if (e.code === 'ArrowUp') { setSel(sel - 1); e.preventDefault(); }\n else if (e.code === 'Enter' || e.code === 'Space') { actions[sel]?.onSelect(); e.preventDefault(); }\n };\n document.addEventListener('keydown', onKey);\n\n scrim.appendChild(card);\n (host ?? document.body).appendChild(scrim);\n\n const handle: ScreenHandle = {\n element: scrim,\n close() {\n document.removeEventListener('keydown', onKey);\n scrim.remove();\n if (active === handle) {\n active = null;\n screenObserver?.('hide', spec.title);\n }\n },\n };\n active = handle;\n return handle;\n}\n\nexport function hideScreen(): void {\n active?.close();\n}\n", "// Player settings, persisted to localStorage and pushed into the audio bus.\n// Framework-agnostic (plain object + subscribe), so any game/UI can bind to it.\n\nimport { audio } from '../audio/audio';\n\nexport interface Settings {\n master: number;\n music: number;\n sfx: number;\n muted: boolean;\n colorblind: boolean;\n reducedMotion: boolean;\n}\n\nconst KEY = 'hayao.settings.v1';\nconst DEFAULTS: Settings = { master: 0.7, music: 0.6, sfx: 0.8, muted: false, colorblind: false, reducedMotion: false };\n\ntype Sub = (s: Settings) => void;\n\nclass SettingsStore {\n private state: Settings;\n private subs = new Set<Sub>();\n\n constructor() {\n this.state = this.load();\n this.pushToAudio();\n }\n\n get(): Settings {\n return { ...this.state };\n }\n\n set(patch: Partial<Settings>): void {\n this.state = { ...this.state, ...patch };\n this.save();\n this.pushToAudio();\n for (const fn of this.subs) fn(this.get());\n }\n\n subscribe(fn: Sub): () => void {\n this.subs.add(fn);\n return () => this.subs.delete(fn);\n }\n\n private pushToAudio(): void {\n audio.setVolumes({ master: this.state.master, music: this.state.music, sfx: this.state.sfx, muted: this.state.muted });\n }\n\n private load(): Settings {\n try {\n const raw = typeof localStorage !== 'undefined' && localStorage.getItem(KEY);\n if (raw) return { ...DEFAULTS, ...JSON.parse(raw) };\n } catch {\n /* ignore */\n }\n return { ...DEFAULTS };\n }\n private save(): void {\n try {\n localStorage.setItem(KEY, JSON.stringify(this.state));\n } catch {\n /* ignore */\n }\n }\n}\n\nexport const settings = new SettingsStore();\n\n// \u2500\u2500 Fullscreen helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport function toggleFullscreen(): void {\n if (typeof document === 'undefined') return;\n const doc = document as Document & { webkitFullscreenElement?: Element; webkitExitFullscreen?: () => void };\n const el = document.documentElement as HTMLElement & { webkitRequestFullscreen?: () => void };\n if (document.fullscreenElement || doc.webkitFullscreenElement) {\n (document.exitFullscreen ?? doc.webkitExitFullscreen)?.call(document);\n } else {\n (el.requestFullscreen ?? el.webkitRequestFullscreen)?.call(el);\n }\n}\n", "// The game shell: a pause menu (Esc) with volume, mute, fullscreen, restart, and\n// back-to-hub \u2014 every game gets it for free (narrow-js lesson: the shell owns Esc,\n// kills debug-key landmines, and standardizes chrome). Browser-only.\n\nimport { audio } from '../audio/audio';\nimport { settings, toggleFullscreen } from './settings';\nimport { showScreen, hideScreen } from './overlay';\n\nexport interface ShellOptions {\n onRestart?: () => void;\n onQuit?: () => void;\n /** Called with true when paused, false when resumed. */\n onPause?: (paused: boolean) => void;\n title?: string;\n}\n\nexport class Shell {\n private paused = false;\n private opts: ShellOptions;\n private keyHandler: (e: KeyboardEvent) => void;\n\n constructor(opts: ShellOptions = {}) {\n this.opts = opts;\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.code === 'Escape') {\n e.preventDefault();\n this.toggle();\n }\n };\n if (typeof document !== 'undefined') document.addEventListener('keydown', this.keyHandler);\n }\n\n get isPaused(): boolean {\n return this.paused;\n }\n\n toggle(): void {\n this.paused ? this.resume() : this.pause();\n }\n\n pause(): void {\n if (this.paused) return;\n this.paused = true;\n audio.blip(440);\n this.opts.onPause?.(true);\n this.render();\n }\n\n resume(): void {\n if (!this.paused) return;\n this.paused = false;\n hideScreen();\n this.opts.onPause?.(false);\n }\n\n private render(): void {\n const s = settings.get();\n const vol = (label: string, v: number) => `${label}: ${Math.round(v * 100)}`;\n showScreen({\n title: this.opts.title ?? 'Paused',\n body:\n `<div style=\"font-size:13px;text-align:left;line-height:1.9\">` +\n `${vol('Master', s.master)} \u00B7 ${vol('Music', s.music)} \u00B7 ${vol('Sfx', s.sfx)}` +\n `<br/><span style=\"opacity:.7\">Use the menu, or keys: M mute \u00B7 F fullscreen</span></div>`,\n actions: [\n { label: 'Resume', primary: true, onSelect: () => this.resume() },\n { label: s.muted ? 'Unmute (M)' : 'Mute (M)', onSelect: () => { settings.set({ muted: !settings.get().muted }); this.render(); } },\n { label: 'Music \u2212/+', onSelect: () => { const m = Math.min(1, settings.get().music + 0.1) % 1.05; settings.set({ music: m > 1 ? 0 : m }); this.render(); } },\n { label: 'Fullscreen (F)', onSelect: () => toggleFullscreen() },\n ...(this.opts.onRestart ? [{ label: 'Restart', onSelect: () => { this.resume(); this.opts.onRestart!(); } }] : []),\n ...(this.opts.onQuit ? [{ label: 'Quit', onSelect: () => { this.resume(); this.opts.onQuit!(); } }] : []),\n ],\n });\n }\n\n dispose(): void {\n if (typeof document !== 'undefined') document.removeEventListener('keydown', this.keyHandler);\n hideScreen();\n }\n}\n", "// TouchControls \u2014 an opt-in virtual gamepad for touch play, sibling to Shell.\n// runBrowser games take keyboard + single pointer; on a phone a keyboard game is\n// unplayable until ~120 lines of host glue exist. This renders floating sticks /\n// buttons over the letterbox and drives the SAME deterministic action set as\n// keys, via `KeyboardSource.setHeld` \u2014 so it needs NO per-frame pump: a control\n// sets held-state on touch and clears it on release, and the engine samples it\n// each fixed step. Each stick/button owns its own pointerId, so two thumbs work\n// at once (dual-stick). Host UI, matching \"menus/HUD are DOM overlays\".\n\nimport type { GameHandle } from '../app/browser';\nimport { snapAxis, quantizeAngle } from '../input/actions';\nimport { datan2, dhypot } from '../core/dmath';\n\n/** A virtual stick. Give it 4 directional actions, and/or an analog axis prefix. */\nexport interface TouchStick {\n /** Directional actions held while tilted past the deadzone. Array = [up,down,left,right]. */\n dirs?: [string, string, string, string] | { up: string; down: string; left: string; right: string };\n /**\n * Emit live analog axes `${prefix}x`, `${prefix}y` (\u22121..1) and `${prefix}angle`\n * (radians), quantized to `buckets`. NOTE: these are LIVE axes (feel), not part\n * of the input log \u2014 for replay-exact analog aim, thread them through\n * `world.step(actions, axes)` (see docs/CONVENTIONS.md \u00A7Pointer).\n */\n prefix?: string;\n /** Axis quantization levels (default 32). */\n buckets?: number;\n /** Dead-zone as a fraction of the stick radius, 0..1 (default 0.28). */\n deadzone?: number;\n}\n\nexport interface TouchButton {\n action: string;\n /** Glyph/label drawn on the button (default the action name). */\n label?: string;\n /** Hold the action while pressed (default true); false = one-shot tap via press(). */\n hold?: boolean;\n}\n\nexport interface TouchControlsLayout {\n /** Left-corner stick (movement). Array shorthand \u2192 [up,down,left,right]. */\n left?: TouchStick | [string, string, string, string];\n /** Right-corner stick (aim). */\n right?: TouchStick | [string, string, string, string];\n /** Action buttons, stacked at the lower-right. */\n buttons?: TouchButton[];\n /** Only mount when the device has a coarse (touch) pointer (default true). */\n touchOnly?: boolean;\n}\n\nconst STYLE_ID = 'hayao-touch-style';\nconst CSS = `\n.hy-touch{position:absolute;inset:0;z-index:40;pointer-events:none;touch-action:none;-webkit-user-select:none;user-select:none}\n.hy-stick{position:absolute;bottom:6%;width:120px;height:120px;border-radius:50%;pointer-events:auto;background:rgba(20,16,10,.16);border:2px solid rgba(250,244,230,.35);box-shadow:inset 0 0 20px rgba(0,0,0,.12)}\n.hy-stick.left{left:5%}\n.hy-stick.right{right:5%}\n.hy-knob{position:absolute;left:50%;top:50%;width:52px;height:52px;margin:-26px 0 0 -26px;border-radius:50%;background:rgba(250,244,230,.6);border:2px solid rgba(20,16,10,.25);transition:transform .04s linear}\n.hy-btns{position:absolute;right:5%;bottom:26%;display:flex;flex-direction:column-reverse;gap:12px;pointer-events:none}\n.hy-btn{pointer-events:auto;width:66px;height:66px;border-radius:50%;font:600 15px/1 var(--hy-serif,Georgia,serif);color:#fbf6ea;background:var(--hy-accent,#a11d3a);border:2px solid rgba(250,244,230,.4);box-shadow:0 4px 12px rgba(30,20,10,.3);display:grid;place-items:center;text-transform:capitalize}\n.hy-btn:active,.hy-btn.on{transform:translateY(2px);filter:brightness(1.15)}\n`;\n\nfunction ensureStyle(): void {\n if (typeof document === 'undefined' || document.getElementById(STYLE_ID)) return;\n const s = document.createElement('style');\n s.id = STYLE_ID;\n s.textContent = CSS;\n document.head.appendChild(s);\n}\n\nfunction normDirs(s: TouchStick): { up: string; down: string; left: string; right: string } | undefined {\n if (!s.dirs) return undefined;\n return Array.isArray(s.dirs) ? { up: s.dirs[0], down: s.dirs[1], left: s.dirs[2], right: s.dirs[3] } : s.dirs;\n}\n\nexport class TouchControls {\n private handle: GameHandle;\n private root: HTMLElement;\n private disposers: Array<() => void> = [];\n /** Every action this control set can hold \u2014 released together on dispose/reset. */\n private owned = new Set<string>();\n\n constructor(handle: GameHandle, layout: TouchControlsLayout) {\n this.handle = handle;\n ensureStyle();\n const coarse = typeof matchMedia !== 'undefined' && matchMedia('(pointer: coarse)').matches;\n const mount = (handle.canvas?.parentElement as HTMLElement | null) ?? undefined;\n this.root = document.createElement('div');\n this.root.className = 'hy-touch';\n // Mount but stay invisible on non-touch devices unless explicitly forced.\n if (mount && (layout.touchOnly === false || coarse)) mount.appendChild(this.root);\n\n const left = normStick(layout.left);\n const right = normStick(layout.right);\n if (left) this.addStick('left', left);\n if (right) this.addStick('right', right);\n if (layout.buttons?.length) this.addButtons(layout.buttons);\n }\n\n private addStick(side: 'left' | 'right', spec: TouchStick): void {\n const base = document.createElement('div');\n base.className = `hy-stick ${side}`;\n const knob = document.createElement('div');\n knob.className = 'hy-knob';\n base.appendChild(knob);\n this.root.appendChild(base);\n\n const dirs = normDirs(spec);\n const prefix = spec.prefix;\n const buckets = spec.buckets ?? 32;\n const dead = spec.deadzone ?? 0.28;\n let activeId: number | null = null;\n\n const setAxes = (nx: number, ny: number) => {\n if (!prefix) return;\n const axes = this.handle.world.input.axes;\n axes.set(`${prefix}x`, snapAxis(nx, buckets));\n axes.set(`${prefix}y`, snapAxis(ny, buckets));\n axes.set(`${prefix}angle`, nx === 0 && ny === 0 ? 0 : quantizeAngle(datan2(ny, nx), buckets));\n };\n const release = () => {\n if (dirs) for (const a of [dirs.up, dirs.down, dirs.left, dirs.right]) this.hold(a, false);\n setAxes(0, 0);\n knob.style.transform = 'translate(0,0)';\n activeId = null;\n };\n const apply = (clientX: number, clientY: number) => {\n const r = base.getBoundingClientRect();\n const rad = r.width / 2;\n let dx = (clientX - (r.left + rad)) / rad;\n let dy = (clientY - (r.top + rad)) / rad;\n const m = dhypot(dx, dy);\n if (m > 1) { dx /= m; dy /= m; }\n knob.style.transform = `translate(${dx * rad * 0.6}px,${dy * rad * 0.6}px)`;\n const mag = dhypot(dx, dy);\n if (dirs) {\n this.hold(dirs.left, dx < -dead);\n this.hold(dirs.right, dx > dead);\n this.hold(dirs.up, dy < -dead);\n this.hold(dirs.down, dy > dead);\n }\n setAxes(mag < dead ? 0 : dx, mag < dead ? 0 : dy);\n };\n\n const onDown = (e: PointerEvent) => {\n if (activeId !== null) return;\n activeId = e.pointerId;\n base.setPointerCapture?.(e.pointerId);\n apply(e.clientX, e.clientY);\n e.preventDefault();\n };\n const onMove = (e: PointerEvent) => { if (e.pointerId === activeId) apply(e.clientX, e.clientY); };\n const onUp = (e: PointerEvent) => { if (e.pointerId === activeId) release(); };\n base.addEventListener('pointerdown', onDown as EventListener);\n base.addEventListener('pointermove', onMove as EventListener);\n base.addEventListener('pointerup', onUp as EventListener);\n base.addEventListener('pointercancel', onUp as EventListener);\n this.disposers.push(() => {\n release();\n base.remove();\n });\n }\n\n private addButtons(buttons: TouchButton[]): void {\n const wrap = document.createElement('div');\n wrap.className = 'hy-btns';\n this.root.appendChild(wrap);\n for (const b of buttons) {\n const el = document.createElement('button');\n el.className = 'hy-btn';\n el.textContent = b.label ?? b.action;\n wrap.appendChild(el);\n const hold = b.hold ?? true;\n const down = (e: PointerEvent) => {\n el.classList.add('on');\n if (hold) this.hold(b.action, true);\n else this.handle.input.press(b.action);\n el.setPointerCapture?.(e.pointerId);\n e.preventDefault();\n };\n const up = () => {\n el.classList.remove('on');\n if (hold) this.hold(b.action, false);\n };\n el.addEventListener('pointerdown', down as EventListener);\n el.addEventListener('pointerup', up as EventListener);\n el.addEventListener('pointercancel', up as EventListener);\n this.disposers.push(() => {\n up();\n el.remove();\n });\n }\n this.disposers.push(() => wrap.remove());\n }\n\n private hold(action: string, on: boolean): void {\n this.handle.input.setHeld(action, on);\n if (on) this.owned.add(action);\n }\n\n dispose(): void {\n for (const d of this.disposers.splice(0)) d();\n for (const a of this.owned) this.handle.input.setHeld(a, false);\n this.owned.clear();\n this.root.remove();\n }\n}\n\nfunction normStick(s: TouchStick | [string, string, string, string] | undefined): TouchStick | undefined {\n if (!s) return undefined;\n return Array.isArray(s) ? { dirs: s } : s;\n}\n", "// Screen transitions + a cinematic sequencer \u2014 the layer between showScreen()\n// (a static DOM dialog) and a scripted, animated scene change.\n//\n// Transition is a COSMETIC scene node that paints a full-screen wipe (fade /\n// iris / dither) in SCREEN space, so it sits on top of the camera untouched. It\n// runs on the fixed clock dt \u2014 not rAF delta \u2014 so a lockstep replay wipes\n// identically, and because it draws through the display list it renders headless\n// (a filmstrip can prove it). The classic move is cover \u2192 onMidpoint (swap the\n// level) \u2192 reveal, all gated off `busy`.\n//\n// CinematicPlayer walks a list of pure-data steps: each step runs an `enter`\n// hook (aim the camera, set text, mutate state) then holds until its duration\n// elapses AND its `until` gate passes \u2014 which is how you fade-gate advancement\n// (step waits on `!transition.busy`). Also cosmetic and dt-driven.\n\nimport { clamp, lerp, type Rect, type Transform, IDENTITY } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { Node, type NodeConfig } from '../scene/node';\n\nexport type WipeKind = 'fade' | 'circle' | 'dither';\n\n// Ordered 4\u00D74 Bayer matrix (thresholds 0..15) for the dither dissolve.\nconst BAYER4 = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];\nconst smoothstep = (t: number): number => t * t * (3 - 2 * t);\n\ninterface Ramp {\n from: number | undefined; // resolved to current coverage when the ramp starts\n to: number;\n dur: number;\n elapsed: number;\n onEnd?: () => void;\n}\n\nexport interface WipeOptions {\n /** Seconds to cover the screen (default 0.4). */\n cover?: number;\n /** Seconds to hold fully covered before revealing (default 0). */\n hold?: number;\n /** Seconds to reveal the scene again (default = cover). */\n reveal?: number;\n /** Fired at full cover \u2014 swap the level/scene here. */\n onMidpoint?: () => void;\n /** Fired once the reveal finishes. */\n onDone?: () => void;\n}\n\nexport interface TransitionConfig extends NodeConfig {\n kind?: WipeKind;\n /** Overlay colour. */\n color?: string;\n /** Screen size in px (pass world.width / world.height). */\n width?: number;\n height?: number;\n /** Dither cell size in px (default 28). */\n cell?: number;\n}\n\n/**\n * A full-screen wipe overlay. Add it to the tree (cosmetic), then drive it with\n * `cover()` / `reveal()` / `wipe()`. `coverage` runs 0 (clear) \u2192 1 (opaque).\n */\nexport class ScreenTransition extends Node {\n override readonly type: string = 'ScreenTransition';\n kind: WipeKind;\n color: string;\n screenW: number;\n screenH: number;\n cell: number;\n /** 0 = fully clear, 1 = fully covering. */\n coverage = 0;\n private queue: Ramp[] = [];\n\n constructor(config: TransitionConfig = {}) {\n super(config);\n this.cosmetic = true;\n this.kind = config.kind ?? 'fade';\n this.color = config.color ?? '#1a1410';\n this.screenW = config.width ?? 1280;\n this.screenH = config.height ?? 720;\n this.cell = config.cell ?? 28;\n }\n\n /** True while a wipe is animating. */\n get busy(): boolean {\n return this.queue.length > 0;\n }\n\n private enqueue(to: number, dur: number, onEnd?: () => void): void {\n this.queue.push({ from: undefined, to, dur: Math.max(1e-4, dur), elapsed: 0, onEnd });\n }\n\n /** Animate the overlay to fully covering over `dur` seconds. */\n cover(dur = 0.4, onEnd?: () => void): this {\n this.enqueue(1, dur, onEnd);\n return this;\n }\n\n /** Animate the overlay back to fully clear over `dur` seconds. */\n reveal(dur = 0.4, onEnd?: () => void): this {\n this.enqueue(0, dur, onEnd);\n return this;\n }\n\n /** Hold the current coverage for `dur` seconds (chains after cover/reveal). */\n hold(dur: number, onEnd?: () => void): this {\n // Target the pending end-state so a mid-queue hold keeps that coverage.\n const target = this.queue.length ? this.queue[this.queue.length - 1].to : this.coverage;\n this.enqueue(target, dur, onEnd);\n return this;\n }\n\n /** The classic cover \u2192 onMidpoint \u2192 reveal sequence. Returns this for chaining. */\n wipe(opts: WipeOptions = {}): this {\n const cover = opts.cover ?? 0.4;\n this.cover(cover, () => {\n this.emit('covered', undefined);\n opts.onMidpoint?.();\n });\n if (opts.hold) this.hold(opts.hold);\n this.reveal(opts.reveal ?? cover, () => {\n this.emit('done', undefined);\n opts.onDone?.();\n });\n return this;\n }\n\n /** Signal emitted at full cover (the midpoint). */\n get covered() {\n return this.signal('covered');\n }\n /** Signal emitted when a wipe fully finishes revealing. */\n get done() {\n return this.signal('done');\n }\n\n protected override onProcess(dt: number): void {\n const step = this.queue[0];\n if (!step) return;\n if (step.from === undefined) step.from = this.coverage;\n step.elapsed += dt;\n const t = clamp(step.elapsed / step.dur, 0, 1);\n this.coverage = lerp(step.from, step.to, smoothstep(t));\n if (t >= 1) {\n this.coverage = step.to;\n const end = step.onEnd;\n this.queue.shift();\n end?.();\n }\n }\n\n protected override draw(out: DrawCommand[], _world: Transform): void {\n const c = this.coverage;\n if (c <= 0) return;\n // Screen space: ignore the camera transform so the wipe stays fixed.\n const z = this.z;\n if (this.kind === 'fade') {\n out.push({ kind: 'rect', x: 0, y: 0, w: this.screenW, h: this.screenH, fill: this.color, opacity: c, transform: IDENTITY, z });\n return;\n }\n if (this.kind === 'circle') {\n // Iris: a filled disc grown from the centre to the far corner.\n const cx = this.screenW / 2;\n const cy = this.screenH / 2;\n const diag = Math.sqrt(cx * cx + cy * cy);\n out.push({ kind: 'circle', cx, cy, radius: c * diag, fill: this.color, transform: IDENTITY, z });\n return;\n }\n // Dither: an ordered dissolve \u2014 one opaque cell per Bayer threshold below c.\n const cols = Math.ceil(this.screenW / this.cell);\n const rows = Math.ceil(this.screenH / this.cell);\n for (let cy = 0; cy < rows; cy++) {\n for (let cx = 0; cx < cols; cx++) {\n const threshold = (BAYER4[(cx & 3) + ((cy & 3) << 2)] + 0.5) / 16;\n if (threshold < c) {\n out.push({ kind: 'rect', x: cx * this.cell, y: cy * this.cell, w: this.cell, h: this.cell, fill: this.color, transform: IDENTITY, z });\n }\n }\n }\n }\n}\n\n// \u2500\u2500 Cinematic sequencer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CinematicStep {\n /** Optional label (handy for debugging/skip logic). */\n name?: string;\n /** Runs once when the step begins \u2014 aim the camera, set text, mutate state. */\n enter?: () => void;\n /** Minimum seconds to hold on this step before advancing (default 0). */\n duration?: number;\n /** Gate: advance only once this returns true (e.g. `() => !transition.busy`). */\n until?: () => boolean;\n}\n\n/**\n * Runs a list of pure-data cinematic steps on the fixed clock. Each step's\n * `enter` fires once, then the player waits for both its `duration` and its\n * `until` gate before moving on \u2014 the fade-gate pattern for scripted intros.\n * Cosmetic: it only orchestrates view/state changes, holds no hashed state.\n */\nexport class CinematicPlayer extends Node {\n override readonly type: string = 'CinematicPlayer';\n private steps: CinematicStep[] = [];\n private index = -1;\n private elapsed = 0;\n private running = false;\n private onFinish?: () => void;\n\n constructor(config: NodeConfig = {}) {\n super(config);\n this.cosmetic = true;\n }\n\n /** Load and start a sequence. `onDone` fires after the last step advances. */\n play(steps: CinematicStep[], onDone?: () => void): this {\n this.steps = steps;\n this.onFinish = onDone;\n this.index = -1;\n this.elapsed = 0;\n this.running = steps.length > 0;\n this.advance();\n return this;\n }\n\n /** True while a sequence is playing. */\n get active(): boolean {\n return this.running;\n }\n /** Index of the step currently on screen (\u22121 before play / after finish). */\n get step(): number {\n return this.index;\n }\n\n /** Signal emitted when the whole sequence finishes. */\n get finished() {\n return this.signal('finished');\n }\n\n private advance(): void {\n this.index++;\n this.elapsed = 0;\n if (this.index >= this.steps.length) {\n this.running = false;\n this.index = -1;\n this.emit('finished', undefined);\n this.onFinish?.();\n return;\n }\n this.steps[this.index].enter?.();\n }\n\n /** Abort the sequence immediately (no further enters, no finish callback). */\n stop(): void {\n this.running = false;\n this.index = -1;\n this.steps = [];\n }\n\n protected override onProcess(dt: number): void {\n if (!this.running) return;\n this.elapsed += dt;\n const s = this.steps[this.index];\n const durationDone = this.elapsed >= (s.duration ?? 0);\n const gateOpen = s.until ? s.until() : true;\n if (durationDone && gateOpen) this.advance();\n }\n}\n\n/**\n * Convenience: make a Transition sized to a world and add it to a parent (the\n * scene root by default, so it paints over everything). Returns the node.\n */\nexport function addTransition(parent: Node, config: TransitionConfig = {}): ScreenTransition {\n const t = new ScreenTransition({ z: 10_000, ...config });\n return parent.addChild(t);\n}\n\n/** A cinematic step that fires a wipe and gates advancement on its completion. */\nexport function wipeStep(transition: ScreenTransition, opts: WipeOptions & { name?: string } = {}): CinematicStep {\n return {\n name: opts.name ?? 'wipe',\n enter: () => transition.wipe(opts),\n until: () => !transition.busy,\n };\n}\n\n/** Screen rect helper for wiring a Transition into other 9-slice/UI code. */\nexport const screenRect = (w: number, h: number): Rect => ({ x: 0, y: 0, w, h });\n", "// Generic winnability solver. Turn-based/puzzle logic implements the pure\n// Puzzle interface; the solver proves a level beatable by search. Deterministic\n// opponent (fixed order + tie-breaks) means single-agent BFS \u2014 no adversarial\n// branching. (narrow-js's insight, generalized and typed.)\n//\n// Rule of the house: a hand-authored level is presumed WRONG until the solver\n// proves it winnable. In-head verification has a documented failure rate.\n\nexport interface Puzzle<State, Move> {\n /** Starting state (optionally per level index). */\n initial(level?: number): State;\n /** Legal moves from a state, in deterministic order. */\n moves(state: State): Move[];\n /** Apply a player move (may fold in a deterministic opponent response). */\n apply(state: State, move: Move): State;\n /** Win test. */\n isWin(state: State): boolean;\n /** Optional dead/lost test \u2014 pruned from the search. */\n isDead?(state: State): boolean;\n /** Canonical key for de-duplication (visited set). */\n key(state: State): string;\n}\n\nexport interface SolveResult<Move> {\n solvable: boolean;\n /** Shortest winning move sequence, if found. */\n path?: Move[];\n /** Depth of the shortest solution. */\n depth?: number;\n /** Nodes expanded (a difficulty/complexity proxy). */\n nodes: number;\n /** True if the search hit a cap before proving/\u200Bdisproving. */\n exhausted: boolean;\n}\n\nexport interface SolveOptions {\n level?: number;\n maxDepth?: number;\n nodeCap?: number;\n}\n\n/** Breadth-first search \u2192 the shortest solution and a real winnability proof. */\nexport function solve<State, Move>(\n puzzle: Puzzle<State, Move>,\n options: SolveOptions = {},\n): SolveResult<Move> {\n const maxDepth = options.maxDepth ?? 60;\n const nodeCap = options.nodeCap ?? 1_000_000;\n const start = puzzle.initial(options.level);\n\n if (puzzle.isWin(start)) return { solvable: true, path: [], depth: 0, nodes: 0, exhausted: false };\n\n interface QNode {\n state: State;\n path: Move[];\n }\n let frontier: QNode[] = [{ state: start, path: [] }];\n const seen = new Set<string>([puzzle.key(start)]);\n let nodes = 0;\n\n for (let depth = 0; depth < maxDepth && frontier.length > 0; depth++) {\n const next: QNode[] = [];\n for (const { state, path } of frontier) {\n for (const move of puzzle.moves(state)) {\n if (nodes >= nodeCap) return { solvable: false, nodes, exhausted: true };\n nodes++;\n const after = puzzle.apply(state, move);\n if (puzzle.isDead?.(after)) continue;\n if (puzzle.isWin(after)) {\n return { solvable: true, path: [...path, move], depth: depth + 1, nodes, exhausted: false };\n }\n const k = puzzle.key(after);\n if (!seen.has(k)) {\n seen.add(k);\n next.push({ state: after, path: [...path, move] });\n }\n }\n }\n frontier = next;\n }\n return { solvable: false, nodes, exhausted: frontier.length > 0 };\n}\n\n/**\n * Assert a puzzle level is winnable (throws with detail if not). Use in tests as\n * the content-balance gate.\n */\nexport function assertSolvable<State, Move>(\n puzzle: Puzzle<State, Move>,\n options: SolveOptions = {},\n): SolveResult<Move> {\n const result = solve(puzzle, options);\n if (!result.solvable) {\n throw new Error(\n `hayao: level ${options.level ?? 0} is NOT winnable ` +\n `(expanded ${result.nodes} nodes${result.exhausted ? ', search capped \u2014 raise nodeCap/maxDepth' : ''}).`,\n );\n }\n return result;\n}\n", "// Determinism verification. Re-run the same seed + input log twice; if any step's\n// state hash diverges, some hidden nondeterminism (Math.random, Date.now, Set\n// iteration, unordered map) leaked in. This is the regression net that lets you\n// refactor the sim fearlessly.\n\nimport type { World } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { frameActions, frameAxes } from '../input/actions';\n\nexport type WorldFactory = () => World;\n\n/** Run a world through an input log, returning the final hash and per-frame hashes. */\nexport function replay(makeWorld: WorldFactory, log: InputLog): { finalHash: string; hashes: string[] } {\n const world = makeWorld();\n const hashes: string[] = [];\n for (let i = 0; i < log.frames.length; i++) {\n world.step(frameActions(log, i), frameAxes(log, i));\n hashes.push(world.hash());\n }\n return { finalHash: world.hash(), hashes };\n}\n\nexport interface DeterminismReport {\n ok: boolean;\n frames: number;\n /** First frame index where the two runs diverged, or -1. */\n divergedAt: number;\n finalHash: string;\n}\n\n/** Run twice and compare every step's hash. */\nexport function checkDeterministic(makeWorld: WorldFactory, log: InputLog): DeterminismReport {\n const a = replay(makeWorld, log);\n const b = replay(makeWorld, log);\n let divergedAt = -1;\n for (let i = 0; i < a.hashes.length; i++) {\n if (a.hashes[i] !== b.hashes[i]) {\n divergedAt = i;\n break;\n }\n }\n return {\n ok: divergedAt === -1 && a.finalHash === b.finalHash,\n frames: log.frames.length,\n divergedAt,\n finalHash: a.finalHash,\n };\n}\n\n/** Assert determinism (throws with the divergence frame). */\nexport function assertDeterministic(makeWorld: WorldFactory, log: InputLog): DeterminismReport {\n const report = checkDeterministic(makeWorld, log);\n if (!report.ok) {\n throw new Error(\n `hayao: sim is NON-deterministic \u2014 runs diverged at frame ${report.divergedAt} ` +\n `of ${report.frames}. Check for Math.random/Date.now/Set-iteration/unordered-map in the sim.`,\n );\n }\n return report;\n}\n\n/**\n * Assert that restoring a snapshot reproduces the exact same continuation \u2014\n * i.e. save/load is lossless. Runs `warmup` steps, snapshots, runs `tail` more\n * on both the original and a restored copy, and compares final hashes.\n */\nexport function assertSnapshotStable(\n makeWorld: WorldFactory,\n log: InputLog,\n warmup: number,\n): { ok: boolean; hashA: string; hashB: string } {\n const original = makeWorld();\n for (let i = 0; i < warmup; i++) original.step(frameActions(log, i), frameAxes(log, i));\n const snap = original.snapshot();\n\n const restored = makeWorld();\n restored.restore(snap);\n\n for (let i = warmup; i < log.frames.length; i++) {\n original.step(frameActions(log, i), frameAxes(log, i));\n restored.step(frameActions(log, i), frameAxes(log, i));\n }\n const hashA = original.hash();\n const hashB = restored.hash();\n return { ok: hashA === hashB, hashA, hashB };\n}\n", "// Scripted playthroughs: drive a world headlessly with a sequence of held-input\n// segments and collect probe snapshots. This is Channel 1a \u2014 proving behavior on\n// game state, in Node, no browser. (Hold keys \u2265 a few frames: variable-height\n// jumps treat a 1-frame synthetic tap as a real short tap.)\n\nimport type { World } from '../world';\n\nexport interface Segment {\n /** Actions held down for this segment. */\n actions?: string[];\n /** Number of fixed steps to run. */\n frames: number;\n}\n\n/** Build a segment: hold `actions` for `frames` steps. */\nexport function hold(actions: string[], frames: number): Segment {\n return { actions, frames };\n}\n/** Build an idle segment (no input) for `frames` steps. */\nexport function wait(frames: number): Segment {\n return { actions: [], frames };\n}\n\nexport interface PlaythroughResult {\n totalFrames: number;\n finalHash: string;\n /** Probe snapshot after each segment. */\n probes: Record<string, unknown>[];\n}\n\n/** Run a scripted playthrough; returns a probe after each segment. */\nexport function scriptedPlaythrough(world: World, script: Segment[]): PlaythroughResult {\n const probes: Record<string, unknown>[] = [];\n let total = 0;\n for (const seg of script) {\n for (let i = 0; i < seg.frames; i++) world.step(seg.actions ?? []);\n total += seg.frames;\n probes.push(world.probe());\n }\n return { totalFrames: total, finalHash: world.hash(), probes };\n}\n\n/** Convenience: advance a world N frames with a fixed input set. */\nexport function pump(world: World, frames: number, actions: string[] = []): void {\n for (let i = 0; i < frames; i++) world.step(actions);\n}\n", "// Browser capture seam. Because the sim is headless-native \u2014 hayao owns the\n// clock and never touches document.hasFocus \u2014 this is ~30 lines, not the ~100 a\n// canvas engine needs. Exposes window.__hayao for scripted browser sessions and\n// aesthetic screenshots. Enable with ?capture=1.\n\nimport type { World } from '../world';\n\nexport interface CaptureTarget {\n readonly world: World;\n /** Advance one fixed step with the given actions and render. */\n stepOnce(actions?: string[]): void;\n /** Current frame as an SVG string (a vector screenshot). */\n renderSVG(): string;\n setPaused(paused: boolean): void;\n}\n\nexport interface HayaoCapture {\n pump(frames: number, actions?: string[]): Record<string, unknown>;\n probe(): Record<string, unknown>;\n hash(): string;\n shot(): string;\n save(path: string): Promise<boolean>;\n key(type: 'keydown' | 'keyup', code: string): void;\n readonly world: World;\n}\n\nexport function isCaptureMode(): boolean {\n return typeof location !== 'undefined' && new URLSearchParams(location.search).has('capture');\n}\n\n/** Install window.__hayao for scripted browser verification. */\nexport function installCapture(target: CaptureTarget): HayaoCapture {\n const api: HayaoCapture = {\n pump(frames, actions = []) {\n target.setPaused(true);\n for (let i = 0; i < frames; i++) target.stepOnce(actions);\n return target.world.probe();\n },\n probe: () => target.world.probe(),\n hash: () => target.world.hash(),\n shot: () => target.renderSVG(),\n async save(path) {\n const svg = target.renderSVG();\n try {\n const res = await fetch('/__shot', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ path, svg }),\n });\n return res.ok;\n } catch {\n return false;\n }\n },\n key(type, code) {\n document.dispatchEvent(new KeyboardEvent(type, { code, bubbles: true }));\n },\n get world() {\n return target.world;\n },\n };\n (globalThis as unknown as { __hayao: HayaoCapture }).__hayao = api;\n return api;\n}\n", "// Declarative input scripts: the ergonomic way to author headless playthroughs\n// for real-time games, where hand-writing per-frame action arrays is hopeless.\n// A script is a list of segments; each holds actions for N frames, optionally\n// tapping others on its first frame.\n\nimport type { World } from '../world';\n\nexport interface ScriptSegment {\n /** Actions held down for every frame of this segment. */\n hold?: string[];\n /** Actions pressed only on the first frame of this segment (taps). */\n press?: string[];\n /** How many fixed steps this segment lasts (default 1). */\n frames?: number;\n}\n\nexport type InputScript = ScriptSegment[];\n\n/** Expand a script into per-frame action arrays (an InputLog's frames). */\nexport function scriptToFrames(script: InputScript): string[][] {\n const out: string[][] = [];\n for (const seg of script) {\n const n = seg.frames ?? 1;\n const hold = seg.hold ?? [];\n for (let i = 0; i < n; i++) out.push(i === 0 && seg.press ? [...hold, ...seg.press] : [...hold]);\n }\n return out;\n}\n\nexport interface DriveResult {\n frames: number;\n /** True if driving stopped early because `until` matched. */\n matched: boolean;\n}\n\n/**\n * Step a world through a script. Pass `until` to stop as soon as a probe\n * predicate holds (e.g. level solved) \u2014 the tail of the script is slack, so\n * playthrough scripts don't need frame-perfect lengths.\n */\nexport function drive(world: World, script: InputScript, until?: (probe: Record<string, unknown>) => boolean): DriveResult {\n let frames = 0;\n for (const f of scriptToFrames(script)) {\n if (until && until(world.probe())) return { frames, matched: true };\n world.step(f);\n frames++;\n }\n return { frames, matched: until ? until(world.probe()) : false };\n}\n", "// The plan-interpreter bot skeleton \u2014 promoted to the engine after three\n// example games (shard-ascent, sproutveil, gleamvale) each rebuilt the same\n// shape: a plan of semantic steps, executed reactively against the probe each\n// frame, emitting actions. Games supply the step executors (steering is\n// genre-specific); the engine supplies the lifecycle, retries, and telemetry.\n//\n// const bot = createPlanBot(plan, {\n// walk(step, probe, out, ctx) { \u2026steer\u2026; if (arrived) ctx.next(); },\n// });\n// while (!probe.won) world.step(bot(world.probe()));\n\nexport interface BotCtx {\n /** Frames spent in the current step. */\n frames: number;\n /** Free per-step scratch (cleared on step change). */\n mem: Record<string, unknown>;\n /** Advance to the next plan step. */\n next(): void;\n /** Restart the current step (retry) \u2014 clears frames + mem. */\n retry(): void;\n}\n\nexport type StepExec<Step, Probe> = (step: Step, probe: Probe, out: string[], ctx: BotCtx) => void;\n\nexport interface PlanBot<Probe> {\n (probe: Probe): string[];\n stepIndex(): number;\n done(): boolean;\n}\n\nexport function createPlanBot<Step extends { kind: string }, Probe>(plan: Step[], execs: Record<string, StepExec<Step, Probe>>): PlanBot<Probe> {\n let i = 0;\n let frames = 0;\n let mem: Record<string, unknown> = {};\n\n const fn = (probe: Probe): string[] => {\n const out: string[] = [];\n const step = plan[i];\n if (!step) return out;\n frames++;\n const ctx: BotCtx = {\n get frames() {\n return frames;\n },\n mem,\n next() {\n i++;\n frames = 0;\n mem = {};\n },\n retry() {\n frames = 0;\n mem = {};\n },\n };\n const exec = execs[step.kind];\n if (!exec) throw new Error(`plan bot: no executor for step kind \"${step.kind}\"`);\n exec(step, probe, out, ctx);\n return out;\n };\n const bot = fn as PlanBot<Probe>;\n bot.stepIndex = () => i;\n bot.done = () => i >= plan.length;\n return bot;\n}\n\n/** Shared steering helper: 4/8-way movement toward a point. */\nexport function steer2D(px: number, py: number, tx: number, ty: number, out: string[], dead = 8): void {\n if (px < tx - dead) out.push('right');\n else if (px > tx + dead) out.push('left');\n if (py < ty - dead) out.push('down');\n else if (py > ty + dead) out.push('up');\n}\n", "// Feel gates (Channel 4): the FLOOR of professional game feel, made checkable.\n//\n// The correctness channels prove a game is not broken; the layout lints prove it\n// is legible. Neither says whether it FEELS good. These gates encode the small\n// set of feel fundamentals that separate amateur from professional and that are\n// genuinely mechanical \u2014 not matters of taste:\n//\n// 1. forgiveness \u2014 grace windows (coyote, jump-buffer, corner-nudge) exist and\n// actually accept a late/early input to the frame (FUN law 5).\n// 2. feedback \u2014 every significant event answers on \u22652 sensory channels\n// within a tight window, with juice magnitudes bounded (min to\n// read, max to not nauseate).\n// 3. readability \u2014 the avatar out-contrasts its surroundings, and every threat\n// telegraphs before its hitbox goes live.\n// 4. camera \u2014 the view moves lawfully: bounded speed/jerk (no snapping),\n// and its lead matches the target's motion.\n//\n// Every function returns human-readable issues (empty array = pass), exactly like\n// `layoutIssues`, so wiring one into a verify suite is one line:\n// t.check(issues.length === 0 ? 'forgiveness gate clean' : issues[0], !issues.length);\n//\n// All pure and allocation-light: gates read plain data (a config, a contract, a\n// display list, a probe timeline, a sampled position series), never the live DOM.\n\nimport type { DrawCommand } from '../render/commands';\nimport type { Vec2 } from '../core/math';\nimport { dhypot, dpow } from '../core/dmath';\n\nconst dedupe = (a: string[]): string[] => [...new Set(a)];\n\n\n// \u2500\u2500 1. Forgiveness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Grace is a system, not polish (FUN law 5). Two checks: a static one on the\n// controller config (the windows are specced at all), and a behavioural one that\n// frame-pumps an actual grace window and asserts accepted-inside / refused-outside.\n\n/** The forgiveness-relevant slice of any character config (PlatformerConfig satisfies it). */\nexport interface ForgivenessSpec {\n /** Seconds of coyote time after leaving the ground. */\n coyoteTime: number;\n /** Seconds a jump press is buffered before landing. */\n jumpBuffer: number;\n /** Pixels the body is nudged sideways to slip past a ceiling corner (0 = none). */\n jumpCornerNudge?: number;\n}\n\nexport interface ForgivenessOptions {\n /** Minimum coyote time in seconds (default 0.05 \u2248 3 frames @60Hz). */\n minCoyote?: number;\n /** Minimum jump-buffer in seconds (default 0.05). */\n minBuffer?: number;\n /** Require a non-zero jump corner nudge (default true). */\n requireCornerNudge?: boolean;\n}\n\n/**\n * Static audit of a controller's grace windows. A platformer that ships without\n * coyote time and input buffering feels like it drops inputs \u2014 the single most\n * common reason an otherwise-correct platformer feels amateur.\n */\nexport function forgivenessIssues(spec: ForgivenessSpec, opts: ForgivenessOptions = {}): string[] {\n const minCoyote = opts.minCoyote ?? 0.05;\n const minBuffer = opts.minBuffer ?? 0.05;\n const requireNudge = opts.requireCornerNudge ?? true;\n const issues: string[] = [];\n if (!(spec.coyoteTime >= minCoyote)) issues.push(`coyote time ${spec.coyoteTime}s is below the ${minCoyote}s floor \u2014 late jumps off a ledge will be dropped`);\n if (!(spec.jumpBuffer >= minBuffer)) issues.push(`jump buffer ${spec.jumpBuffer}s is below the ${minBuffer}s floor \u2014 early jumps before landing will be swallowed`);\n if (requireNudge && !((spec.jumpCornerNudge ?? 0) > 0)) issues.push('no jump corner nudge \u2014 clipping a ceiling edge kills upward momentum instead of slipping past');\n return issues;\n}\n\n/**\n * Behavioural grace-window prover. `accepts(delayFrames)` runs the sim with the\n * grace-triggering input applied `delayFrames` after the enabling event and\n * returns whether the action still took. A correct window accepts every delay in\n * `[0, windowFrames]` and refuses `windowFrames + 1` \u2014 the exact edge FUN law 5\n * demands. Use it for coyote time, jump buffering, i-frames, mercy windows.\n */\nexport function graceWindowIssues(label: string, windowFrames: number, accepts: (delayFrames: number) => boolean): string[] {\n const issues: string[] = [];\n for (let d = 0; d <= windowFrames; d++) {\n if (!accepts(d)) issues.push(`${label}: input ${d} frame(s) into the window was refused \u2014 grace window is shorter than the specced ${windowFrames}`);\n }\n if (accepts(windowFrames + 1)) issues.push(`${label}: input ${windowFrames + 1} frame(s) in (past the window) was still accepted \u2014 grace window is longer than specced (unfair leniency)`);\n return dedupe(issues);\n}\n\n// \u2500\u2500 2. Feedback completeness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Every gameplay-significant event must answer on at least two sensory channels\n// within a tight window, and the juice magnitudes must stay inside an envelope:\n// big enough to read, small enough not to nauseate or drown the frame.\n\nexport type FeedbackChannel = 'visual' | 'audio' | 'haptic';\n\n/** What a game promises to fire for one event kind \u2014 audited statically. */\nexport interface FeedbackResponse {\n /** Channels this event answers on (particles/flash = visual, sfx = audio, shake/rumble = haptic). */\n channels: FeedbackChannel[];\n /** Screen-shake trauma added (0..1), if any \u2014 bounded by the envelope. */\n shake?: number;\n /** Hit-stop / freeze frames injected, if any \u2014 bounded by the envelope. */\n hitstopFrames?: number;\n}\n\n/** event kind \u2192 its feedback response. The game declares this next to its sim. */\nexport type FeedbackContract = Record<string, FeedbackResponse>;\n\nexport interface FeedbackOptions {\n /** Minimum distinct channels per event (default 2). */\n minChannels?: number;\n /** Allowed screen-shake trauma range (default [0, 1]). */\n shake?: [number, number];\n /** Allowed hit-stop range in frames (default [0, 12] \u2014 beyond ~0.2s reads as a hitch). */\n hitstop?: [number, number];\n}\n\n/**\n * Audit a feedback contract: every required event exists, answers on \u2265 minChannels\n * distinct channels, and keeps its shake/hit-stop inside the envelope. This is the\n * \"does every hit/land/collect/death actually land on the senses?\" gate.\n */\nexport function feedbackIssues(contract: FeedbackContract, requiredEvents: readonly string[], opts: FeedbackOptions = {}): string[] {\n const minCh = opts.minChannels ?? 2;\n const [shakeLo, shakeHi] = opts.shake ?? [0, 1];\n const [stopLo, stopHi] = opts.hitstop ?? [0, 12];\n const issues: string[] = [];\n for (const ev of requiredEvents) {\n const r = contract[ev];\n if (!r) {\n issues.push(`event \"${ev}\" has no feedback response \u2014 it happens silently`);\n continue;\n }\n const distinct = new Set(r.channels).size;\n if (distinct < minCh) issues.push(`event \"${ev}\" answers on ${distinct} channel(s) (${r.channels.join('+') || 'none'}) \u2014 needs \u2265 ${minCh} (e.g. sfx + particles)`);\n if (r.shake !== undefined && (r.shake < shakeLo || r.shake > shakeHi)) issues.push(`event \"${ev}\" shake ${r.shake} is outside the [${shakeLo}, ${shakeHi}] envelope`);\n if (r.hitstopFrames !== undefined && (r.hitstopFrames < stopLo || r.hitstopFrames > stopHi)) issues.push(`event \"${ev}\" hit-stop ${r.hitstopFrames}f is outside the [${stopLo}, ${stopHi}]f envelope`);\n }\n return dedupe(issues);\n}\n\n// \u2500\u2500 3. Readability: avatar salience + threat telegraphs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Relative luminance (WCAG) of a #rrggbb / #rgb color, in [0,1]. */\nexport function relLuminance(hex: string): number {\n let h = hex.replace('#', '');\n if (h.length === 3) h = h.split('').map((c) => c + c).join('');\n const n = parseInt(h, 16);\n const chan = (c: number): number => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : dpow((s + 0.055) / 1.055, 2.4);\n };\n return 0.2126 * chan((n >> 16) & 255) + 0.7152 * chan((n >> 8) & 255) + 0.0722 * chan(n & 255);\n}\n\n/** WCAG contrast ratio between two colors, in [1, 21]. */\nexport function contrastRatio(a: string, b: string): number {\n const la = relLuminance(a);\n const lb = relLuminance(b);\n const hi = Math.max(la, lb);\n const lo = Math.min(la, lb);\n return (hi + 0.05) / (lo + 0.05);\n}\n\nexport interface SalienceOptions {\n /** Minimum contrast the avatar must hold against the background (default 3). */\n minBackgroundContrast?: number;\n /**\n * The avatar's fill must out-contrast the MEDIAN non-avatar fill against the\n * background by at least this factor (default 1.15) \u2014 i.e. it visibly pops from\n * the scenery rather than blending into it.\n */\n minSalienceFactor?: number;\n}\n\nconst fillOf = (c: DrawCommand): string | undefined => (c.kind === 'text' ? undefined : (c as { fill?: string }).fill);\n\n/**\n * Readability gate: the player avatar must be the most salient thing on screen.\n * The game passes the exact fill it painted the avatar with; the gate asserts that\n * color out-contrasts both the background and the median scenery fill in the live\n * display list. \"Where's my guy?\" is a fun-killer no correctness proof catches \u2014\n * this one does, from pure draw data.\n */\nexport function salienceIssues(commands: DrawCommand[], avatarFill: string, background: string, opts: SalienceOptions = {}): string[] {\n const minBg = opts.minBackgroundContrast ?? 3;\n const minFactor = opts.minSalienceFactor ?? 1.15;\n const issues: string[] = [];\n const avatarContrast = contrastRatio(avatarFill, background);\n if (avatarContrast < minBg) issues.push(`avatar (${avatarFill}) contrast vs background is ${avatarContrast.toFixed(2)}:1 (needs \u2265 ${minBg}:1) \u2014 it sinks into the ground`);\n\n const others: number[] = [];\n for (const c of commands) {\n const f = fillOf(c);\n if (f && f !== 'none' && f !== avatarFill) others.push(contrastRatio(f, background));\n }\n if (others.length) {\n others.sort((x, y) => x - y);\n const median = others[Math.floor(others.length / 2)];\n if (avatarContrast < median * minFactor) issues.push(`avatar (${avatarFill}, ${avatarContrast.toFixed(2)}:1) does not pop from the scenery (median ${median.toFixed(2)}:1) \u2014 it needs \u2265 ${minFactor}\u00D7 the median contrast`);\n }\n return dedupe(issues);\n}\n\nexport interface TelegraphFrame {\n /** True on frames where a threat is warning (flash/wind-up) before it can hurt you. */\n telegraphing: boolean;\n /** True on frames where the threat's hitbox is live (it can deal damage). */\n active: boolean;\n}\n\n/**\n * Telegraph gate: every activation of a threat must be preceded by at least\n * `minFrames` of contiguous telegraph. Reactive play is only possible if danger\n * announces itself; a hitbox that goes live with no wind-up is an unfair death.\n * Feed a per-frame timeline (one entry per sim frame) for a single threat.\n */\nexport function telegraphIssues(timeline: readonly TelegraphFrame[], minFrames: number, label = 'threat'): string[] {\n const issues: string[] = [];\n let warn = 0;\n for (let i = 0; i < timeline.length; i++) {\n const f = timeline[i];\n const justActivated = f.active && (i === 0 || !timeline[i - 1].active);\n if (justActivated && warn < minFrames) issues.push(`${label}: hitbox went live at frame ${i} after only ${warn} telegraph frame(s) \u2014 needs \u2265 ${minFrames} of wind-up`);\n warn = f.active ? 0 : f.telegraphing ? warn + 1 : 0;\n }\n return dedupe(issues);\n}\n\n// \u2500\u2500 4. Camera lawfulness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface CameraOptions {\n /** Fixed timestep between samples in seconds (default 1/60). */\n dt?: number;\n /** Max camera speed in px/s before it reads as a snap (default 1800). */\n maxSpeed?: number;\n /** Max camera acceleration in px/s\u00B2 before the motion reads as jerky (default 90000). */\n maxAccel?: number;\n}\n\n/**\n * Camera lawfulness gate over a sampled position series (one Vec2 per frame). A\n * good follow camera never teleports and never jerks: bounded velocity (no snap)\n * and bounded acceleration (smooth, not stuttery). You cannot systematize when a\n * director SHOULD break these for drama \u2014 but an unbidden snap is always a bug.\n */\nexport function cameraIssues(samples: readonly Vec2[], opts: CameraOptions = {}): string[] {\n const dt = opts.dt ?? 1 / 60;\n const maxSpeed = opts.maxSpeed ?? 1800;\n const maxAccel = opts.maxAccel ?? 90000;\n if (samples.length < 3) return [];\n const issues: string[] = [];\n const vel: number[] = [];\n for (let i = 1; i < samples.length; i++) {\n const dx = samples[i].x - samples[i - 1].x;\n const dy = samples[i].y - samples[i - 1].y;\n const speed = dhypot(dx, dy) / dt;\n vel.push(speed);\n if (speed > maxSpeed) issues.push(`camera snapped at frame ${i}: ${Math.round(speed)}px/s exceeds the ${maxSpeed}px/s ceiling`);\n }\n for (let i = 1; i < vel.length; i++) {\n const accel = Math.abs(vel[i] - vel[i - 1]) / dt;\n if (accel > maxAccel) issues.push(`camera jerked at frame ${i + 1}: ${Math.round(accel)}px/s\u00B2 exceeds the ${maxAccel}px/s\u00B2 ceiling`);\n }\n return dedupe(issues);\n}\n\n/**\n * Look-ahead gate: on the axes where the target is moving, the camera should lead\n * in the SAME direction (bias the view toward where you're going), never trail\n * backwards. Compares net camera drift to net target drift across the series.\n */\nexport function lookAheadIssues(cameraSamples: readonly Vec2[], targetSamples: readonly Vec2[], minLead = 0): string[] {\n if (cameraSamples.length < 2 || cameraSamples.length !== targetSamples.length) return [];\n const camDX = cameraSamples[cameraSamples.length - 1].x - cameraSamples[0].x;\n const tgtDX = targetSamples[targetSamples.length - 1].x - targetSamples[0].x;\n const camDY = cameraSamples[cameraSamples.length - 1].y - cameraSamples[0].y;\n const tgtDY = targetSamples[targetSamples.length - 1].y - targetSamples[0].y;\n const issues: string[] = [];\n if (Math.abs(tgtDX) > minLead && Math.sign(camDX) !== 0 && Math.sign(camDX) !== Math.sign(tgtDX)) issues.push('camera drifts opposite the target on X \u2014 the view lags behind instead of leading');\n if (Math.abs(tgtDY) > minLead && Math.sign(camDY) !== 0 && Math.sign(camDY) !== Math.sign(tgtDY)) issues.push('camera drifts opposite the target on Y \u2014 the view lags behind instead of leading');\n return issues;\n}\n\n// \u2500\u2500 The declarative floor: one spec, all applicable gates \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// A game DECLARES its feel contract once (`export const feel: FeelSpec`); the\n// portfolio audit (`npm run feel`) and the game's own verify then run every gate\n// the spec provides inputs for. This is how the floor rises for ALL output: new\n// games declare a spec by definition-of-done, and the audit reports coverage.\n\nexport interface FeelSpec {\n /** The avatar's fill color \u2014 enables the salience gate. */\n avatarFill?: string;\n /** Background color (defaults to the game's `background`). */\n background?: string;\n /** Controller grace config \u2014 enables the forgiveness gate (PlatformerConfig fits). */\n forgiveness?: ForgivenessSpec;\n /** Declared feedback contract + the events that must be covered \u2014 enables the feedback gate. */\n feedback?: { contract: FeedbackContract; events: readonly string[] };\n /** True for scrolling games \u2014 enables the camera gate (needs sampled positions). */\n scrolls?: boolean;\n}\n\n/** Runtime inputs the audit/verify computes and hands to the aggregator. */\nexport interface FeelContext {\n /** A rendered display list (drive a few frames, then `world.render()`). */\n commands?: DrawCommand[];\n /** Sampled camera-follow positions over a run (exclude the pre-start frame). */\n camSamples?: readonly Vec2[];\n /** Matching target positions, for the look-ahead check. */\n targetSamples?: readonly Vec2[];\n /** Fixed timestep for the camera gate (default 1/60). */\n dt?: number;\n /** Background fallback if the spec omits one. */\n background?: string;\n}\n\nexport interface FeelReport {\n ok: boolean;\n /** One entry per gate that actually ran (given the spec + context). */\n sections: { gate: string; issues: string[] }[];\n /** Gates the spec asks for but that lacked the runtime context to run. */\n skipped: string[];\n}\n\n/**\n * Run every feel gate the spec provides inputs for, returning a structured report.\n * Static gates (forgiveness, feedback) run from the spec alone; salience needs a\n * rendered display list; the camera gate needs sampled positions. Gates whose\n * context is missing are reported as `skipped`, never silently dropped.\n */\nexport function runFeelGates(spec: FeelSpec, ctx: FeelContext = {}): FeelReport {\n const sections: { gate: string; issues: string[] }[] = [];\n const skipped: string[] = [];\n const bg = spec.background ?? ctx.background ?? '#ffffff';\n if (spec.forgiveness) sections.push({ gate: 'forgiveness', issues: forgivenessIssues(spec.forgiveness) });\n if (spec.feedback) sections.push({ gate: 'feedback', issues: feedbackIssues(spec.feedback.contract, spec.feedback.events) });\n if (spec.avatarFill) {\n if (ctx.commands) sections.push({ gate: 'salience', issues: salienceIssues(ctx.commands, spec.avatarFill, bg) });\n else skipped.push('salience (no rendered frame)');\n }\n if (spec.scrolls) {\n if (ctx.camSamples && ctx.camSamples.length >= 3) {\n const issues = cameraIssues(ctx.camSamples, { dt: ctx.dt });\n if (ctx.targetSamples) issues.push(...lookAheadIssues(ctx.camSamples, ctx.targetSamples));\n sections.push({ gate: 'camera', issues });\n } else skipped.push('camera (no sampled positions)');\n }\n return { ok: sections.every((s) => s.issues.length === 0), sections, skipped };\n}\n", "// Layout lints \u2014 verification for the HUMAN-contact layer. The first real\n// playtest of the 20-genre campaign found that every reported defect lived in\n// the one layer the sim proofs cannot see: text buried under sprites, labels\n// kissing shapes, controls nobody explains. But the display list is pure\n// data, so the basics of readability are assertable like everything else.\n//\n// Rules enforced here (see CONVENTIONS \"The human-contact layer\"):\n// 1. TEXT IS SACRED. A shape may fully contain a text's box (it's a panel)\n// or be fully disjoint from it. Partial overlap = collision. Shapes at\n// z \u2264 1 are exempt \u2014 that's the background lattice (tile grids, felt).\n// 2. FIRST CONTACT. Every action in the input map must be mentioned by some\n// on-screen text on the first frame (its key or its name) \u2014 a player who\n// reads the screen must be able to discover the controls.\n\nimport type { DrawCommand, TextCommand } from '../render/commands';\nimport type { InputMap } from '../input/actions';\nimport type { World } from '../world';\nimport { contrastRatio } from './gates';\n\nexport interface TextBox {\n cmd: TextCommand;\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\n/** Approximate a text command's on-screen box (serif \u2248 0.56em per char). */\nexport function textBox(cmd: TextCommand): TextBox {\n const w = cmd.text.length * cmd.size * 0.56;\n const h = cmd.size * 1.25;\n const cx = cmd.transform.e + cmd.x;\n const by = cmd.transform.f + cmd.y; // baseline\n const left = cmd.align === 'center' ? cx - w / 2 : cmd.align === 'right' ? cx - w : cx;\n return { cmd, x: left, y: by - cmd.size, w, h };\n}\n\n/** Conservative bounds of a non-text command (local shape + translation). */\nexport function shapeBox(cmd: DrawCommand): { x: number; y: number; w: number; h: number } | null {\n const ex = cmd.transform.e;\n const ey = cmd.transform.f;\n switch (cmd.kind) {\n case 'rect':\n return { x: ex + cmd.x, y: ey + cmd.y, w: cmd.w, h: cmd.h };\n case 'circle':\n return { x: ex + cmd.cx - cmd.radius, y: ey + cmd.cy - cmd.radius, w: cmd.radius * 2, h: cmd.radius * 2 };\n case 'poly': {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (let i = 0; i < cmd.points.length; i += 2) {\n minX = Math.min(minX, cmd.points[i]);\n maxX = Math.max(maxX, cmd.points[i]);\n minY = Math.min(minY, cmd.points[i + 1]);\n maxY = Math.max(maxY, cmd.points[i + 1]);\n }\n return { x: ex + minX, y: ey + minY, w: maxX - minX, h: maxY - minY };\n }\n default:\n return null; // paths are decorative fans/arcs \u2014 skip (conservative)\n }\n}\n\nconst overlaps = (a: { x: number; y: number; w: number; h: number }, b: { x: number; y: number; w: number; h: number }): boolean =>\n a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;\n\nconst contains = (outer: { x: number; y: number; w: number; h: number }, inner: { x: number; y: number; w: number; h: number }, pad = 2): boolean =>\n outer.x - pad <= inner.x && outer.y - pad <= inner.y && outer.x + outer.w + pad >= inner.x + inner.w && outer.y + outer.h + pad >= inner.y + inner.h;\n\nexport interface LayoutOptions {\n /** Shapes at or below this z are background lattice (tiles/felt) and may sit under text. */\n backgroundZ?: number;\n /** Extra pixels of breathing room demanded around text (default 0 = touch is allowed, overlap is not). */\n margin?: number;\n /**\n * Lint transient view chrome too (floating popups, particles). Off by default:\n * a \"+10\" drifting across a HUD label is motion, not a layout bug (see #26).\n */\n includeTransient?: boolean;\n /**\n * The page background these commands paint on. When given, contrast lints run\n * (see `minContrast` / `minTextContrast`): a shape or label that barely differs\n * from what sits under it is invisible even though the sim hashes fine (#30).\n */\n background?: string;\n /**\n * Minimum contrast ratio a solid foreground shape must hold against the\n * background to count as visible at all (default 1.5). Only checked when\n * `background` is set.\n */\n minContrast?: number;\n /**\n * Minimum contrast ratio text must hold against its backing (panel fill, or the\n * background) \u2014 the WCAG AA readability bar (default 4.5). Only when `background`\n * is set. Pass 0 to skip the text-contrast check while keeping shape contrast.\n */\n minTextContrast?: number;\n}\n\nconst isTransient = (c: DrawCommand): boolean => (c as { transient?: boolean }).transient === true;\nconst solidFill = (c: DrawCommand): string | undefined => {\n const f = (c as { fill?: string }).fill;\n if (!f || f === 'none') return undefined;\n if ((c as { gradient?: unknown }).gradient) return undefined; // gradient bounds vary \u2014 skip\n return f;\n};\n\n/**\n * Lint a display list for text readability and visibility. Returns human-readable\n * issues (empty = clean). Checks:\n * 1. text-vs-shape partial overlaps (a label half-under a shape),\n * 2. text fully hidden behind an opaque higher-z shape (silent invisible labels, #31),\n * 3. text-vs-text overlaps,\n * 4. (opt-in via `background`) low-contrast shapes and text (#30).\n * Transient commands (popups/particles) are skipped unless `includeTransient`.\n */\nexport function layoutIssues(commands: DrawCommand[], opts: LayoutOptions = {}): string[] {\n const backgroundZ = opts.backgroundZ ?? 1;\n const margin = opts.margin ?? 0;\n const bg = opts.background;\n const minContrast = opts.minContrast ?? 1.5;\n const minTextContrast = opts.minTextContrast ?? 4.5;\n const issues: string[] = [];\n const lintable = opts.includeTransient ? commands : commands.filter((c) => !isTransient(c));\n const texts: TextBox[] = [];\n for (const c of lintable) if (c.kind === 'text' && (c as TextCommand).text.trim().length) texts.push(textBox(c as TextCommand));\n\n for (const t of texts) {\n const tz = t.cmd.z ?? 0;\n const r = { x: t.x - margin, y: t.y - margin, w: t.w + margin * 2, h: t.h + margin * 2 };\n // A backing panel fully contains the text and sits BELOW it in paint order\n // (z \u2264 text z). It absolves collisions with shapes it covers \u2014 HUD scrims.\n // A containing shape ABOVE the text is not a panel; it buries the label.\n let panelZ = -Infinity;\n let panelFill: string | undefined = bg;\n for (const c of lintable) {\n if (c.kind === 'text') continue;\n const b = shapeBox(c);\n if (!b || !contains(b, t)) continue;\n const opaque = c.opacity === undefined || c.opacity >= 0.6;\n const cz = c.z ?? 0;\n if (opaque && cz <= tz && cz >= panelZ) {\n panelZ = cz;\n panelFill = solidFill(c) ?? panelFill; // the nearest opaque backing under the text\n }\n // Occlusion (#31): an opaque shape that contains the text but paints ABOVE\n // it hides the label entirely \u2014 no gate caught this before.\n if (cz > tz && (c.opacity === undefined || c.opacity >= 0.9)) {\n issues.push(`text \"${clip(t.cmd.text)}\" is hidden behind a ${c.kind} (z${cz} > text z${tz}) that fully covers it \u2014 give the text a higher z, or the shape a lower one`);\n }\n }\n for (const c of lintable) {\n if (c.kind === 'text') continue;\n if ((c.z ?? 0) <= backgroundZ) continue; // background lattice\n if ((c.z ?? 0) <= panelZ) continue; // hidden behind the text's panel\n if (c.opacity !== undefined && c.opacity < 0.25) continue; // ghosts\n const b = shapeBox(c);\n if (!b) continue;\n if (overlaps(r, b) && !contains(b, t)) {\n issues.push(`text \"${clip(t.cmd.text)}\" collides with a ${c.kind} (z${c.z}) at ~(${Math.round(b.x)},${Math.round(b.y)}) \u2014 back it with a panel, or stay clear`);\n }\n }\n // Contrast (#30): text must read against whatever it sits on.\n if (bg && minTextContrast > 0) {\n const fg = t.cmd.fill;\n if (fg && fg !== 'none' && (t.cmd.opacity === undefined || t.cmd.opacity >= 0.6)) {\n const ratio = contrastRatio(fg, panelFill ?? bg);\n if (ratio < minTextContrast) issues.push(`text \"${clip(t.cmd.text)}\" (${fg}) contrast is ${ratio.toFixed(2)}:1 on its backing (needs \u2265 ${minTextContrast}:1) \u2014 barely readable`);\n }\n }\n }\n\n // Contrast (#30): a solid foreground shape must differ from the background.\n if (bg) {\n for (const c of lintable) {\n if (c.kind === 'text') continue;\n if ((c.z ?? 0) <= backgroundZ) continue;\n if (c.opacity !== undefined && c.opacity < 0.6) continue;\n const fill = solidFill(c);\n if (!fill) continue;\n const ratio = contrastRatio(fill, bg);\n if (ratio < minContrast) issues.push(`${c.kind} (${fill}, z${c.z}) contrast is ${ratio.toFixed(2)}:1 vs background ${bg} (needs \u2265 ${minContrast}:1) \u2014 it vanishes into the ground`);\n }\n }\n\n for (let i = 0; i < texts.length; i++)\n for (let j = i + 1; j < texts.length; j++)\n if (overlaps(texts[i], texts[j])) issues.push(`texts \"${clip(texts[i].cmd.text)}\" and \"${clip(texts[j].cmd.text)}\" overlap`);\n return dedupe(issues);\n}\n\nconst clip = (s: string): string => (s.length > 28 ? s.slice(0, 25) + '\u2026' : s);\nconst dedupe = (a: string[]): string[] => [...new Set(a)];\n\n/** Friendly names a hint text may use to reference a key code. */\nexport function keyMentions(code: string): string[] {\n if (code.startsWith('Digit')) return [code.slice(5)];\n if (code.startsWith('Key')) return [code.slice(3).toLowerCase()];\n if (code.startsWith('Arrow')) return ['arrow', '\u2190', '\u2192', '\u2191', '\u2193', code.slice(5).toLowerCase()];\n if (code.startsWith('Shift')) return ['shift'];\n if (code === 'Space') return ['space'];\n if (code === 'Enter') return ['enter'];\n if (code === 'Period') return ['.'];\n return [code.toLowerCase()];\n}\n\n/**\n * First-contact check: which actions does no on-screen text explain? An\n * action passes if any text mentions its name or one of its keys' friendly\n * names. 'restart' is exempt (universal convention).\n */\nexport function missingControlHints(world: World, inputMap: InputMap): string[] {\n const textBlob = world\n .render()\n .filter((c): c is TextCommand => c.kind === 'text')\n .map((c) => c.text.toLowerCase())\n .join(' \u00B7 ');\n const missing: string[] = [];\n const mentions = (n: string): boolean => {\n if (!n.length) return false;\n // Short tokens (single letters, digits) must appear as standalone words,\n // or \"f\" would be satisfied by the word \"fire\" losing the actual key.\n if (n.length <= 2 && /^[a-z0-9.]+$/.test(n)) return new RegExp(`(^|[^a-z0-9])${n.replace('.', '\\\\.')}($|[^a-z0-9])`).test(textBlob);\n return textBlob.includes(n);\n };\n for (const [action, keys] of Object.entries(inputMap)) {\n if (action === 'restart') continue;\n const names = [action.toLowerCase().replace(/-\\d+$/, ''), ...keys.flatMap(keyMentions)];\n if (!names.some(mentions)) missing.push(action);\n }\n return dedupe(missing);\n}\n", "// Feel probes (Channel 3): quality proxies computed from a per-frame probe\n// timeline. The harness cannot feel fun, but it can measure fun's precursors \u2014\n// time-to-first-meaningful-action, event cadence, difficulty ramp, input\n// decision density \u2014 and fail when a game drifts outside its tuned windows.\n// These are proxies, not proof: pair them with the filmstrip and a human-set\n// window per game (see docs/VERIFICATION.md \u00A7Channel 3).\n\nimport type { World } from '../world';\n\nexport type ProbeFrame = Record<string, unknown>;\n\n/**\n * Step a world through per-frame action arrays, probing after every step.\n * Returns frames.length + 1 probes: index 0 is the pre-step state, index i is\n * the state after frame i. (With the default 60Hz clock, index / 60 = sim\n * seconds.) For a segment-level timeline use scriptedPlaythrough instead.\n */\nexport function recordTimeline(world: World, frames: string[][]): ProbeFrame[] {\n const out: ProbeFrame[] = [world.probe()];\n for (const f of frames) {\n world.step(f);\n out.push(world.probe());\n }\n return out;\n}\n\n/** First timeline index where `pred` holds, or -1 if it never does. */\nexport function firstFrame(timeline: ProbeFrame[], pred: (p: ProbeFrame) => boolean): number {\n for (let i = 0; i < timeline.length; i++) if (pred(timeline[i])) return i;\n return -1;\n}\n\n/** The value of one probe key across the timeline. */\nexport function series(timeline: ProbeFrame[], key: string): unknown[] {\n return timeline.map((p) => p[key]);\n}\n\n/** Timeline indices where `key`'s value differs from the previous frame \u2014 an event cadence. */\nexport function changeFrames(timeline: ProbeFrame[], key: string): number[] {\n const out: number[] = [];\n for (let i = 1; i < timeline.length; i++) if (timeline[i][key] !== timeline[i - 1][key]) out.push(i);\n return out;\n}\n\n/** Monotonic within slack: 'up' means every value \u2265 previous \u2212 slack. */\nexport function isMonotonic(values: number[], dir: 'up' | 'down', slack = 0): boolean {\n for (let i = 1; i < values.length; i++) {\n if (dir === 'up' ? values[i] < values[i - 1] - slack : values[i] > values[i - 1] + slack) return false;\n }\n return true;\n}\n\n/**\n * Fraction of frames carrying at least one action \u2014 a crude engagement proxy.\n * Near 0 the player is waiting; near 1 they are mashing; a tuned game usually\n * lives somewhere in between (set the window per genre).\n */\nexport function inputDensity(frames: string[][]): number {\n if (frames.length === 0) return 0;\n return frames.filter((f) => f.length > 0).length / frames.length;\n}\n\n/** Largest gap (in frames) between consecutive events \u2014 dead-air detector. */\nexport function longestLull(eventFrames: number[], totalFrames: number): number {\n const pts = [0, ...eventFrames, totalFrames];\n let worst = 0;\n for (let i = 1; i < pts.length; i++) worst = Math.max(worst, pts[i] - pts[i - 1]);\n return worst;\n}\n", "// Ramp gate (Channel 5): prove the SHAPE of an hour, not just one level.\n//\n// The solver proves each level winnable; the feel gates prove each moment feels\n// fair. Neither says the *sequence* is well-formed. A campaign that jumps from\n// trivial to brutal in one step, or flatlines at one difficulty for forty levels,\n// is \"correct\" level-by-level and miserable to play. This gate reads the per-level\n// difficulty series (solver depths, or any monotone difficulty proxy) and asserts\n// the fundamentals of a good curve \u2014 the things that ARE mechanical, not taste:\n//\n// 1. escalation \u2014 the finale out-challenges the opening; the trend rises.\n// 2. no cliffs \u2014 no single step spikes difficulty beyond an envelope (the\n// #1 cause of a \"difficulty wall\" that sheds players).\n// 3. rhythm \u2014 small dips (breathers) are allowed, but the curve doesn't\n// mostly descend; forward progress dominates.\n// 4. variety \u2014 the series isn't a flat line; levels actually differ.\n//\n// Pure, allocation-light, and returns human-readable issues (empty = pass), the\n// same idiom as `layoutIssues` / the feel gates \u2014 one line wires it into verify.\n\nconst dedupe = (a: string[]): string[] => [...new Set(a)];\n\nexport interface RampStats {\n count: number;\n min: number;\n max: number;\n mean: number;\n /** Distinct difficulty values \u2014 a flat curve has 1. */\n distinct: number;\n /** Largest single step-to-step increase. */\n maxJump: number;\n /** Fraction of steps that rise or hold (0..1). */\n forwardFraction: number;\n}\n\n/** Summarize a difficulty series \u2014 handy for logging the curve next to the gate. */\nexport function rampStats(difficulty: readonly number[]): RampStats {\n const n = difficulty.length;\n if (n === 0) return { count: 0, min: 0, max: 0, mean: 0, distinct: 0, maxJump: 0, forwardFraction: 1 };\n let min = difficulty[0];\n let max = difficulty[0];\n let sum = 0;\n let maxJump = 0;\n let forward = 0;\n for (let i = 0; i < n; i++) {\n const d = difficulty[i];\n if (d < min) min = d;\n if (d > max) max = d;\n sum += d;\n if (i > 0) {\n const step = d - difficulty[i - 1];\n if (step > maxJump) maxJump = step;\n if (step >= 0) forward++;\n }\n }\n return {\n count: n,\n min,\n max,\n mean: sum / n,\n distinct: new Set(difficulty).size,\n maxJump,\n forwardFraction: n > 1 ? forward / (n - 1) : 1,\n };\n}\n\nexport interface RampOptions {\n /**\n * Largest allowed single-step increase, as a MULTIPLE of the average forward\n * step. A step steeper than this reads as a difficulty cliff (default 3\u00D7).\n */\n maxJumpFactor?: number;\n /** Absolute floor for the jump envelope so tiny early steps don't over-constrain (default 2). */\n minJumpAllowance?: number;\n /** Minimum fraction of steps that must rise-or-hold \u2014 forward progress (default 0.6). */\n minForwardFraction?: number;\n /** Minimum distinct difficulty values \u2014 variety, not a flat line (default 3). */\n minDistinct?: number;\n /** Require the last level to be within this fraction of the peak (default 0.8 = finale \u2265 80% of max). */\n finaleFraction?: number;\n}\n\n/**\n * Audit a difficulty curve. `difficulty[i]` is the i-th level's difficulty proxy\n * \u2014 typically the solver's solution depth, but any monotone measure works. Returns\n * the specific curve sins found (empty array = a well-shaped ramp).\n */\nexport function rampIssues(difficulty: readonly number[], opts: RampOptions = {}): string[] {\n const maxJumpFactor = opts.maxJumpFactor ?? 3;\n const minJumpAllowance = opts.minJumpAllowance ?? 2;\n const minForward = opts.minForwardFraction ?? 0.6;\n const minDistinct = opts.minDistinct ?? 3;\n const finaleFraction = opts.finaleFraction ?? 0.8;\n const issues: string[] = [];\n const n = difficulty.length;\n if (n < 2) {\n issues.push(`ramp has ${n} level(s) \u2014 need at least 2 to form a curve`);\n return issues;\n }\n const s = rampStats(difficulty);\n\n // 1. Escalation: the finale should be at or near the hardest point.\n if (difficulty[n - 1] < difficulty[0]) {\n issues.push(`curve descends overall: finale (${difficulty[n - 1]}) is easier than the opener (${difficulty[0]}) \u2014 the game gets EASIER`);\n }\n if (s.max > 0 && difficulty[n - 1] < s.max * finaleFraction) {\n issues.push(`finale (${difficulty[n - 1]}) is well below the peak (${s.max}) \u2014 the hardest level is buried mid-campaign, so it ends on an anticlimax`);\n }\n\n // 2. No cliffs: bound the steepest single jump against the average forward step.\n let riseSum = 0;\n let riseCount = 0;\n for (let i = 1; i < n; i++) {\n const step = difficulty[i] - difficulty[i - 1];\n if (step > 0) {\n riseSum += step;\n riseCount++;\n }\n }\n const avgRise = riseCount > 0 ? riseSum / riseCount : 0;\n const jumpCeiling = Math.max(minJumpAllowance, avgRise * maxJumpFactor);\n for (let i = 1; i < n; i++) {\n const step = difficulty[i] - difficulty[i - 1];\n if (step > jumpCeiling) {\n issues.push(`difficulty cliff at level ${i + 1}: jumps ${difficulty[i - 1]}\u2192${difficulty[i]} (+${step}), past the +${jumpCeiling.toFixed(1)} envelope \u2014 smooth it with an intermediate level`);\n }\n }\n\n // 3. Rhythm: forward progress must dominate (dips are fine, a downhill slide isn't).\n if (s.forwardFraction < minForward) {\n issues.push(`only ${(s.forwardFraction * 100).toFixed(0)}% of steps make progress (need \u2265 ${(minForward * 100).toFixed(0)}%) \u2014 the curve wanders/descends instead of building`);\n }\n\n // 4. Variety: not a flat line.\n if (s.distinct < minDistinct) {\n issues.push(`only ${s.distinct} distinct difficulty value(s) across ${n} levels (need \u2265 ${minDistinct}) \u2014 the curve is flat; levels don't actually differ in challenge`);\n }\n\n return dedupe(issues);\n}\n\n/**\n * Assert a difficulty curve is well-shaped (throws with the first issue if not).\n * The campaign-level analogue of `assertSolvable` \u2014 one call gates the ramp.\n */\nexport function assertRamp(difficulty: readonly number[], opts: RampOptions = {}): void {\n const issues = rampIssues(difficulty, opts);\n if (issues.length) {\n throw new Error(`hayao: difficulty ramp is ill-shaped \u2014 ${issues[0]}`);\n }\n}\n", "// Filmstrip: sampled frames of a run composed into ONE SVG contact sheet, so\n// the \"judge looks from a headless screenshot\" step can see MOTION \u2014 pacing,\n// readability during play, layering under load \u2014 not a single posed frame.\n// Looks only, never correctness: state was already proven numerically.\n\nimport type { World } from '../world';\nimport { commandsToSVGInner } from '../render/svgString';\n\nexport interface FilmstripOptions {\n /** The game's view size (defineGame width/height). */\n width: number;\n height: number;\n background?: string;\n /** How many panels to sample across the run (default 12, min 2). */\n panels?: number;\n /** Panels per row (default 4). */\n cols?: number;\n /** Rendered width of one panel in px (default 320). */\n panelWidth?: number;\n}\n\n/**\n * Step `world` through per-frame actions, sampling evenly spaced panels\n * (always including the first and last frame), and return one standalone SVG.\n * Panel labels are frame numbers plus sim seconds at the 60Hz convention.\n */\nexport function renderFilmstrip(world: World, frames: string[][], opts: FilmstripOptions): string {\n const panels = Math.max(2, opts.panels ?? 12);\n const every = Math.max(1, Math.ceil(frames.length / (panels - 1)));\n // Each panel salts its gradient/shadow <defs> ids with its own prefix so the\n // composited document never cross-references (SVG `url(#\u2026)` is document-global).\n const shots: { frame: number; inner: string }[] = [{ frame: 0, inner: commandsToSVGInner(world.render(), 'p0') }];\n for (let i = 0; i < frames.length; i++) {\n world.step(frames[i]);\n if ((i + 1) % every === 0 || i === frames.length - 1) {\n shots.push({ frame: i + 1, inner: commandsToSVGInner(world.render(), `p${shots.length}`) });\n }\n }\n\n const cols = Math.max(1, opts.cols ?? 4);\n const pw = opts.panelWidth ?? 320;\n const ph = Math.round((pw * opts.height) / opts.width);\n const labelH = 18;\n const gap = 8;\n const cellW = pw + gap;\n const cellH = ph + labelH + gap;\n const rows = Math.ceil(shots.length / cols);\n const totalW = cols * cellW + gap;\n const totalH = rows * cellH + gap;\n const bg = opts.background ?? '#ffffff';\n\n const cells = shots\n .map((s, i) => {\n const x = gap + (i % cols) * cellW;\n const y = gap + Math.floor(i / cols) * cellH;\n return (\n `<g transform=\"translate(${x} ${y})\">` +\n `<svg width=\"${pw}\" height=\"${ph}\" viewBox=\"0 0 ${opts.width} ${opts.height}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${opts.width}\" height=\"${opts.height}\" fill=\"${bg}\"/>` +\n s.inner +\n `</svg>` +\n `<rect x=\"0\" y=\"0\" width=\"${pw}\" height=\"${ph}\" fill=\"none\" stroke=\"#999\" stroke-width=\"1\"/>` +\n `<text x=\"${pw / 2}\" y=\"${ph + 13}\" font-size=\"11\" font-family=\"monospace\" text-anchor=\"middle\" fill=\"#555\">` +\n `f ${s.frame} \u00B7 ${(s.frame / 60).toFixed(1)}s</text>` +\n `</g>`\n );\n })\n .join('');\n\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${totalW} ${totalH}\" width=\"${totalW}\" height=\"${totalH}\">` +\n `<rect x=\"0\" y=\"0\" width=\"${totalW}\" height=\"${totalH}\" fill=\"#f4f4f2\"/>` +\n cells +\n `</svg>`\n );\n}\n", "// Audio filmstrip: the \"judge looks from a headless artifact\" step, for sound.\n// A rendered StereoBuffer can't be heard in CI, so we make it VISIBLE and\n// MEASURABLE \u2014 a standalone SVG with a waveform overview, a log-magnitude\n// spectrogram, and the extracted feature vector printed alongside. State (the\n// notes, the mix) was already proven numerically; this is looks-and-listens\n// only, exactly mirroring renderFilmstrip for the visual channel.\n\nimport { dlog10 } from '../core/dmath';\nimport { type StereoBuffer, type Samples } from '../audio/pcm';\nimport { features, magnitudeSpectrum, type AudioFeatures } from '../audio/analysis';\n\nexport interface AudioFilmstripOptions {\n /** Overall SVG width in px (default 900). */\n width?: number;\n /** Time columns in the spectrogram (default 220). */\n timeBins?: number;\n /** Frequency bands in the spectrogram (default 64). */\n freqBands?: number;\n /** Title shown above the strip. */\n title?: string;\n}\n\n/** Downmix to mono for analysis (average of the two channels). */\nfunction mono(buf: StereoBuffer): Samples {\n const n = buf.left.length;\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) out[i] = (buf.left[i] + buf.right[i]) * 0.5;\n return out;\n}\n\n/** Peak-per-column min/max for a compact waveform overview. */\nfunction waveformPath(ch: Samples, cols: number, w: number, h: number, midY: number): string {\n const per = Math.max(1, Math.floor(ch.length / cols));\n let up = `M0 ${midY}`;\n let dn = '';\n for (let c = 0; c < cols; c++) {\n let mn = 0;\n let mx = 0;\n const start = c * per;\n for (let i = 0; i < per && start + i < ch.length; i++) {\n const v = ch[start + i];\n if (v > mx) mx = v;\n if (v < mn) mn = v;\n }\n const x = (c / cols) * w;\n up += ` L${x.toFixed(1)} ${(midY - mx * (h / 2)).toFixed(1)}`;\n dn = ` L${x.toFixed(1)} ${(midY - mn * (h / 2)).toFixed(1)}` + dn;\n }\n return up + dn + ' Z';\n}\n\n/**\n * Render an audio filmstrip SVG for a stereo buffer: L/R waveforms, a\n * spectrogram heatmap, and the feature readout. Deterministic and standalone\n * (inline styles, no external refs) so it drops straight into t.artifact().\n */\nexport function renderAudioFilmstrip(buf: StereoBuffer, opts: AudioFilmstripOptions = {}): string {\n const W = opts.width ?? 900;\n const tBins = opts.timeBins ?? 220;\n const fBands = opts.freqBands ?? 64;\n const pad = 16;\n const inner = W - pad * 2;\n const waveH = 70;\n const specH = 200;\n const featH = 84;\n const H = pad * 5 + waveH * 2 + specH + featH;\n\n const f = features(mono(buf));\n\n // \u2500\u2500 waveforms \u2500\u2500\n const lPath = waveformPath(buf.left, tBins, inner, waveH, waveH / 2);\n const rPath = waveformPath(buf.right, tBins, inner, waveH, waveH / 2);\n\n // \u2500\u2500 spectrogram \u2500\u2500 frame the mono signal, log-compress magnitudes to alpha\n const m = mono(buf);\n const frameSize = 2048;\n const hop = Math.max(1, Math.floor(m.length / tBins));\n const cellW = inner / tBins;\n const cellH = specH / fBands;\n let cells = '';\n for (let c = 0; c < tBins; c++) {\n const start = c * hop;\n if (start + 64 >= m.length) break;\n const mag = magnitudeSpectrum(m.subarray(start, Math.min(start + frameSize, m.length)));\n if (mag.length === 0) continue;\n const binsPerBand = Math.max(1, Math.floor(mag.length / fBands));\n for (let b = 0; b < fBands; b++) {\n let e = 0;\n for (let k = 0; k < binsPerBand; k++) e += mag[b * binsPerBand + k] ?? 0;\n // log-compress: map ~[-60,0] dB \u2192 [0,1] alpha\n const db = e > 1e-6 ? 20 * dlog10(e) : -120;\n const a = Math.max(0, Math.min(1, (db + 60) / 60));\n if (a < 0.03) continue;\n const x = pad + c * cellW;\n const y = pad * 3 + waveH * 2 + specH - (b + 1) * cellH; // low freq at bottom\n const col = specColor(a);\n cells += `<rect x=\"${x.toFixed(1)}\" y=\"${y.toFixed(1)}\" width=\"${(cellW + 0.6).toFixed(1)}\" height=\"${(cellH + 0.6).toFixed(1)}\" fill=\"${col}\"/>`;\n }\n }\n\n const featText = featureLines(f)\n .map((line, i) => `<text x=\"${pad + 4}\" y=\"${H - featH + 20 + i * 18}\" font-family=\"monospace\" font-size=\"12\" fill=\"#e8e4d8\">${line}</text>`)\n .join('');\n\n const y0 = pad;\n const y1 = pad * 2 + waveH;\n const yLabelWave = (label: string, y: number) =>\n `<text x=\"${pad}\" y=\"${y - 3}\" font-family=\"monospace\" font-size=\"10\" fill=\"#8a8474\">${label}</text>`;\n\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${W} ${H}\" width=\"${W}\" height=\"${H}\">` +\n `<rect width=\"${W}\" height=\"${H}\" fill=\"#1a1814\"/>` +\n (opts.title ? `<text x=\"${pad}\" y=\"${pad - 3}\" font-family=\"monospace\" font-size=\"12\" fill=\"#d8b25a\">${escapeXml(opts.title)}</text>` : '') +\n // waveforms\n yLabelWave('L', y0) +\n `<g transform=\"translate(${pad} ${y0})\"><rect width=\"${inner}\" height=\"${waveH}\" fill=\"#211e18\"/><path d=\"${lPath}\" fill=\"#5a9ac4\" opacity=\"0.9\"/></g>` +\n yLabelWave('R', y1) +\n `<g transform=\"translate(${pad} ${y1})\"><rect width=\"${inner}\" height=\"${waveH}\" fill=\"#211e18\"/><path d=\"${rPath}\" fill=\"#5ac48f\" opacity=\"0.9\"/></g>` +\n // spectrogram\n `<rect x=\"${pad}\" y=\"${pad * 3 + waveH * 2}\" width=\"${inner}\" height=\"${specH}\" fill=\"#0d0c0a\"/>` +\n cells +\n // features\n `<rect x=\"${pad}\" y=\"${H - featH}\" width=\"${inner}\" height=\"${featH - pad}\" fill=\"#211e18\"/>` +\n featText +\n `</svg>`\n );\n}\n\n/** Warm heat ramp (washi/ember palette) for spectrogram energy. */\nfunction specColor(a: number): string {\n // dark \u2192 shu red \u2192 gold, keeping it on-brand and legible on dark\n const r = Math.round(40 + a * 200);\n const g = Math.round(20 + a * a * 150);\n const b = Math.round(30 + a * 40);\n return `rgb(${r},${g},${b})`;\n}\n\nfunction featureLines(f: AudioFeatures): string[] {\n return [\n `dur ${f.durationSec.toFixed(2)}s peak ${f.peakDb.toFixed(1)} dBFS rms ${f.rms.toFixed(3)}`,\n `centroid ${Math.round(f.centroidHz)} Hz zcr ${Math.round(f.zcr)}/s`,\n `tempo ~${Math.round(f.tempoBpm)} bpm onsets ${f.onsetDensity.toFixed(1)}/s`,\n ];\n}\n\nfunction escapeXml(s: string): string {\n return s.replace(/[<>&]/g, (c) => (c === '<' ? '<' : c === '>' ? '>' : '&'));\n}\n\nexport interface AudioExpectation {\n minDurationSec?: number;\n maxDurationSec?: number;\n maxPeakDb?: number; // e.g. -1 to guarantee headroom / no clipping\n minRms?: number; // guarantee it isn't silent\n minCentroidHz?: number;\n maxCentroidHz?: number;\n tempoBpm?: number; // expected tempo\u2026\n tempoToleranceBpm?: number; // \u2026within this tolerance (default 12)\n}\n\nexport interface AudioAssertion {\n ok: boolean;\n failures: string[];\n features: AudioFeatures;\n}\n\n/**\n * Assert a rendered buffer's measured features against an expectation. This is\n * the numeric half of the audio channel \u2014 what a verify.ts suite calls to prove\n * \"this track is a ~120bpm piece that isn't clipping and isn't silent\".\n */\nexport function assertAudio(buf: StereoBuffer, exp: AudioExpectation): AudioAssertion {\n const f = features(mono(buf));\n const failures: string[] = [];\n const chk = (cond: boolean, msg: string) => {\n if (!cond) failures.push(msg);\n };\n if (exp.minDurationSec !== undefined) chk(f.durationSec >= exp.minDurationSec, `duration ${f.durationSec.toFixed(2)}s < min ${exp.minDurationSec}`);\n if (exp.maxDurationSec !== undefined) chk(f.durationSec <= exp.maxDurationSec, `duration ${f.durationSec.toFixed(2)}s > max ${exp.maxDurationSec}`);\n if (exp.maxPeakDb !== undefined) chk(f.peakDb <= exp.maxPeakDb, `peak ${f.peakDb.toFixed(1)}dB > max ${exp.maxPeakDb}`);\n if (exp.minRms !== undefined) chk(f.rms >= exp.minRms, `rms ${f.rms.toFixed(3)} < min ${exp.minRms} (too quiet?)`);\n if (exp.minCentroidHz !== undefined) chk(f.centroidHz >= exp.minCentroidHz, `centroid ${Math.round(f.centroidHz)}Hz < min ${exp.minCentroidHz}`);\n if (exp.maxCentroidHz !== undefined) chk(f.centroidHz <= exp.maxCentroidHz, `centroid ${Math.round(f.centroidHz)}Hz > max ${exp.maxCentroidHz}`);\n if (exp.tempoBpm !== undefined) {\n const tol = exp.tempoToleranceBpm ?? 12;\n chk(Math.abs(f.tempoBpm - exp.tempoBpm) <= tol, `tempo ${Math.round(f.tempoBpm)}bpm not within ${tol} of ${exp.tempoBpm}`);\n }\n return { ok: failures.length === 0, failures, features: f };\n}\n", "// The World: the deterministic simulation container. Owns the root scene, the\n// rng, the clock, the input state, an event bus, and a resource table. Advancing\n// the world is `step()` \u2014 a pure function of (previous state, input frame).\n\nimport { Clock, type ClockConfig } from './core/clock';\nimport { EventBus } from './core/events';\nimport { hashValue } from './core/hash';\nimport { Rng } from './core/rng';\nimport { InputState, type AxisFrame } from './input/actions';\nimport { Node, resetNodeIds, type WorldContext } from './scene/node';\nimport { deserializeNode } from './scene/registry';\nimport type { Camera2D } from './scene/nodes';\nimport { IDENTITY, applyTransform, composeTransform, invertTransform, makeTransform, type Transform, type Vec2 } from './core/math';\nimport type { DrawCommand } from './render/commands';\n\nexport interface WorldConfig {\n seed?: number;\n clock?: ClockConfig;\n /** Design-space dimensions (default 1280\u00D7720). */\n width?: number;\n height?: number;\n /** Resolved tuning values (see app/tuning.ts). Sim state: hashed + snapshotted. */\n tuning?: Record<string, number | string>;\n /**\n * Dev guard: during each step(), `Math.random`/`Date.now` are wrapped so a\n * stray call inside the sim warns ONCE (with a stack hint) instead of\n * silently breaking determinism. Never throws; safe to leave on in tests.\n */\n guardDeterminism?: boolean;\n}\n\n/** Default engine event map; games extend it with their own keys. */\nexport interface CoreEvents {\n [key: string]: unknown;\n}\n\nexport class World<TState extends Record<string, unknown> = Record<string, unknown>> implements WorldContext {\n readonly rng: Rng;\n readonly clock: Clock;\n readonly input = new InputState();\n readonly events = new EventBus<CoreEvents>();\n readonly resources = new Map<string, unknown>();\n /**\n * Canonical game state that lives OUTSIDE the scene tree (pure-sim structs,\n * controllers). Must be plain JSON-serializable data: it is included in\n * `hash()` and `snapshot()`, so hidden state here cannot escape determinism\n * checks the way ad-hoc module variables can.\n */\n state: TState = {} as TState;\n readonly width: number;\n readonly height: number;\n /**\n * Pause switch. While true, only `pauseMode: 'always'` subtrees update \u2014\n * rendering, input sampling, and the clock keep ticking, so a pause menu\n * (an 'always' subtree) stays live. Sim state: hashed + snapshotted, but\n * only when true, so pinned hashes of unpaused games are unchanged.\n */\n paused = false;\n /**\n * Sim-time multiplier: the tree receives `clock.dt * timeScale` (slow-mo /\n * fast-forward), while `'always'` subtrees get the unscaled dt so UI keeps\n * realtime feel. The clock itself ticks normally. Hashed/snapshotted only\n * when \u2260 1.\n */\n timeScale = 1;\n\n root: Node;\n activeCamera: Camera2D | null = null;\n\n private seed: number;\n private freeQueue: Node[] = [];\n private started = false;\n private tuningValues: Record<string, number | string>;\n private guardDeterminism: boolean;\n private warnedClamp = false;\n private warnedNondet = false;\n\n constructor(config: WorldConfig = {}) {\n this.seed = config.seed ?? 1;\n this.rng = new Rng(this.seed);\n this.clock = new Clock(config.clock);\n this.width = config.width ?? 1280;\n this.height = config.height ?? 720;\n this.tuningValues = { ...(config.tuning ?? {}) };\n this.guardDeterminism = config.guardDeterminism ?? false;\n this.root = new Node({ name: 'root' });\n }\n\n /**\n * Read a tuning value resolved at world creation (declared default unless\n * overridden). Throws on an undeclared key \u2014 a typo here would otherwise\n * silently read `undefined` into the sim.\n */\n tune<T extends number | string = number>(key: string): T {\n const v = this.tuningValues[key];\n if (v === undefined) throw new Error(`tune('${key}'): no such knob declared in the game's tuning spec`);\n return v as T;\n }\n\n /**\n * Read a shared resource by key. Throws on a missing key (listing what IS\n * available) \u2014 a typo here would otherwise silently read `undefined` into\n * the sim, exactly like an undeclared tuning knob.\n */\n resource<T>(key: string): T {\n if (!this.resources.has(key)) {\n const available = [...this.resources.keys()].join(', ') || '(none)';\n throw new Error(`resource('${key}'): not set. Available: ${available}`);\n }\n return this.resources.get(key) as T;\n }\n\n get time(): number {\n return this.clock.simTimeSec;\n }\n get frame(): number {\n return this.clock.frame;\n }\n\n /** Replace the scene root, entering the tree. */\n setRoot(node: Node): void {\n if (this.root) this.root.exitTree();\n this.root = node;\n this.started = false;\n }\n\n requestFree(node: Node): void {\n this.freeQueue.push(node);\n }\n\n private ensureStarted(): void {\n if (!this.started) {\n this.root.enterTree(this);\n this.started = true;\n }\n }\n\n /**\n * Advance exactly one fixed step with the given actions held down.\n * This is THE deterministic transition \u2014 call it from Node or the browser loop.\n */\n step(actionsDown: Iterable<string> = [], axes?: AxisFrame): void {\n if (typeof actionsDown === 'string' || typeof (actionsDown as Iterable<string>)[Symbol.iterator] !== 'function') {\n throw new TypeError(`step(actionsDown): pass an array/iterable of action names, got ${typeof actionsDown === 'string' ? `the string '${actionsDown}'` : typeof actionsDown}`);\n }\n this.ensureStarted();\n const unguard = this.guardDeterminism ? this.installGuard() : null;\n try {\n this.input.beginFrame(actionsDown, axes);\n // Scaled dt drives the sim; the unscaled dt rides along for 'always' subtrees.\n this.root.updateTree(this.clock.dt * this.timeScale, this.clock.dt, 'pausable', this.paused);\n this.flushFree();\n this.clock.tick();\n } finally {\n unguard?.();\n }\n }\n\n /**\n * Wrap `Math.random`/`Date.now` for the duration of a step so a stray call\n * inside the sim warns ONCE per world (with a stack hint) \u2014 the values still\n * flow through, so nothing breaks mid-frame. Returns the restore function;\n * properly nested re-entry (a world stepped inside another's step) is safe\n * because each install restores exactly what it replaced.\n */\n private installGuard(): () => void {\n const mathObj = globalThis.Math;\n const realRandom = mathObj.random;\n const realNow = globalThis.Date.now;\n const warn = (what: string) => {\n if (this.warnedNondet) return;\n this.warnedNondet = true;\n const stack = new Error().stack?.split('\\n').slice(2, 5).join('\\n') ?? '';\n console.warn(`hayao: ${what} called during step() \u2014 nondeterministic. Use world.rng / ctx.time instead.\\n${stack}`);\n };\n // Note: names below omit the call parens so the invariants lint (which\n // greps for literal nondeterministic CALLS) doesn't flag the guard itself.\n mathObj.random = () => {\n warn('Math.random');\n return realRandom.call(mathObj);\n };\n globalThis.Date.now = () => {\n warn('Date.now');\n return realNow.call(globalThis.Date);\n };\n return () => {\n mathObj.random = realRandom;\n globalThis.Date.now = realNow;\n };\n }\n\n /**\n * Feed REAL elapsed ms; runs 0+ fixed steps. Returns steps run. This is the\n * realtime driver entry point \u2014 it CLAMPS realMs to the clock's maxFrameMs\n * (default 250) to avoid a spiral of death, so `advance(1200)` runs ~15 steps,\n * not 72. For headless tests/harnesses that want to fast-forward an exact\n * number of steps, use `runSteps(n)` or `step()` \u2014 never `advance` with a big ms.\n */\n advance(realMs: number, actionsDown: Iterable<string> = [], axes?: AxisFrame): number {\n if (realMs > this.clock.maxFrameMs && !this.warnedClamp) {\n this.warnedClamp = true;\n console.warn(`hayao: advance(${realMs}) exceeds maxFrameMs (${this.clock.maxFrameMs}) and is clamped \u2014 a realtime driver must never spiral. To fast-forward an exact number of steps, use runSteps(n).`);\n }\n const steps = this.clock.advance(realMs);\n for (let i = 0; i < steps; i++) this.step(actionsDown, axes);\n return steps;\n }\n\n /**\n * Run exactly `n` fixed steps \u2014 the deterministic fast-forward for tests and\n * headless drivers (unlike `advance`, no realtime clamp). Pass `actionsFor(i)`\n * to script the input per step; omit it to hold nothing down.\n */\n runSteps(n: number, actionsFor?: (i: number) => Iterable<string>, axesFor?: (i: number) => AxisFrame | undefined): void {\n for (let i = 0; i < n; i++) this.step(actionsFor ? actionsFor(i) : [], axesFor?.(i));\n }\n\n /**\n * Run pending frees NOW instead of at the end of the step. `free()` is\n * deferred (safe during iteration), which means freed nodes survive until\n * the step ends \u2014 during a scene swap that lets old nodes contaminate the\n * first frame of the new scene. Pattern: `oldRoot.free(); world.flushFree();\n * buildNewScene()`. Called automatically at the end of every step.\n */\n flushFree(): void {\n if (this.freeQueue.length === 0) return;\n const q = this.freeQueue;\n this.freeQueue = [];\n for (const node of q) {\n node.exitTree();\n node.parent?.removeChild(node);\n if (this.activeCamera === node) this.activeCamera = null;\n }\n }\n\n // \u2500\u2500 Tree inspection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Visit every live node depth-first (root first, child-index order). */\n walk(fn: (node: Node) => void): void {\n const visit = (n: Node): void => {\n fn(n);\n for (const c of n.children) visit(c);\n };\n visit(this.root);\n }\n\n /** Total live nodes in the tree (root included). */\n get nodeCount(): number {\n let n = 0;\n this.walk(() => n++);\n return n;\n }\n\n /**\n * One indented line per node \u2014 `name (type) [flags] @x,y` \u2014 for quick tree\n * audits in a REPL or test failure message.\n */\n debugTree(): string {\n const lines: string[] = [];\n const visit = (n: Node, depth: number): void => {\n const flags: string[] = [];\n if (n.cosmetic) flags.push('cosmetic');\n if (n.screenSpace) flags.push('screenSpace');\n if (n.pauseMode !== 'inherit') flags.push(n.pauseMode);\n if (!n.visible) flags.push('!visible');\n lines.push(`${' '.repeat(depth)}${n.name} (${n.type})${flags.length > 0 ? ` [${flags.join(' ')}]` : ''} @${n.pos.x},${n.pos.y}`);\n for (const c of n.children) visit(c, depth + 1);\n };\n visit(this.root, 0);\n return lines.join('\\n');\n }\n\n /** The active camera's world position + zoom, or null (see WorldContext.camera). */\n camera(): { pos: { x: number; y: number }; zoom: number } | null {\n if (!this.activeCamera) return null;\n const wt = this.activeCamera.worldTransform();\n return { pos: { x: wt.e, y: wt.f }, zoom: this.activeCamera.zoom };\n }\n\n // \u2500\u2500 Rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** The view transform (inverse of the active camera), mapping world \u2192 screen. */\n viewTransform(): Transform {\n if (!this.activeCamera) return IDENTITY;\n const cam = this.activeCamera;\n // Center the camera in design space, apply zoom, then invert.\n const camWorld = cam.worldTransform();\n const centered = composeTransform(makeTransform({ x: this.width / 2, y: this.height / 2 }, 0, { x: cam.zoom, y: cam.zoom }), invertTransform(camWorld));\n return centered;\n }\n\n /**\n * Map a world-space point to screen/design space (the forward view transform).\n * With no active camera this is the identity, so world == screen.\n */\n worldToScreen(p: Vec2): Vec2 {\n return applyTransform(this.viewTransform(), p);\n }\n\n /**\n * Map a screen/design-space point back to world space \u2014 the inverse of the\n * view transform. Use this to turn a pointer position (in design units) into\n * a world coordinate under a scrolled/zoomed camera. Keep raw pointer values\n * OUT of the sim: convert at the host edge and feed the result in as a\n * quantized action/axis, or determinism breaks (see docs/CONVENTIONS.md).\n */\n screenToWorld(p: Vec2): Vec2 {\n return applyTransform(invertTransform(this.viewTransform()), p);\n }\n\n /** Project the whole scene to a display list (already camera-applied). */\n render(): DrawCommand[] {\n this.ensureStarted();\n const out: DrawCommand[] = [];\n this.root.collectDraw(out, this.viewTransform());\n return out;\n }\n\n // \u2500\u2500 Determinism & saves \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Deterministic structural hash of the whole sim state. */\n hash(): string {\n return hashValue({\n seed: this.seed,\n rng: this.rng.getState(),\n clock: this.clock.getState(),\n input: this.input.getState(),\n state: this.state,\n tree: this.root.serialize(),\n // Only when declared, so games without tuning keep their pinned hashes.\n ...(Object.keys(this.tuningValues).length > 0 ? { tuning: this.tuningValues } : {}),\n // Same guard: only when non-default, so pre-pause pinned hashes survive.\n ...(this.paused ? { paused: true } : {}),\n ...(this.timeScale !== 1 ? { timeScale: this.timeScale } : {}),\n });\n }\n\n /** Compact snapshot for undo/time-travel and saves. */\n snapshot(): WorldSnapshot {\n return {\n seed: this.seed,\n rng: this.rng.getState(),\n clock: this.clock.getState(),\n input: this.input.getState(),\n state: structuredClone(this.state),\n tree: this.root.serialize(),\n tuning: { ...this.tuningValues },\n // Only when non-default, so pre-pause snapshots stay byte-identical.\n ...(this.paused ? { paused: true } : {}),\n ...(this.timeScale !== 1 ? { timeScale: this.timeScale } : {}),\n };\n }\n\n /** Restore a snapshot. Rebuilds the tree from data (behaviors are re-attached by scene code). */\n restore(snap: WorldSnapshot): void {\n this.seed = snap.seed;\n this.rng.setState(snap.rng);\n this.clock.setState(snap.clock);\n this.input.setState(snap.input);\n this.state = structuredClone(snap.state) as TState;\n if (snap.tuning) this.tuningValues = { ...snap.tuning };\n this.paused = snap.paused ?? false;\n this.timeScale = snap.timeScale ?? 1;\n resetNodeIds(1_000_000); // avoid id collisions with the live session\n this.setRoot(deserializeNode(snap.tree));\n this.ensureStarted();\n }\n\n /** A compact probe snapshot for the verification harness (override-friendly). */\n probe(): Record<string, unknown> {\n return {\n frame: this.frame,\n time: this.time,\n hash: this.hash(),\n nodes: this.root.query('Sprite').length + this.root.query('Text').length,\n };\n }\n}\n\nexport interface WorldSnapshot {\n seed: number;\n rng: ReturnType<Rng['getState']>;\n clock: ReturnType<Clock['getState']>;\n input: ReturnType<InputState['getState']>;\n state: Record<string, unknown>;\n tree: ReturnType<Node['serialize']>;\n /** Resolved tuning values (absent in pre-tuning saves). */\n tuning?: Record<string, number | string>;\n /** Pause flag (absent when false \u2014 keeps old snapshots byte-identical). */\n paused?: boolean;\n /** Sim-time multiplier (absent when 1). */\n timeScale?: number;\n}\n", "// Tuning: declared, live-adjustable parameters. A game declares its knobs once\n// (`tuning` on the GameDefinition); `createWorld` resolves declared defaults +\n// overrides into plain values the sim reads via `world.tune()`. Resolved values\n// are sim state \u2014 hashed and snapshotted \u2014 so a knob change can never escape the\n// determinism checks. The declared defaults ARE the config: code stays the\n// source of truth, and Studio overrides are session data, never a second config.\n\nimport type { GameDefinition } from './game';\n\nexport type TuningValue = number | string;\nexport type TuningValues = Record<string, TuningValue>;\n\nexport interface TuningKnob {\n key: string;\n /** Human label for panels; defaults to the key. */\n label?: string;\n type: 'number' | 'color' | 'enum';\n default: TuningValue;\n /** number knobs: slider bounds + resolution. */\n min?: number;\n max?: number;\n step?: number;\n /** enum knobs: the allowed values. */\n options?: string[];\n /** Panel grouping (e.g. 'jump', 'combat', 'style'). */\n group?: string;\n /**\n * Pure-view knob (palette, fonts): eligible for cheap re-apply without a sim\n * rebuild. Sim-affecting knobs leave this unset.\n */\n cosmetic?: boolean;\n}\n\nexport interface TuningSpec {\n knobs: TuningKnob[];\n}\n\n/**\n * A named alternative of a game for A/B playtesting: a tuning preset and/or a\n * definition patch. Tuning-only variants can hot-swap mid-play (rebuild with\n * snapshot carryover); `patch` variants restart fresh.\n */\nexport interface Variant {\n label: string;\n tuning?: TuningValues;\n patch?(def: GameDefinition): GameDefinition;\n}\n\n/** Sugar for declaring knobs without repeating the key in a label. */\nexport const knob = {\n num(key: string, opts: { default: number; min?: number; max?: number; step?: number; label?: string; group?: string; cosmetic?: boolean }): TuningKnob {\n return { key, type: 'number', ...opts };\n },\n color(key: string, opts: { default: string; label?: string; group?: string; cosmetic?: boolean }): TuningKnob {\n return { key, type: 'color', cosmetic: true, ...opts };\n },\n enumOf(key: string, opts: { default: string; options: string[]; label?: string; group?: string; cosmetic?: boolean }): TuningKnob {\n return { key, type: 'enum', ...opts };\n },\n};\n\n/**\n * Resolve a spec + overrides into concrete values: declared defaults first,\n * overrides applied only for DECLARED keys (unknown keys are dropped \u2014 a typo'd\n * override must not smuggle undeclared state into the hash), numbers clamped to\n * [min, max] and coerced, enum values validated against `options`.\n */\nexport function resolveTuning(spec: TuningSpec | undefined, overrides?: TuningValues): TuningValues {\n const out: TuningValues = {};\n if (!spec) return out;\n for (const k of spec.knobs) {\n out[k.key] = k.default;\n const o = overrides?.[k.key];\n if (o === undefined) continue;\n if (k.type === 'number') {\n const n = typeof o === 'number' ? o : Number(o);\n if (!Number.isFinite(n)) continue;\n const lo = k.min ?? -Infinity;\n const hi = k.max ?? Infinity;\n out[k.key] = Math.min(hi, Math.max(lo, n));\n } else if (k.type === 'enum') {\n if (typeof o === 'string' && (k.options ?? []).includes(o)) out[k.key] = o;\n } else {\n if (typeof o === 'string') out[k.key] = o;\n }\n }\n return out;\n}\n", "// The project system. A game is a data definition: dimensions, input map, and a\n// build() that constructs the initial scene tree. `createWorld` turns it into a\n// live deterministic World \u2014 used identically by the browser driver, the headless\n// runner, and every test. That symmetry is the whole point.\n\nimport { World } from '../world';\nimport type { Node } from '../scene/node';\nimport { DEFAULT_INPUT_MAP, type InputLog, type InputMap } from '../input/actions';\nimport type { ClockConfig } from '../core/clock';\nimport { resolveTuning, type TuningSpec, type TuningValues } from './tuning';\n\n/**\n * Optional boot splash. Rendered by the engine (so its colors are palette-guaranteed\n * and never trip a contrast escape the way a hand-rolled loading <div> can) while\n * `preload` runs. Pass `splash: false` to opt out entirely.\n */\nexport interface SplashConfig {\n /** Splash headline (defaults to the game title). */\n title?: string;\n /** Background/foreground pair; defaults to a contrast-guaranteed pair from the game background. */\n palette?: { bg: string; fg: string };\n /** Keep the splash up at least this long, so a fast preload doesn't flash by. */\n minDurationMs?: number;\n}\n\nexport interface GameDefinition<TState extends Record<string, unknown> = Record<string, unknown>> {\n title: string;\n width?: number;\n height?: number;\n seed?: number;\n background?: string;\n clock?: ClockConfig;\n inputMap?: InputMap;\n /** Build the initial scene tree for a fresh world. */\n build(world: World<TState>): Node;\n /** Optional compact probe snapshot for verification (defaults to World.probe). */\n probe?(world: World<TState>): Record<string, unknown>;\n /**\n * Live-tunable parameters, declared once. Defaults ARE the config; Studio and\n * tests override them via `createWorld(def, { tuning })` and the sim reads\n * resolved values with `world.tune(key)`. Values are hashed + snapshotted.\n */\n tuning?: TuningSpec;\n /**\n * Re-attach behaviors/controllers after `world.restore()` rebuilds the tree\n * from data (closures do not survive a restore). One contract serves every\n * carryover path: Studio knob changes, variant toggles, HMR, and net rollback.\n */\n attach?(world: World<TState>): void;\n /**\n * Awaited before the world starts stepping \u2014 load fonts, sprite atlases, a\n * SoundFont, anything async. The engine holds a splash on screen until it\n * resolves, so there is no asset pop-in and no ungoverned pre-first-frame window.\n */\n preload?(world: World<TState>): Promise<void>;\n /** Boot splash config, or `false` to start on the first frame with no cover. */\n splash?: SplashConfig | false;\n}\n\n/**\n * Identity + defaults. Kept as a function so games read `export default defineGame({\u2026})`.\n * Pass a state shape for a typed world: `defineGame<{ score: number }>({ \u2026 })`\n * types `world.state` in build/probe/attach/preload (default keeps untyped calls as-is).\n */\nexport function defineGame<TState extends Record<string, unknown> = Record<string, unknown>>(\n def: GameDefinition<TState>,\n): Required<Pick<GameDefinition<TState>, 'width' | 'height' | 'seed' | 'inputMap' | 'background'>> & GameDefinition<TState> {\n return {\n width: 1280,\n height: 720,\n seed: 1,\n background: '#f3ecdb',\n inputMap: DEFAULT_INPUT_MAP,\n ...def,\n };\n}\n\nexport interface CreateWorldOptions {\n seed?: number;\n /** Overrides for declared tuning knobs (undeclared keys are dropped). */\n tuning?: TuningValues;\n}\n\n/**\n * Build a live, deterministic World from a game definition. No browser needed.\n * `opts` as a bare number is the legacy seed override.\n */\nexport function createWorld<TState extends Record<string, unknown> = Record<string, unknown>>(def: GameDefinition<TState>, opts?: number | CreateWorldOptions): World<TState> {\n const o: CreateWorldOptions = typeof opts === 'number' ? { seed: opts } : (opts ?? {});\n const world = new World<TState>({\n seed: o.seed ?? def.seed ?? 1,\n width: def.width ?? 1280,\n height: def.height ?? 720,\n clock: def.clock,\n tuning: resolveTuning(def.tuning, o.tuning),\n });\n world.setRoot(def.build(world));\n if (def.probe) {\n // Instance override shadows the prototype method.\n (world as unknown as { probe: () => Record<string, unknown> }).probe = () => def.probe!(world);\n }\n return world;\n}\n\n/** The input map a game uses (with defaults applied). */\nexport function gameInputMap(def: GameDefinition): InputMap {\n return def.inputMap ?? DEFAULT_INPUT_MAP;\n}\n\nexport interface HeadlessResult<TState extends Record<string, unknown> = Record<string, unknown>> {\n world: World<TState>;\n hash: string;\n steps: number;\n}\n\n/**\n * Run a game to completion in Node with no host \u2014 play an input log (or zero\n * steps) and return the final world + state hash. This is what tests, the CI\n * verifier, and replays call. The browser is never involved.\n */\nexport function runHeadless<TState extends Record<string, unknown> = Record<string, unknown>>(def: GameDefinition<TState>, inputLog?: InputLog): HeadlessResult<TState> {\n const world = createWorld(def);\n const frames = inputLog?.frames ?? [];\n for (const f of frames) world.step(f);\n return { world, hash: world.hash(), steps: frames.length };\n}\n", "// The playtest session artifact and its headless replay. A session is a\n// RE-EXECUTABLE, not a recording: (seed, tuning, inputLog, axesLog) reproduce\n// the whole run bit-exactly in Node, so any metric can be computed\n// retroactively and any tick can be re-inspected. Pure module: no DOM \u2014 the\n// browser recorder lives in record.ts, the analyzer and MCP sidecar replay\n// through here.\n\nimport { createWorld, type GameDefinition } from '../app/game';\nimport type { TuningValues } from '../app/tuning';\nimport type { InputLog } from '../input/actions';\nimport type { World, WorldSnapshot } from '../world';\n\n/** Which build/variant produced a session \u2014 a report is never ambiguous about code. */\nexport interface VariantRef {\n name: string;\n kind: 'dev' | 'module' | 'worktree';\n commit?: string;\n}\n\nexport interface ScreenEvent {\n frame: number;\n kind: 'pause' | 'resume' | 'restart' | 'overlay-show' | 'overlay-hide' | 'knob' | 'variant' | 'hot-swap' | 'scrub';\n detail?: string;\n}\n\n/** Wall-clock context the sim can't see (tab hidden \u2260 hesitation). */\nexport interface WallClockMark {\n frame: number;\n /** ms since session start (wall clock \u2014 context only, never sim input). */\n t: number;\n kind: 'visibility-hidden' | 'visibility-visible' | 'blur' | 'focus';\n}\n\nexport interface Annotation {\n frame: number;\n tag: string;\n note?: string;\n}\n\n/** A mid-play tuning change (Studio knob): replay applies it AT its frame. */\nexport interface KnobEvent {\n frame: number;\n key: string;\n value: number | string;\n}\n\nexport type EndReason = 'goal' | 'quit' | 'restart' | 'navigate' | 'idle' | 'hot-swap';\n\nexport interface PlaytestSession {\n id: string;\n game: string;\n startedAt: string;\n /** Git short sha of the code that ran (from the Studio dev server). */\n buildRef: string;\n seed: number;\n variant: VariantRef;\n /** Tuning at session start (resolved values). */\n tuningValues: TuningValues;\n /**\n * When play continued across a code hot-swap, the new segment records the\n * world it resumed FROM \u2014 replay restores it before stepping, so even\n * mid-development sessions stay bit-exactly re-executable.\n */\n startSnapshot?: WorldSnapshot;\n knobEvents: KnobEvent[];\n inputLog: InputLog;\n /** Delta-encoded analog axes: [frame, axis, value] whenever a value changed. */\n axesLog: Array<[number, string, number]>;\n screenEvents: ScreenEvent[];\n wallClockMarks: WallClockMark[];\n annotations: Annotation[];\n endReason: EndReason;\n /** Invited-playtester fields \u2014 creator sessions leave them unset. */\n playerId?: string;\n consent?: { recorded: boolean; at: string };\n}\n\nexport interface ReplayOptions {\n toFrame?: number;\n /** Observer called once with the fresh world BEFORE any step (subscribe to events here). */\n onWorld?: (world: World) => void;\n /** Observer called AFTER each step with the frame index just played. */\n onFrame?: (world: World, frame: number) => void;\n}\n\n/**\n * Replay a session headlessly to `toFrame` (default: the whole log) and return\n * the live world. Bit-exact with the original run: axes deltas are applied\n * before the step that first saw them; knob events rebuild-with-carryover at\n * their frame exactly as the Studio panel did (including `def.attach`).\n * A bare number as `opts` is `toFrame`.\n */\nexport function replaySession(def: GameDefinition, session: PlaytestSession, opts?: number | ReplayOptions): World {\n const o: ReplayOptions = typeof opts === 'number' ? { toFrame: opts } : (opts ?? {});\n const world = createWorld(def, { seed: session.seed, tuning: session.tuningValues });\n if (session.startSnapshot) {\n world.restore(structuredClone(session.startSnapshot));\n def.attach?.(world);\n }\n o.onWorld?.(world);\n const end = Math.min(o.toFrame ?? session.inputLog.frames.length, session.inputLog.frames.length);\n let axisIdx = 0;\n let knobIdx = 0;\n const tuning: TuningValues = { ...session.tuningValues };\n for (let i = 0; i < end; i++) {\n while (knobIdx < session.knobEvents.length && session.knobEvents[knobIdx].frame === i) {\n const k = session.knobEvents[knobIdx++];\n tuning[k.key] = k.value;\n const snap = world.snapshot();\n snap.tuning = { ...tuning };\n world.restore(snap);\n def.attach?.(world);\n }\n while (axisIdx < session.axesLog.length && session.axesLog[axisIdx][0] === i) {\n const [, name, value] = session.axesLog[axisIdx++];\n world.input.axes.set(name, value);\n }\n world.step(session.inputLog.frames[i]);\n o.onFrame?.(world, i);\n }\n return world;\n}\n", "// The ethnographer: turns a recorded playtest session into a compact, factual\n// report an agent can reason over \u2014 hesitations, deaths, futile inputs, the\n// quit moment \u2014 WITHOUT an LLM reading 40k raw frames. Pure and deterministic:\n// pass 1 mines the input log alone (no sim), pass 2 replays once and samples\n// probes/events at the frames pass 1 flagged.\n//\n// Doctrine: telemetry DESCRIBES, the human DIRECTS. A hesitation is a\n// hypothesis (confused? admiring? distracted?), never a verdict \u2014 reports feed\n// the director's questions, and nothing here auto-triggers a code change.\n//\n// Event convention: games that emit `world.events` 'death' / 'goal' get death\n// topology and honest quit detection; games that don't still get every\n// log-derived metric. Emit 'death' AT the death location (before any respawn\n// reset) \u2014 the cluster position is probed at emit time. Position comes from\n// probe fields px/py (or x/y).\n\nimport type { GameDefinition } from '../app/game';\nimport { replaySession, type PlaytestSession } from '../studio/session';\n\nexport interface HesitationSpan {\n startFrame: number;\n frames: number;\n /** Probe sampled at the span's first frame (what was on screen when input went quiet). */\n probe: Record<string, unknown>;\n}\n\nexport interface DeathCluster {\n x: number;\n y: number;\n count: number;\n frames: number[];\n}\n\nexport interface FutileVerb {\n action: string;\n /** Rising-edge presses after which no probe field changed within the window. */\n futilePresses: number;\n totalPresses: number;\n frames: number[];\n}\n\nexport interface QuitContext {\n frame: number;\n probe: Record<string, unknown>;\n /** Deaths / hesitation starts inside the final window before the quit. */\n recentDeaths: number;\n recentHesitations: number;\n endReason: PlaytestSession['endReason'];\n}\n\nexport interface AnnotationContext {\n frame: number;\n tag: string;\n note?: string;\n probe: Record<string, unknown>;\n}\n\nexport interface PlaytestReport {\n sessionId: string;\n game: string;\n buildRef: string;\n seed: number;\n variant: PlaytestSession['variant'];\n frames: number;\n /** Sim seconds (frames \u00D7 dt); wall time can be longer (pauses, hidden tab). */\n simSeconds: number;\n reachedGoal: boolean;\n deaths: number;\n hesitations: HesitationSpan[];\n deathClusters: DeathCluster[];\n futileVerbs: FutileVerb[];\n /** Present unless the session ended at the goal. */\n quit?: QuitContext;\n annotations: AnnotationContext[];\n knobEvents: PlaytestSession['knobEvents'];\n /** Verbs the player NEVER used (declared in the input map but absent from the log). */\n unusedActions: string[];\n}\n\nexport interface AnalyzeOptions {\n /** Min quiet frames to count as a hesitation (default 45 \u2248 0.75s @ 60fps). */\n hesitationFrames?: number;\n /** Frames after a press in which SOMETHING must change, else it was futile (default 30). */\n futileWindow?: number;\n /** Final-window size for quit context, in frames (default 300 \u2248 5s). */\n quitWindow?: number;\n /** Death-cluster bucket size in world px (default 64). */\n clusterPx?: number;\n}\n\n/** Probe minus volatile bookkeeping \u2014 the fields that mean \"state changed\". */\nfunction probeSignature(probe: Record<string, unknown>): string {\n const { frame: _f, time: _t, hash: _h, ...rest } = probe;\n return JSON.stringify(rest);\n}\n\nfunction probePosition(probe: Record<string, unknown>): { x: number; y: number } | null {\n const x = probe.px ?? probe.x;\n const y = probe.py ?? probe.y;\n return typeof x === 'number' && typeof y === 'number' ? { x, y } : null;\n}\n\n/** Frame ranges the sim ran but the human plausibly wasn't looking/playing. */\nfunction excludedFrames(session: PlaytestSession): Array<[number, number]> {\n const out: Array<[number, number]> = [];\n let hiddenAt: number | null = null;\n for (const m of session.wallClockMarks) {\n if (m.kind === 'visibility-hidden' && hiddenAt === null) hiddenAt = m.frame;\n if (m.kind === 'visibility-visible' && hiddenAt !== null) {\n out.push([hiddenAt, m.frame]);\n hiddenAt = null;\n }\n }\n if (hiddenAt !== null) out.push([hiddenAt, session.inputLog.frames.length]);\n let openAt: number | null = null;\n for (const e of session.screenEvents) {\n if ((e.kind === 'overlay-show' || e.kind === 'pause') && openAt === null) openAt = e.frame;\n if ((e.kind === 'overlay-hide' || e.kind === 'resume') && openAt !== null) {\n out.push([openAt, e.frame]);\n openAt = null;\n }\n }\n return out;\n}\n\nconst inRanges = (frame: number, ranges: Array<[number, number]>): boolean =>\n ranges.some(([a, b]) => frame >= a && frame < b);\n\nexport function analyzePlaytest(def: GameDefinition, session: PlaytestSession, opts: AnalyzeOptions = {}): PlaytestReport {\n const hesitationMin = opts.hesitationFrames ?? 45;\n const futileWindow = opts.futileWindow ?? 30;\n const quitWindow = opts.quitWindow ?? 300;\n const clusterPx = opts.clusterPx ?? 64;\n const frames = session.inputLog.frames;\n const excluded = excludedFrames(session);\n\n // \u2500\u2500 pass 1: mine the log alone (no sim) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Hesitation candidates: runs of empty action sets with no axis movement\n // (any axis change \u2014 pointer motion or press \u2014 counts as activity).\n const axisChangeAt = new Set(session.axesLog.map(([f]) => f));\n const hesitationCandidates: Array<{ startFrame: number; frames: number }> = [];\n let quietStart: number | null = null;\n for (let i = 0; i <= frames.length; i++) {\n const quiet = i < frames.length && frames[i].length === 0 && !axisChangeAt.has(i);\n if (quiet && quietStart === null) quietStart = i;\n if (!quiet && quietStart !== null) {\n const len = i - quietStart;\n if (len >= hesitationMin && !inRanges(quietStart, excluded)) hesitationCandidates.push({ startFrame: quietStart, frames: len });\n quietStart = null;\n }\n }\n\n // Rising-edge presses per action + the census of verbs never touched.\n const pressesByAction = new Map<string, number[]>();\n for (let i = 0; i < frames.length; i++) {\n const prev = i > 0 ? frames[i - 1] : [];\n for (const a of frames[i]) {\n if (!prev.includes(a)) {\n if (!pressesByAction.has(a)) pressesByAction.set(a, []);\n pressesByAction.get(a)!.push(i);\n }\n }\n }\n const declared = Object.keys(def.inputMap ?? {});\n const unusedActions = declared.filter((a) => !pressesByAction.has(a));\n\n // \u2500\u2500 pass 2: one replay, sampling probes at flagged frames \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const wantProbe = new Set<number>();\n for (const h of hesitationCandidates) wantProbe.add(h.startFrame);\n for (const a of session.annotations) wantProbe.add(Math.max(0, Math.min(a.frame, frames.length - 1)));\n for (const [, presses] of pressesByAction) {\n for (const p of presses) {\n wantProbe.add(Math.max(0, p - 1)); // state just before the press\u2026\n wantProbe.add(Math.min(frames.length - 1, p + futileWindow)); // \u2026vs after the window\n }\n }\n if (frames.length > 0) wantProbe.add(frames.length - 1);\n\n const probes = new Map<number, Record<string, unknown>>();\n const deaths: Array<{ frame: number; pos: { x: number; y: number } | null }> = [];\n let reachedGoal = false;\n let frameNow = -1;\n const world = replaySession(def, session, {\n onWorld: (w) => {\n // The event convention: 'death' and 'goal' on world.events. Games that\n // don't emit still get every log-derived metric.\n w.events.on('death', () => deaths.push({ frame: frameNow + 1, pos: probePosition(w.probe()) }));\n w.events.on('goal', () => (reachedGoal = true));\n },\n onFrame: (w, i) => {\n frameNow = i;\n if (wantProbe.has(i)) probes.set(i, w.probe());\n },\n });\n const finalProbe = frames.length > 0 ? (probes.get(frames.length - 1) ?? world.probe()) : world.probe();\n // Probe-flag fallback for the win: many games expose `won` without emitting.\n if (finalProbe.won === true) reachedGoal = true;\n\n // \u2500\u2500 assemble \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const hesitations: HesitationSpan[] = hesitationCandidates.map((h) => ({\n ...h,\n probe: probes.get(h.startFrame) ?? {},\n }));\n\n const clusters = new Map<string, DeathCluster>();\n for (const d of deaths) {\n const key = d.pos ? `${Math.round(d.pos.x / clusterPx)}:${Math.round(d.pos.y / clusterPx)}` : 'unknown';\n const c = clusters.get(key) ?? { x: d.pos?.x ?? 0, y: d.pos?.y ?? 0, count: 0, frames: [] };\n c.count++;\n c.frames.push(d.frame);\n clusters.set(key, c);\n }\n\n const futileVerbs: FutileVerb[] = [];\n for (const [action, presses] of pressesByAction) {\n const futile: number[] = [];\n for (const p of presses) {\n const before = probes.get(Math.max(0, p - 1));\n const after = probes.get(Math.min(frames.length - 1, p + futileWindow));\n if (before && after && probeSignature(before) === probeSignature(after)) futile.push(p);\n }\n if (futile.length > 0) {\n futileVerbs.push({ action, futilePresses: futile.length, totalPresses: presses.length, frames: futile });\n }\n }\n\n const annotations: AnnotationContext[] = session.annotations.map((a) => {\n const f = Math.max(0, Math.min(a.frame, frames.length - 1));\n return { frame: a.frame, tag: a.tag, ...(a.note !== undefined ? { note: a.note } : {}), probe: probes.get(f) ?? {} };\n });\n\n const report: PlaytestReport = {\n sessionId: session.id,\n game: session.game,\n buildRef: session.buildRef,\n seed: session.seed,\n variant: session.variant,\n frames: frames.length,\n simSeconds: world.time,\n reachedGoal,\n deaths: deaths.length,\n hesitations,\n deathClusters: [...clusters.values()].sort((a, b) => b.count - a.count),\n futileVerbs: futileVerbs.sort((a, b) => b.futilePresses - a.futilePresses),\n annotations,\n knobEvents: session.knobEvents,\n unusedActions,\n };\n\n if (!reachedGoal && frames.length > 0) {\n const from = Math.max(0, frames.length - quitWindow);\n report.quit = {\n frame: frames.length - 1,\n probe: finalProbe,\n recentDeaths: deaths.filter((d) => d.frame >= from).length,\n recentHesitations: hesitations.filter((h) => h.startFrame >= from).length,\n endReason: session.endReason,\n };\n }\n\n return report;\n}\n", "// Browser driver: mounts a renderer, samples real input into the fixed-step\n// kernel, projects to the renderer each frame, and wires audio + the pause shell.\n// Wall-clock only feeds the accumulator (how many steps to run) \u2014 replays use the\n// input log, not wall time, so the sim stays deterministic.\n\nimport type { CreateWorldOptions, GameDefinition, SplashConfig } from './game';\nimport { createWorld } from './game';\nimport { KeyboardSource, PointerSource, type InputSource } from '../input/source';\nimport type { Vec2 } from '../core/math';\nimport type { DrawCommand } from '../render/commands';\nimport { relLuminance } from '../verify/gates';\nimport { SvgRenderer } from '../render/svg';\nimport { Canvas2DRenderer } from '../render/canvas';\nimport { WebGL2Renderer } from '../render/webgl';\nimport type { Renderer, Viewport } from '../render/renderer';\nimport { renderToSVGString } from '../render/svgString';\nimport { audio } from '../audio/audio';\nimport { settings } from '../ui/settings';\nimport { setOverlayHost } from '../ui/overlay';\nimport { Shell } from '../ui/shell';\nimport { installCapture, isCaptureMode } from '../verify/capture';\nimport type { World } from '../world';\n\nexport interface RunOptions {\n /** Rendering backend. Default 'svg'. Use 'webgl' for post-processing effects. */\n renderer?: 'svg' | 'canvas' | 'webgl';\n /** Start the pause/settings shell (Esc). Default true. */\n shell?: boolean;\n onRestart?: () => void;\n /** World creation overrides (seed, tuning) \u2014 applied on start AND restart. */\n world?: CreateWorldOptions;\n /**\n * Observer hook: called after each advance that ran \u22651 step, with the step\n * count and the action set those steps saw. Every step in the batch saw the\n * SAME actions and axes, so recording `steps \u00D7 (actions, axes)` replays\n * exactly. Studio's session recorder rides this; it must never mutate.\n */\n onAdvance?: (world: World, steps: number, actions: readonly string[]) => void;\n /** Shell pause/resume observer (true = paused). */\n onPause?: (paused: boolean) => void;\n /**\n * Freeze gate: while it returns true the loop keeps rendering but runs no\n * steps (no pause overlay \u2014 Studio's scrubber holds the sim with this).\n */\n isHeld?: () => boolean;\n /**\n * Extra input sources (e.g. GamepadSource) sampled each step alongside the\n * built-in KeyboardSource and PointerSource. Each source's sample() is called\n * before world.advance(), and dispose() on stop(). You can also add sources\n * after the handle is returned via GameHandle.addSource().\n */\n sources?: InputSource[];\n}\n\nexport interface GameHandle {\n world: World;\n renderer: Renderer;\n /** The live input source \u2014 game UI calls input.press('action') for buttons. */\n input: KeyboardSource;\n /**\n * Continuous pointer/touch in DESIGN space, sampled into world.input.axes each\n * step (pointer.x / pointer.y / pointer.down). Read `handle.pointer.read()` for\n * a one-off, or `world.input.axis('pointer.x')` inside the sim.\n */\n pointer: PointerSource;\n /** The mounted canvas/svg node (attach your own listeners here if needed). */\n canvas: HTMLElement | SVGElement | undefined;\n /** Map a pointer event's clientX/Y to design coordinates (undoes the letterbox). */\n toDesign(clientX: number, clientY: number): Vec2;\n /** The drawn (letterboxed) area within the mount \u2014 anchor host-drawn UI here. */\n viewport(): Viewport | undefined;\n /** Resolves after preload completes and the first real frame has rendered. */\n ready: Promise<void>;\n /** Run a callback once the game is ready (fires immediately if already ready). */\n onReady(cb: () => void): void;\n /**\n * Register an extra input source (e.g. GamepadSource) to be sampled each step\n * alongside PointerSource. Returns a cleanup function that removes the source\n * (calling its dispose()) when invoked.\n *\n * Typical pattern:\n * const handle = runBrowser(def, mount);\n * const gamepad = new GamepadSource({ keyboard: handle.input });\n * const removeGamepad = handle.addSource(gamepad);\n */\n addSource(source: InputSource): () => void;\n /**\n * Drive one frame by hand: sample the pointer (and extra sources), advance\n * the world by dtMs with the currently-held actions, and render \u2014 exactly\n * what the real loop does per frame. Default dtMs is one fixed step's ms.\n * For headless/tool-driven frame-stepping with visuals updating; the wall-\n * clock loop keeps running independently (pause the shell or use isHeld to\n * make tick() the only driver).\n */\n tick(dtMs?: number): void;\n stop(): void;\n restart(): void;\n}\n\n/**\n * A palette-guaranteed splash display list. The fg is picked to clear the WCAG AA\n * bar against the bg, so the boot cover can never ship the low-contrast defect a\n * hand-rolled loading <div> can (that's the whole reason this lives in the engine).\n */\nfunction splashCommands(cfg: SplashConfig, def: GameDefinition, width: number, height: number): DrawCommand[] {\n const bg = cfg.palette?.bg ?? '#141821';\n // Guaranteed-contrast ink: whichever of near-black / near-white reads on the bg.\n const fg = cfg.palette?.fg ?? (relLuminance(bg) > 0.4 ? '#14171f' : '#f4efe3');\n const title = cfg.title ?? def.title;\n const t = { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };\n return [\n { kind: 'rect', x: 0, y: 0, w: width, h: height, fill: bg, transform: t, z: 0 },\n { kind: 'text', text: title, x: width / 2, y: height / 2, size: Math.round(height * 0.06), align: 'center', weight: 700, fill: fg, transform: t, z: 1 },\n { kind: 'text', text: 'loading\u2026', x: width / 2, y: height / 2 + height * 0.08, size: Math.round(height * 0.03), align: 'center', fill: fg, opacity: 0.7, transform: t, z: 1 },\n ];\n}\n\nexport function runBrowser(def: GameDefinition, mount: HTMLElement, opts: RunOptions = {}): GameHandle {\n const width = def.width ?? 1280;\n const height = def.height ?? 720;\n const background = def.background ?? '#f3ecdb';\n\n let world = createWorld(def, opts.world);\n const renderer: Renderer =\n opts.renderer === 'canvas'\n ? new Canvas2DRenderer({ width, height, background })\n : opts.renderer === 'webgl'\n ? new WebGL2Renderer({ width, height, background })\n : new SvgRenderer({ width, height, background });\n\n mount.style.position = mount.style.position || 'relative';\n renderer.mount?.(mount);\n setOverlayHost(mount);\n\n const input = new KeyboardSource(def.inputMap ?? {}, document);\n // keyboard wired in so mouse buttons enter the same deterministic action log\n // as keys (mouse.left/right/middle held actions + inputMap bindings).\n const pointer = new PointerSource(renderer, { keyboard: input });\n const extraSources: InputSource[] = [...(opts.sources ?? [])];\n const capture = isCaptureMode();\n\n // Arm the unknown-action typo guard: declare what this host can produce.\n // Re-run on restart \u2014 a fresh world gets a fresh InputState.\n const declareInputs = () => world.input.declareActions(input.actionNames());\n declareInputs();\n\n // Start audio on first user gesture (autoplay policy).\n const startAudio = () => {\n audio.start();\n const s = settings.get();\n audio.setVolumes(s);\n window.removeEventListener('pointerdown', startAudio);\n window.removeEventListener('keydown', startAudio);\n };\n window.addEventListener('pointerdown', startAudio);\n window.addEventListener('keydown', startAudio);\n\n const renderFrame = () => renderer.draw(world.render());\n const restart = () => {\n world = createWorld(def, opts.world);\n declareInputs();\n renderFrame();\n };\n\n const shell =\n opts.shell === false\n ? null\n : new Shell({\n title: def.title,\n onRestart: opts.onRestart ?? restart,\n onPause: (paused) => opts.onPause?.(paused),\n });\n\n // \u2500\u2500 Boot lifecycle: splash \u2192 preload \u2192 first frame \u2192 ready \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Capture mode wants the real game immediately (headless SVG), so it skips boot.\n const splashCfg = def.splash === false ? null : def.splash ?? {};\n const splash = splashCfg && !capture ? splashCommands(splashCfg, def, width, height) : null;\n let booting = !capture;\n const readyCbs: Array<() => void> = [];\n let resolveReady!: () => void;\n const ready = new Promise<void>((r) => (resolveReady = r));\n const bootStart = performance.now();\n\n let last = performance.now();\n const finishBoot = () => {\n if (!booting) return;\n booting = false;\n last = performance.now(); // don't hand the first real frame a boot-sized dt\n renderFrame();\n resolveReady();\n for (const cb of readyCbs.splice(0)) cb();\n };\n\n // One real frame: sample sources \u2192 advance \u2192 render. Shared verbatim by the\n // wall-clock loop and handle.tick() so tool-driven stepping IS the loop.\n const perFrame = (dtMs: number) => {\n if (!capture && !(shell?.isPaused) && !opts.isHeld?.()) {\n pointer.sample(world.input); // pointer.x/y/down into axes before the step reads them\n for (const s of extraSources) s.sample(world.input);\n const actions = input.currentActions();\n const steps = world.advance(dtMs, actions);\n if (steps > 0) {\n input.clearPressed(); // virtual taps held until sampled\n opts.onAdvance?.(world, steps, actions);\n }\n }\n renderFrame();\n };\n\n // \u2500\u2500 Frame scheduler: native rAF when visible, setTimeout when hidden \u2500\u2500\u2500\u2500\u2500\n // rAF is throttled to death in hidden tabs/iframes, so the engine owns the\n // fallback (games must NOT patch the global requestAnimationFrame \u2014 that\n // road ends in double-fires and shared-slot races; see the 2026-07 triage).\n // Gate on document.hidden ONLY \u2014 hasFocus() is false for a merely-unfocused\n // window whose rAF still runs fine, and gating on it stalls the game.\n // Exactly one callback is pending at a time, and each timeout closes over\n // its own callback (no shared slot); visibilitychange re-arms the pending\n // callback onto the other mechanism.\n let raf = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let pendingCb: FrameRequestCallback | null = null;\n let stopped = false;\n const HIDDEN_TICK_MS = 16;\n const clearScheduled = () => {\n if (raf !== 0) {\n cancelAnimationFrame(raf);\n raf = 0;\n }\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n };\n const schedule = (cb: FrameRequestCallback) => {\n if (stopped) return;\n pendingCb = cb;\n if (document.hidden) {\n timer = setTimeout(() => {\n timer = undefined;\n pendingCb = null;\n cb(performance.now());\n }, HIDDEN_TICK_MS);\n } else {\n raf = requestAnimationFrame((now) => {\n raf = 0;\n pendingCb = null;\n cb(now);\n });\n }\n };\n const onVisibility = () => {\n const cb = pendingCb;\n if (cb === null) return; // mid-frame or stopped; the next schedule() re-reads hidden\n clearScheduled();\n pendingCb = null;\n schedule(cb);\n };\n document.addEventListener('visibilitychange', onVisibility);\n\n const loop = (now: number) => {\n if (booting) {\n if (splash) renderer.draw(splash);\n schedule(loop);\n return;\n }\n const dt = now - last;\n last = now;\n perFrame(dt);\n schedule(loop);\n };\n schedule(loop);\n\n if (booting) {\n const minDur = splashCfg?.minDurationMs ?? 0;\n const preload = def.preload ? Promise.resolve().then(() => def.preload!(world)) : Promise.resolve();\n const holdSplash = new Promise<void>((r) => setTimeout(r, Math.max(0, minDur - (performance.now() - bootStart))));\n Promise.all([preload, holdSplash])\n .then(finishBoot)\n .catch((err) => {\n console.error('hayao: preload failed \u2014', err);\n finishBoot(); // never strand the player on the splash\n });\n } else {\n resolveReady();\n }\n\n const handle: GameHandle = {\n get world() {\n return world;\n },\n renderer,\n input,\n pointer,\n canvas: renderer.element,\n toDesign: (clientX, clientY) => renderer.toDesign?.(clientX, clientY) ?? { x: clientX, y: clientY },\n viewport: () => renderer.viewport?.(),\n ready,\n onReady(cb) {\n if (booting) readyCbs.push(cb);\n else cb();\n },\n addSource(source: InputSource) {\n extraSources.push(source);\n return () => {\n const i = extraSources.indexOf(source);\n if (i !== -1) extraSources.splice(i, 1);\n source.dispose?.();\n };\n },\n tick(dtMs) {\n perFrame(dtMs ?? world.clock.stepMs);\n },\n stop() {\n stopped = true;\n pendingCb = null;\n clearScheduled();\n document.removeEventListener('visibilitychange', onVisibility);\n input.dispose();\n pointer.dispose();\n for (const s of extraSources) s.dispose?.();\n extraSources.length = 0;\n shell?.dispose();\n renderer.dispose?.();\n },\n restart,\n };\n\n if (capture) {\n installCapture({\n get world() {\n return world;\n },\n stepOnce: (actions = []) => {\n world.step(actions);\n renderFrame();\n },\n renderSVG: () => renderToSVGString(world.render(), width, height, background),\n setPaused: () => {},\n });\n }\n\n return handle;\n}\n", "// verify/dom \u2014 prove the ONE layer the headless proofs cannot see: the browser\n// host controls (virtual sticks, buttons, pointer/touch aim). It boots the real\n// `runBrowser` wiring under a DOM (jsdom/happy-dom), lets a test fire synthetic\n// pointer/touch events, and then steps the sim so you can assert on `probe()`.\n// This extends \"prove it, don't vibe it\" to the human-contact edge.\n//\n// Requires a DOM environment. In a Vitest file, opt in with: // @vitest-environment jsdom\n//\n// Note: under jsdom `getBoundingClientRect()` returns a zero rect, so the\n// letterbox maps client px 1:1 to design px \u2014 pass DESIGN coordinates straight\n// to `touchDown(id, x, y)` and the sim sees them unchanged.\n\nimport { runBrowser, type GameHandle } from '../app/browser';\nimport type { GameDefinition } from '../app/game';\n\nexport interface DomHarness {\n /** The live game handle (world, input, pointer, renderer, viewport\u2026). */\n handle: GameHandle;\n /** Press a finger/pointer down at design (x,y) with a stable id (default 1). */\n touchDown(x: number, y: number, id?: number): void;\n /** Move a tracked finger/pointer to design (x,y). */\n touchMove(x: number, y: number, id?: number): void;\n /** Lift a finger/pointer (default id 1). */\n touchUp(id?: number): void;\n /**\n * Sample the live pointer + keyboard input into the sim, then run `n` fixed\n * steps \u2014 the same order `runBrowser` uses, minus wall-clock. Held/virtual\n * actions and quantized axes flow through exactly as in production.\n */\n step(n?: number, axes?: Record<string, number>): void;\n dispose(): void;\n}\n\nfunction synthPointer(type: string, x: number, y: number, id: number): Event {\n const e = new Event(type, { bubbles: true }) as Event & { clientX: number; clientY: number; pointerId: number; button: number };\n e.clientX = x;\n e.clientY = y;\n e.pointerId = id;\n e.button = 0;\n return e;\n}\n\n/**\n * Boot a game's real host wiring under the DOM for a host-layer test. The loop is\n * frozen (`isHeld`) so stepping is deterministic and test-driven \u2014 call `step()`\n * after firing input. Attach a `TouchControls` to `harness.handle` to prove a\n * virtual gamepad end-to-end.\n */\nexport function bootDom(def: GameDefinition, mount?: HTMLElement): DomHarness {\n if (typeof document === 'undefined') {\n throw new Error(\"verify/dom: no DOM found \u2014 set the test's environment to jsdom (// @vitest-environment jsdom).\");\n }\n const owned = !mount;\n const host = mount ?? document.createElement('div');\n if (owned) document.body.appendChild(host);\n\n const handle = runBrowser(def, host, { shell: false, isHeld: () => true });\n const el = handle.canvas as EventTarget | undefined;\n\n return {\n handle,\n touchDown(x, y, id = 1) {\n el?.dispatchEvent(synthPointer('pointerdown', x, y, id));\n },\n touchMove(x, y, id = 1) {\n el?.dispatchEvent(synthPointer('pointermove', x, y, id));\n },\n touchUp(id = 1) {\n // Release listens on the window (a finger lifted off-canvas still ends it).\n globalThis.dispatchEvent?.(synthPointer('pointerup', 0, 0, id));\n },\n step(n = 1, axes) {\n for (let i = 0; i < n; i++) {\n handle.pointer.sample(handle.world.input);\n handle.world.step(handle.input.currentActions(), axes);\n handle.input.clearPressed();\n }\n },\n dispose() {\n handle.stop();\n if (owned) host.remove();\n },\n };\n}\n", "// Finite state machines for AI, screens, and move-animation. Two flavours:\n//\n// \u2022 `Fsm` \u2014 classic onEnter/onUpdate/onLeave states + an ORDERED transition\n// table (first matching guard wins). For enemy brains, UI phases, anything\n// driven by conditions.\n// \u2022 `PhaseClock` \u2014 the pure-logic\u2194`cosmetic` bridge. A timed phase with an\n// eased 0\u21921 progress value and a `next`-phase map (super-castle-game's\n// `IState` + `NextPhaseMap`, generalised): logical moves advance in discrete\n// phases while `progress()` feeds smooth interpolation to the view.\n//\n// Both are DETERMINISTIC: time arrives as a fixed `dt` (from the `Clock`, never\n// wall-clock), transitions are evaluated in array order, and the whole state is\n// a single serializable key + timer so it round-trips through `world.state`.\n\n/** Per-state lifecycle hooks. All optional; all pure over the shared context. */\nexport interface StateHandlers<C> {\n /** Ran once when the machine enters this state. */\n onEnter?(ctx: C): void;\n /** Ran every `update(dt)` while in this state. */\n onUpdate?(ctx: C, dt: number): void;\n /** Ran once when the machine leaves this state. */\n onLeave?(ctx: C): void;\n}\n\n/**\n * A guarded edge. `from` is a source state or `'*'` (any). Edges are evaluated\n * in table order every tick; the first whose `when` returns true fires. Keep\n * the table ordered \u2014 order IS the tie-break, so the machine stays hash-stable.\n */\nexport interface Transition<S extends string, C> {\n from: S | '*';\n to: S;\n when(ctx: C): boolean;\n}\n\nexport class Fsm<S extends string, C> {\n /** The active state key \u2014 this is the whole serializable state. */\n current: S;\n\n constructor(\n private readonly states: Record<S, StateHandlers<C>>,\n private readonly transitions: readonly Transition<S, C>[],\n initial: S,\n private readonly ctx: C,\n ) {\n this.current = initial;\n this.states[initial]?.onEnter?.(ctx);\n }\n\n /**\n * Advance one fixed step: fire the first satisfied transition (if any), then\n * run the current state's `onUpdate`. A transition runs its target's\n * `onUpdate` this same tick, so entering and acting aren't a frame apart.\n */\n update(dt: number): void {\n for (const t of this.transitions) {\n if ((t.from === '*' || t.from === this.current) && t.when(this.ctx)) {\n this.go(t.to);\n break;\n }\n }\n this.states[this.current]?.onUpdate?.(this.ctx, dt);\n }\n\n /** Force a transition (fires onLeave/onEnter). No-op if already there. */\n go(to: S): void {\n if (to === this.current) return;\n this.states[this.current]?.onLeave?.(this.ctx);\n this.current = to;\n this.states[to]?.onEnter?.(this.ctx);\n }\n\n /** True when in one of the given states. */\n is(...states: S[]): boolean {\n return states.includes(this.current);\n }\n\n /** Serialize (games persist this in `world.state`; the handlers are code). */\n getState(): S {\n return this.current;\n }\n /** Restore without firing enter/leave (it's a resume, not a transition). */\n setState(state: S): void {\n this.current = state;\n }\n}\n\n/** Eased progress curve `[0,1] \u2192 [0,1]`. Identity by default. */\nexport type Ease = (t: number) => number;\n\n/** A timed phase: how long it lasts and (optionally) what follows it. */\nexport interface PhaseDef {\n /** Duration in seconds (same units as the `dt` you feed `update`). */\n duration: number;\n /** Successor phase when this one elapses. Omit for a terminal phase. */\n next?: string;\n}\n\n/**\n * A phase with a countdown and an eased progress readout. Drives discrete\n * logical steps (each phase = one settled move) while exposing `progress()` for\n * the view to interpolate between the old and new position \u2014 so animation\n * timing rides on the same deterministic clock as the logic.\n */\nexport class PhaseClock {\n /** Current phase key \u2014 serializable with `elapsed`. */\n phase: string;\n /** Seconds spent in the current phase so far. */\n elapsed = 0;\n\n constructor(\n private readonly defs: Record<string, PhaseDef>,\n initial: string,\n ) {\n if (!defs[initial]) throw new Error(`hayao: PhaseClock has no phase '${initial}'`);\n this.phase = initial;\n }\n\n private get duration(): number {\n return this.defs[this.phase]?.duration ?? 0;\n }\n\n /** Eased fraction 0\u21921 through the current phase (clamped). For cosmetic interp. */\n progress(ease: Ease = (t) => t): number {\n const d = this.duration;\n const raw = d > 0 ? this.elapsed / d : 1;\n return ease(raw < 0 ? 0 : raw > 1 ? 1 : raw);\n }\n\n /** True once the current phase's duration has fully elapsed. */\n get done(): boolean {\n return this.elapsed >= this.duration;\n }\n\n /**\n * Advance by `dt`. When a phase completes and has a `next`, roll into it\n * (carrying any overshoot so long phases don't drift). Returns true on the\n * tick a new phase begins \u2014 the game's cue to commit the next logical step.\n */\n update(dt: number): boolean {\n this.elapsed += dt;\n let advanced = false;\n // Loop in case a very small duration is stepped over in one big dt.\n let guard = 0;\n while (this.elapsed >= this.duration && this.defs[this.phase]?.next !== undefined && guard++ < 1024) {\n const overshoot = this.elapsed - this.duration;\n this.phase = this.defs[this.phase].next as string;\n this.elapsed = overshoot;\n advanced = true;\n }\n return advanced;\n }\n\n /** Jump to a phase and reset its timer (fresh `onEnter`-style restart). */\n to(phase: string): void {\n if (!this.defs[phase]) throw new Error(`hayao: PhaseClock has no phase '${phase}'`);\n this.phase = phase;\n this.elapsed = 0;\n }\n\n getState(): { phase: string; elapsed: number } {\n return { phase: this.phase, elapsed: this.elapsed };\n }\n setState(state: { phase: string; elapsed: number }): void {\n this.phase = state.phase;\n this.elapsed = state.elapsed;\n }\n}\n", "// Deterministic coroutines \u2014 sequenced game flow (intros, cutscenes, boss\n// phases, tutorials) as plain generators stepped on the fixed clock.\n//\n// WHY GENERATORS, NOT PROMISES: async/await resolves on the microtask queue,\n// whose interleaving with the render loop is engine- and load-dependent \u2014 a\n// Promise-based `await sleep(1)` lands on a *wall-clock-ish* boundary that two\n// runs (or two peers) will disagree on. A generator only advances when\n// `Coroutines.step(dt)` says so, so every resume happens at an exact sim step\n// and replays land on the same tick, every time.\n//\n// Usage (an intro flow: wait, then race a prompt against a timeout):\n//\n// const co = new Coroutines();\n// co.start(function* () {\n// yield sleep(1.5); // banner hold\n// const winner = yield race(waitFor(() => input.any), sleep(5));\n// if (winner === 0) showTip('nice, you pressed something');\n// yield nextStep(); // let the tip render\n// }, 'intro');\n//\n// // \u2026and in the game's brain node (Coroutines is engine-agnostic on purpose \u2014\n// // it has no Node/world coupling, so a game owns WHEN it advances):\n// brain.onUpdate = (_n, dt) => co.step(dt);\n//\n// Semantics (all deterministic, all fixed-step):\n// \u2022 `step(dt)` advances live runners in insertion order, at most one resume per\n// runner per step; conditions are evaluated at most once per step.\n// \u2022 A runner's first resume (start \u2192 first yield) happens on the first `step()`\n// AFTER `start()` \u2014 a coroutine started during `step()` never runs mid-step;\n// it runs first thing on the NEXT step.\n// \u2022 `yield sleep(s)` resumes on the first step where the accumulated dt reaches\n// `s` (within 1e-9, absorbing float drift on non-exact dt like 1/60).\n// \u2022 `yield race(...)` resumes with the index of the WINNING wait (ties go to\n// the lowest index); every other yield resumes with 0.\n// \u2022 Yielding another runner's handle joins it (resumes once that runner is done).\n// \u2022 An exception inside a generator kills only that runner, with a console.warn\n// naming it (pass a `name` to `start` to get useful blame).\n\n/** Resumes after `seconds` of accumulated sim time. */\nexport function sleep(seconds: number): Wait {\n return { kind: 'sleep', left: seconds };\n}\n\n/** Resumes on the first step where `cond()` is true (checked once per step). */\nexport function waitFor(cond: () => boolean): Wait {\n return { kind: 'cond', cond };\n}\n\n/** Resumes on the next step \u2014 yields one frame (e.g. to let a spawn render). */\nexport function nextStep(): Wait {\n return { kind: 'next' };\n}\n\n/**\n * Resumes when ANY of the waits completes; the yield expression evaluates to\n * the winning index (ties resolve to the lowest index \u2014 deterministic).\n */\nexport function race(...waits: Wait[]): Wait {\n return { kind: 'race', waits };\n}\n\n/** Resumes when ALL of the waits have completed. */\nexport function all(...waits: Wait[]): Wait {\n return { kind: 'all', waits };\n}\n\ninterface SleepWait {\n kind: 'sleep';\n left: number;\n}\ninterface CondWait {\n kind: 'cond';\n cond: () => boolean;\n /** Memo so a satisfied condition is never re-evaluated (inside all()). */\n met?: boolean;\n}\ninterface NextWait {\n kind: 'next';\n passed?: boolean;\n}\ninterface RaceWait {\n kind: 'race';\n waits: Wait[];\n}\ninterface AllWait {\n kind: 'all';\n waits: Wait[];\n}\n\n/** What a coroutine may yield. A `CoroutineHandle` yield joins that runner. */\nexport type Wait = SleepWait | CondWait | NextWait | RaceWait | AllWait | CoroutineHandle;\n\n/** A started coroutine. `done` flips when it returns, throws, or is stopped. */\nexport interface CoroutineHandle {\n readonly name: string;\n readonly done: boolean;\n /** Kill the runner (its generator's finally blocks run via `return()`). */\n stop(): void;\n}\n\nconst EPS = 1e-9;\n\n/**\n * Advance a wait by dt. Returns -1 while pending; otherwise the resume value\n * (the winning index for race, 0 for everything else).\n */\nfunction advanceWait(w: Wait, dt: number): number {\n if (isHandle(w)) return w.done ? 0 : -1;\n switch (w.kind) {\n case 'sleep':\n w.left -= dt;\n return w.left <= EPS ? 0 : -1;\n case 'cond':\n if (!w.met && w.cond()) w.met = true;\n return w.met ? 0 : -1;\n case 'next':\n // The first advance IS the next step \u2014 completes immediately.\n w.passed = true;\n return 0;\n case 'race': {\n // Advance every arm (each is checked once this step), lowest index wins.\n let winner = -1;\n for (let i = 0; i < w.waits.length; i++) {\n if (advanceWait(w.waits[i], dt) >= 0 && winner < 0) winner = i;\n }\n return winner;\n }\n case 'all': {\n let done = true;\n for (const inner of w.waits) {\n if (!isDone(inner)) {\n if (advanceWait(inner, dt) < 0) done = false;\n }\n }\n return done ? 0 : -1;\n }\n }\n}\n\n/** Has this wait already completed? (Used by all() to skip finished arms.) */\nfunction isDone(w: Wait): boolean {\n if (isHandle(w)) return w.done;\n switch (w.kind) {\n case 'sleep':\n return w.left <= EPS;\n case 'cond':\n return w.met === true;\n case 'next':\n return w.passed === true;\n case 'race':\n return w.waits.some(isDone);\n case 'all':\n return w.waits.every(isDone);\n }\n}\n\nfunction isHandle(w: Wait): w is CoroutineHandle {\n return w instanceof Runner;\n}\n\nclass Runner implements CoroutineHandle {\n readonly name: string;\n done = false;\n /** null until the first resume (which runs the body to its first yield). */\n wait: Wait | null = null;\n private readonly gen: Generator<Wait, void, number>;\n\n constructor(factory: () => Generator<Wait, void, number>, name: string) {\n this.name = name;\n this.gen = factory();\n }\n\n /** Resume the generator with a value; a throw kills only this runner. */\n resume(value: number): void {\n try {\n const it = this.gen.next(value);\n if (it.done) this.done = true;\n else this.wait = it.value;\n } catch (err) {\n this.done = true;\n console.warn(`[hayao] coroutine \"${this.name}\" threw and was stopped:`, err);\n }\n }\n\n stop(): void {\n if (this.done) return;\n this.done = true;\n try {\n this.gen.return(undefined);\n } catch {\n /* a throw during unwind still counts as stopped */\n }\n }\n}\n\n/**\n * A deterministic scheduler for many concurrent coroutines. Owns no clock \u2014\n * call `step(dt)` from wherever your game advances (typically a brain node's\n * `onUpdate`), so coroutine time IS sim time.\n */\nexport class Coroutines {\n private runners: Runner[] = [];\n /** Started since the last step boundary; adopted at the top of the next step. */\n private pending: Runner[] = [];\n private nextId = 0;\n\n /**\n * Register a coroutine. Its body runs (up to the first yield) on the NEXT\n * `step()` \u2014 never immediately, and never mid-step. Pass a `name` so a\n * thrown generator warns something better than \"co3\".\n */\n start(gen: () => Generator<Wait, void, number>, name?: string): CoroutineHandle {\n const r = new Runner(gen, name ?? `co${this.nextId}`);\n this.nextId++;\n this.pending.push(r);\n return r;\n }\n\n /** Advance every live runner by one fixed step, in insertion order. */\n step(dt: number): void {\n // Adopt runners started before this step; ones started DURING this step\n // land in `pending` and are adopted next step (so a mid-step start never\n // advances in the same step it was created).\n if (this.pending.length > 0) {\n this.runners.push(...this.pending);\n this.pending.length = 0;\n }\n for (const r of this.runners) {\n if (r.done) continue;\n if (r.wait === null) {\n r.resume(0); // first resume: run the body to its first yield\n continue;\n }\n const result = advanceWait(r.wait, dt);\n if (result >= 0) {\n r.wait = null;\n r.resume(result);\n }\n }\n // Compact in place (order-preserving) so dead runners don't accumulate.\n let write = 0;\n for (const r of this.runners) if (!r.done) this.runners[write++] = r;\n this.runners.length = write;\n }\n\n /** Stop every runner (including ones not yet adopted). */\n stopAll(): void {\n for (const r of this.runners) r.stop();\n for (const r of this.pending) r.stop();\n this.runners.length = 0;\n this.pending.length = 0;\n }\n\n /** Live runner count (started-but-not-yet-stepped ones included). */\n get active(): number {\n let n = 0;\n for (const r of this.runners) if (!r.done) n++;\n for (const r of this.pending) if (!r.done) n++;\n return n;\n }\n}\n", "// Weighted random picking + loot/spawn tables. Built strictly ON `world.rng`\n// (an `Rng`) \u2014 never `Math.random`. A single float draw per pick, scanned over\n// cumulative weights in array order, so results are deterministic and\n// reproducible from the RNG state alone. (js13k games fake this with\n// filter+shuffle or reach for `Math.random`; this is the honest primitive.)\n\nimport type { Rng } from '../core/rng';\n\n/** One weighted option: a value and its relative weight (\u2265 0). */\nexport interface WeightedEntry<T> {\n value: T;\n weight: number;\n}\n\n/** Sum a weight list, clamping negatives to 0 (a negative weight is a bug, not a subtraction). */\nfunction totalWeight(weights: readonly number[]): number {\n let sum = 0;\n for (const w of weights) sum += w > 0 ? w : 0;\n return sum;\n}\n\n/**\n * Pick an index in [0, weights.length) with probability \u221D weights[i]. Draws\n * exactly one `rng.float()` and walks the weights in order, so the choice is a\n * pure function of the RNG state. Throws if no weight is positive.\n */\nexport function weightedIndex(rng: Rng, weights: readonly number[]): number {\n const total = totalWeight(weights);\n if (total <= 0) throw new Error('hayao: weightedIndex needs at least one positive weight');\n let r = rng.float() * total;\n for (let i = 0; i < weights.length; i++) {\n const w = weights[i] > 0 ? weights[i] : 0;\n if (r < w) return i;\n r -= w;\n }\n // Float rounding can leave r \u2265 every remaining bucket; hand it the last positive one.\n for (let i = weights.length - 1; i >= 0; i--) if (weights[i] > 0) return i;\n return weights.length - 1;\n}\n\n/** Pick `items[i]` with probability \u221D `weights[i]` (parallel arrays). */\nexport function weightedPick<T>(rng: Rng, items: readonly T[], weights: readonly number[]): T {\n if (items.length !== weights.length) throw new Error('hayao: weightedPick items/weights length mismatch');\n return items[weightedIndex(rng, weights)];\n}\n\n/** Pick the value of one weighted entry. */\nexport function pickEntry<T>(rng: Rng, entries: readonly WeightedEntry<T>[]): T {\n return entries[weightedIndex(rng, entries.map((e) => e.weight))].value;\n}\n\n/**\n * A reusable loot/spawn table. Precomputes cumulative weights once so repeated\n * rolls are cheap; every draw still comes from the passed `Rng`, keeping the\n * table itself stateless and the randomness owned by `world.rng`.\n */\nexport class LootTable<T> {\n private readonly values: readonly T[];\n /** Cumulative (prefix-sum) weights; last element is the total. */\n private readonly cumulative: readonly number[];\n readonly total: number;\n\n constructor(entries: readonly WeightedEntry<T>[]) {\n if (entries.length === 0) throw new Error('hayao: LootTable needs at least one entry');\n const values: T[] = [];\n const cumulative: number[] = [];\n let sum = 0;\n for (const e of entries) {\n sum += e.weight > 0 ? e.weight : 0;\n values.push(e.value);\n cumulative.push(sum);\n }\n if (sum <= 0) throw new Error('hayao: LootTable needs at least one positive weight');\n this.values = values;\n this.cumulative = cumulative;\n this.total = sum;\n }\n\n /** One draw with replacement. */\n roll(rng: Rng): T {\n const r = rng.float() * this.total;\n // Linear scan (tables are small); ordered \u2192 deterministic.\n for (let i = 0; i < this.cumulative.length; i++) if (r < this.cumulative[i]) return this.values[i];\n return this.values[this.values.length - 1];\n }\n\n /** `n` independent draws with replacement, in order. */\n rollMany(rng: Rng, n: number): T[] {\n const out: T[] = [];\n for (let i = 0; i < n; i++) out.push(this.roll(rng));\n return out;\n }\n}\n", "// Graph search: BFS, flood-fill, connected-components, and grid A*/Dijkstra.\n// Pairs with `physics/tilemap.ts` (enemy nav, region/cluster detection, unit\n// routing) but works over any adjacency function too.\n//\n// DETERMINISM: neighbours are visited in a fixed order, the frontier is an\n// array (BFS) or a binary heap tie-broken by a monotonic insertion counter\n// (A*/Dijkstra), and grids are scanned row-major. `cameFrom`/`cost` maps are\n// only ever read by key \u2014 never iterated to drive logic \u2014 so no Set/Map\n// ordering hazard reaches `world.hash()`. No RNG, no wall-clock; fully pure.\n\nimport { TILE, tileAt, type TilemapData } from '../physics/tilemap';\n\n// \u2500\u2500 generic graph search over an adjacency function \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Neighbours of a node, in deterministic order. */\nexport type Neighbours<N> = (node: N) => N[];\n/** Stable string identity for a node (visited-set + path keys). */\nexport type NodeKey<N> = (node: N) => string;\n\nexport interface BfsResult<N> {\n /** Nodes in expansion order (breadth-first). */\n order: N[];\n /** key \u2192 the node it was first reached from (for path reconstruction). */\n cameFrom: Map<string, N>;\n /** key \u2192 steps from the start (start = 0). */\n dist: Map<string, number>;\n}\n\n/**\n * Breadth-first search from `start`. Explores the whole reachable component\n * unless `goal` short-circuits it. `maxNodes` caps work on huge/open graphs.\n */\nexport function bfs<N>(\n start: N,\n neighbours: Neighbours<N>,\n key: NodeKey<N>,\n opts: { goal?: (n: N) => boolean; maxNodes?: number } = {},\n): BfsResult<N> {\n const maxNodes = opts.maxNodes ?? 1_000_000;\n const order: N[] = [];\n const cameFrom = new Map<string, N>();\n const dist = new Map<string, number>();\n const startKey = key(start);\n dist.set(startKey, 0);\n let frontier: N[] = [start];\n order.push(start);\n if (opts.goal?.(start)) return { order, cameFrom, dist };\n\n let expanded = 0;\n while (frontier.length > 0 && expanded < maxNodes) {\n const next: N[] = [];\n for (const node of frontier) {\n const d = dist.get(key(node)) ?? 0;\n for (const nb of neighbours(node)) {\n const k = key(nb);\n if (dist.has(k)) continue;\n dist.set(k, d + 1);\n cameFrom.set(k, node);\n order.push(nb);\n expanded++;\n if (opts.goal?.(nb)) return { order, cameFrom, dist };\n next.push(nb);\n }\n }\n frontier = next;\n }\n return { order, cameFrom, dist };\n}\n\n/** Reconstruct the path start\u2192goal from a `cameFrom` map, or [] if unreachable. */\nexport function reconstructPath<N>(cameFrom: Map<string, N>, key: NodeKey<N>, start: N, goal: N): N[] {\n const path: N[] = [goal];\n let cur = goal;\n const startKey = key(start);\n while (key(cur) !== startKey) {\n const prev = cameFrom.get(key(cur));\n if (prev === undefined) return []; // goal not connected to start\n cur = prev;\n path.push(cur);\n }\n path.reverse();\n return path;\n}\n\n// \u2500\u2500 weighted search: Dijkstra / A* over an adjacency function \u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A neighbour with the step cost to reach it (must be \u2265 0). */\nexport interface WeightedEdge<N> {\n node: N;\n cost: number;\n}\nexport type WeightedNeighbours<N> = (node: N) => WeightedEdge<N>[];\n\n/**\n * A* (Dijkstra when `heuristic` is omitted/zero) over a weighted adjacency\n * function. Returns the least-cost path start\u2192goal (inclusive) or null.\n * Tie-broken by insertion order via a monotonic counter \u2192 identical path on\n * every engine.\n */\nexport function astar<N>(\n start: N,\n isGoal: (n: N) => boolean,\n neighbours: WeightedNeighbours<N>,\n key: NodeKey<N>,\n opts: { heuristic?: (n: N) => number; maxNodes?: number } = {},\n): { path: N[]; cost: number } | null {\n const h = opts.heuristic ?? (() => 0);\n const maxNodes = opts.maxNodes ?? 1_000_000;\n const cameFrom = new Map<string, N>();\n const gScore = new Map<string, number>();\n const heap = new MinHeap<N>();\n const startKey = key(start);\n gScore.set(startKey, 0);\n heap.push(start, h(start));\n\n let expanded = 0;\n while (heap.size > 0 && expanded < maxNodes) {\n const { item: cur, priority: f } = heap.pop();\n const ck = key(cur);\n const g = gScore.get(ck) ?? Infinity;\n // Stale heap entry (a cheaper path superseded it): f encodes g+h at push time.\n if (f > g + h(cur) + 1e-9) continue;\n if (isGoal(cur)) return { path: rebuild(cameFrom, key, cur), cost: g };\n expanded++;\n for (const edge of neighbours(cur)) {\n const nk = key(edge.node);\n const tentative = g + edge.cost;\n if (tentative < (gScore.get(nk) ?? Infinity)) {\n gScore.set(nk, tentative);\n cameFrom.set(nk, cur);\n heap.push(edge.node, tentative + h(edge.node));\n }\n }\n }\n return null;\n}\n\nfunction rebuild<N>(cameFrom: Map<string, N>, key: NodeKey<N>, goal: N): N[] {\n const path: N[] = [goal];\n let cur = goal;\n let prev = cameFrom.get(key(cur));\n while (prev !== undefined) {\n cur = prev;\n path.push(cur);\n prev = cameFrom.get(key(cur));\n }\n path.reverse();\n return path;\n}\n\n/**\n * Binary min-heap keyed on a numeric priority, tie-broken by insertion sequence\n * so equal-priority items pop in push order \u2014 the source of A*'s determinism.\n */\nclass MinHeap<T> {\n private items: T[] = [];\n private prio: number[] = [];\n private seq: number[] = [];\n private counter = 0;\n\n get size(): number {\n return this.items.length;\n }\n\n push(item: T, priority: number): void {\n this.items.push(item);\n this.prio.push(priority);\n this.seq.push(this.counter++);\n this.bubbleUp(this.items.length - 1);\n }\n\n pop(): { item: T; priority: number } {\n const item = this.items[0];\n const priority = this.prio[0];\n const last = this.items.length - 1;\n this.swap(0, last);\n this.items.pop();\n this.prio.pop();\n this.seq.pop();\n if (this.items.length > 0) this.bubbleDown(0);\n return { item, priority };\n }\n\n /** true if a is strictly higher priority (lower value, then earlier seq). */\n private less(a: number, b: number): boolean {\n return this.prio[a] < this.prio[b] || (this.prio[a] === this.prio[b] && this.seq[a] < this.seq[b]);\n }\n\n private bubbleUp(i: number): void {\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (!this.less(i, parent)) break;\n this.swap(i, parent);\n i = parent;\n }\n }\n\n private bubbleDown(i: number): void {\n const n = this.items.length;\n for (;;) {\n const l = 2 * i + 1;\n const r = 2 * i + 2;\n let smallest = i;\n if (l < n && this.less(l, smallest)) smallest = l;\n if (r < n && this.less(r, smallest)) smallest = r;\n if (smallest === i) break;\n this.swap(i, smallest);\n i = smallest;\n }\n }\n\n private swap(a: number, b: number): void {\n [this.items[a], this.items[b]] = [this.items[b], this.items[a]];\n [this.prio[a], this.prio[b]] = [this.prio[b], this.prio[a]];\n [this.seq[a], this.seq[b]] = [this.seq[b], this.seq[a]];\n }\n}\n\n// \u2500\u2500 grid conveniences (row-major, tilemap-friendly) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface Cell {\n x: number;\n y: number;\n}\n\n/** 4-neighbour offsets (N, E, S, W), in a fixed order. */\nexport const NEIGHBORS_4: readonly Cell[] = [\n { x: 0, y: -1 },\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n];\n/** 8-neighbour offsets (orthogonals then diagonals), in a fixed order. */\nexport const NEIGHBORS_8: readonly Cell[] = [\n ...NEIGHBORS_4,\n { x: 1, y: -1 },\n { x: 1, y: 1 },\n { x: -1, y: 1 },\n { x: -1, y: -1 },\n];\n\n/** Is a cell walkable? Called for in-bounds cells only. */\nexport type Passable = (x: number, y: number) => boolean;\n\nconst cellKey = (c: Cell): string => `${c.x},${c.y}`;\n\nfunction gridNeighbours(passable: Passable, cols: number, rows: number, diagonal: boolean): Neighbours<Cell> {\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n return (c: Cell) => {\n const out: Cell[] = [];\n for (const o of offsets) {\n const x = c.x + o.x;\n const y = c.y + o.y;\n if (x < 0 || y < 0 || x >= cols || y >= rows) continue;\n if (!passable(x, y)) continue;\n out.push({ x, y });\n }\n return out;\n };\n}\n\n/**\n * Flood-fill from a seed cell over `passable`, returning every reachable cell\n * in breadth-first (deterministic) order. The classic bucket-fill / region-grab.\n */\nexport function floodFill(\n start: Cell,\n passable: Passable,\n opts: { cols: number; rows: number; diagonal?: boolean },\n): Cell[] {\n if (!passable(start.x, start.y)) return [];\n const nb = gridNeighbours(passable, opts.cols, opts.rows, opts.diagonal ?? false);\n return bfs(start, nb, cellKey).order;\n}\n\nexport interface Components {\n /** Row-major label per cell: -1 for impassable, else a component id \u2265 0. */\n labels: number[];\n /** Cells of each component, indexed by id, each in row-major order. */\n cells: Cell[][];\n}\n\n/**\n * Label connected regions of passable cells. Scans row-major and flood-fills\n * each unlabeled passable cell, so component ids are assigned deterministically\n * (top-left region first). Region/cluster detection for match-3, territory, etc.\n */\nexport function connectedComponents(cols: number, rows: number, passable: Passable, diagonal = false): Components {\n const labels = new Array<number>(cols * rows).fill(-1);\n const cells: Cell[][] = [];\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n if (labels[y * cols + x] !== -1 || !passable(x, y)) continue;\n const id = cells.length;\n const region: Cell[] = [];\n // Iterative BFS with an in-place label as the visited marker.\n let frontier: Cell[] = [{ x, y }];\n labels[y * cols + x] = id;\n while (frontier.length > 0) {\n const next: Cell[] = [];\n for (const c of frontier) {\n region.push(c);\n for (const o of offsets) {\n const nx = c.x + o.x;\n const ny = c.y + o.y;\n if (nx < 0 || ny < 0 || nx >= cols || ny >= rows) continue;\n const idx = ny * cols + nx;\n if (labels[idx] !== -1 || !passable(nx, ny)) continue;\n labels[idx] = id;\n next.push({ x: nx, y: ny });\n }\n }\n frontier = next;\n }\n cells.push(region);\n }\n }\n return { labels, cells };\n}\n\n/**\n * Grid A* / Dijkstra. Returns the least-cost cell path start\u2192goal (inclusive)\n * or null if unreachable. Default step cost is 1 (orthogonal) / \u221A2 (diagonal);\n * pass `cost(x,y)` to weight terrain. Heuristic defaults to Manhattan (4-dir)\n * or octile (8-dir) \u2014 admissible, integer-stable, so paths reproduce exactly.\n */\nexport function astarGrid(\n start: Cell,\n goal: Cell,\n passable: Passable,\n opts: { cols: number; rows: number; diagonal?: boolean; cost?: (x: number, y: number) => number; maxNodes?: number },\n): Cell[] | null {\n const diagonal = opts.diagonal ?? false;\n const offsets = diagonal ? NEIGHBORS_8 : NEIGHBORS_4;\n const stepCost = opts.cost ?? (() => 1);\n const SQRT2 = 1.4142135623730951;\n\n const neighbours: WeightedNeighbours<Cell> = (c) => {\n const out: WeightedEdge<Cell>[] = [];\n for (const o of offsets) {\n const x = c.x + o.x;\n const y = c.y + o.y;\n if (x < 0 || y < 0 || x >= opts.cols || y >= opts.rows) continue;\n if (!passable(x, y)) continue;\n const diag = o.x !== 0 && o.y !== 0;\n out.push({ node: { x, y }, cost: stepCost(x, y) * (diag ? SQRT2 : 1) });\n }\n return out;\n };\n\n const heuristic = (c: Cell): number => {\n const dx = Math.abs(c.x - goal.x);\n const dy = Math.abs(c.y - goal.y);\n if (!diagonal) return dx + dy; // Manhattan\n const lo = Math.min(dx, dy);\n return dx + dy - (2 - SQRT2) * lo; // octile\n };\n\n if (!passable(goal.x, goal.y)) return null;\n const result = astar(start, (c) => c.x === goal.x && c.y === goal.y, neighbours, cellKey, {\n heuristic,\n maxNodes: opts.maxNodes,\n });\n return result ? result.path : null;\n}\n\n/** Build a `Passable` from a tilemap: everything but SOLID/out-of-bounds walks. */\nexport function passableFromTilemap(map: TilemapData): Passable {\n return (x, y) => tileAt(map, x, y) !== TILE.SOLID;\n}\n", "// Undo / record-replay buffers over pure state. Nearly free given Hayao's\n// pure-logic + snapshot model, but worth packaging cleanly:\n// \u2022 UndoStack \u2014 a bounded memento (state-clone) stack with redo, for puzzle\n// undo over an immutable-ish State (dying-dreams clones its\n// PuzzleState; this is that, with a cursor and a size cap).\n// \u2022 RingBuffer \u2014 a bounded FIFO for ghost/echo trails (soul-jumper's 8-frame\n// pose history) \u2014 overwrites oldest, O(1) push.\n// Both are pure and deterministic; store their contents as plain data so they\n// ride along in `world.state` without escaping the hash.\n\n/** Deep clone used by default. structuredClone is available in Node \u226517 & browsers. */\nfunction deepClone<S>(s: S): S {\n return structuredClone(s);\n}\n\n/**\n * A memento stack for undo/redo over snapshots of pure state. Call `record()`\n * after every committed move; `undo()`/`redo()` walk the cursor. States are\n * cloned in and out so callers can freely mutate what they get back. Capacity is\n * bounded \u2014 the oldest entry is dropped once `limit` is exceeded (undo has a\n * horizon, memory doesn't grow without bound).\n */\nexport class UndoStack<S> {\n private history: S[] = [];\n private cursor = -1;\n private readonly limit: number;\n private readonly clone: (s: S) => S;\n\n constructor(opts: { limit?: number; clone?: (s: S) => S } = {}) {\n this.limit = Math.max(1, opts.limit ?? 64);\n this.clone = opts.clone ?? deepClone;\n }\n\n /** Push a new state as the present, discarding any redo branch ahead of it. */\n record(state: S): void {\n // Drop the redo tail, then append.\n this.history.length = this.cursor + 1;\n this.history.push(this.clone(state));\n this.cursor = this.history.length - 1;\n // Enforce the horizon from the front.\n if (this.history.length > this.limit) {\n const overflow = this.history.length - this.limit;\n this.history.splice(0, overflow);\n this.cursor -= overflow;\n }\n }\n\n /** Step back one state and return a clone of it (undefined if nothing to undo). */\n undo(): S | undefined {\n if (this.cursor <= 0) return undefined;\n this.cursor--;\n return this.clone(this.history[this.cursor]);\n }\n\n /** Step forward one state and return a clone of it (undefined if nothing to redo). */\n redo(): S | undefined {\n if (this.cursor >= this.history.length - 1) return undefined;\n this.cursor++;\n return this.clone(this.history[this.cursor]);\n }\n\n /** A clone of the current state, or undefined if empty. */\n current(): S | undefined {\n return this.cursor >= 0 ? this.clone(this.history[this.cursor]) : undefined;\n }\n\n get canUndo(): boolean {\n return this.cursor > 0;\n }\n get canRedo(): boolean {\n return this.cursor < this.history.length - 1;\n }\n /** Number of recorded states retained. */\n get size(): number {\n return this.history.length;\n }\n\n clear(): void {\n this.history.length = 0;\n this.cursor = -1;\n }\n}\n\n/**\n * A fixed-capacity ring buffer \u2014 the ghost/echo trail. Push a pose (or any value)\n * each frame; when full, the oldest is overwritten. `toArray()` returns\n * oldest\u2192newest, which is exactly the order a trail renderer wants (tail first,\n * head last). Pure and O(1) per push.\n */\nexport class RingBuffer<T> {\n private readonly buf: (T | undefined)[];\n private start = 0;\n private count = 0;\n\n constructor(readonly capacity: number) {\n if (!Number.isInteger(capacity) || capacity < 1) throw new Error('hayao: RingBuffer capacity must be a positive integer');\n this.buf = new Array<T | undefined>(capacity);\n }\n\n push(item: T): void {\n const end = (this.start + this.count) % this.capacity;\n this.buf[end] = item;\n if (this.count < this.capacity) {\n this.count++;\n } else {\n // Full: the write above overwrote the oldest slot; advance start past it.\n this.start = (this.start + 1) % this.capacity;\n }\n }\n\n /** Number of items currently held (\u2264 capacity). */\n get length(): number {\n return this.count;\n }\n get isFull(): boolean {\n return this.count === this.capacity;\n }\n\n /** Item by age index: 0 = oldest, length-1 = newest. Undefined if out of range. */\n at(i: number): T | undefined {\n if (i < 0 || i >= this.count) return undefined;\n return this.buf[(this.start + i) % this.capacity];\n }\n\n /** The most recently pushed item, or undefined if empty. */\n latest(): T | undefined {\n return this.at(this.count - 1);\n }\n\n /** Contents oldest\u2192newest. */\n toArray(): T[] {\n const out: T[] = [];\n for (let i = 0; i < this.count; i++) out.push(this.buf[(this.start + i) % this.capacity]!);\n return out;\n }\n\n clear(): void {\n this.start = 0;\n this.count = 0;\n this.buf.fill(undefined);\n }\n}\n", "// Pluggable persistence backend. The ONLY browser-coupled piece of save/load:\n// everything above it (codec, save manager) is pure and headless-stable. In the\n// browser you get `localStorage`; headless you get an in-memory map (so tests can\n// round-trip a save without touching disk or leaking global state) or a true\n// no-op. The sim never imports this directly \u2014 it snapshots/restores plain data.\n\n/**\n * A minimal key\u2192string store. Deliberately tiny (get/set/remove/keys) so any\n * backend \u2014 `localStorage`, a Map, a file, IndexedDB \u2014 satisfies it trivially.\n */\nexport interface StorageAdapter {\n get(key: string): string | null;\n set(key: string, value: string): void;\n remove(key: string): void;\n /** All keys currently held, in insertion order where the backend preserves it. */\n keys(): string[];\n}\n\n/** In-memory backend. Deterministic and self-contained \u2014 the headless default. */\nexport class MemoryStorage implements StorageAdapter {\n private readonly map = new Map<string, string>();\n\n get(key: string): string | null {\n return this.map.has(key) ? this.map.get(key)! : null;\n }\n set(key: string, value: string): void {\n this.map.set(key, value);\n }\n remove(key: string): void {\n this.map.delete(key);\n }\n keys(): string[] {\n return [...this.map.keys()];\n }\n}\n\n/** Swallows everything \u2014 reads always miss. For runs that must stay pristine. */\nexport class NullStorage implements StorageAdapter {\n get(_key: string): string | null {\n return null;\n }\n set(_key: string, _value: string): void {}\n remove(_key: string): void {}\n keys(): string[] {\n return [];\n }\n}\n\n/**\n * `localStorage`-backed, guarded on every call: a disabled/absent/full store\n * (private mode, quota, SSR) degrades to a silent miss instead of throwing, so a\n * save failure never crashes a game. Keys are namespaced by `prefix`.\n */\nexport class LocalStorageAdapter implements StorageAdapter {\n constructor(private readonly prefix = 'hayao.save.') {}\n\n private ls(): Storage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null; // access itself can throw when cookies/storage are blocked\n }\n }\n\n get(key: string): string | null {\n try {\n return this.ls()?.getItem(this.prefix + key) ?? null;\n } catch {\n return null;\n }\n }\n set(key: string, value: string): void {\n try {\n this.ls()?.setItem(this.prefix + key, value);\n } catch {\n /* quota / disabled \u2014 a lost save beats a crash */\n }\n }\n remove(key: string): void {\n try {\n this.ls()?.removeItem(this.prefix + key);\n } catch {\n /* ignore */\n }\n }\n keys(): string[] {\n const ls = this.ls();\n if (!ls) return [];\n const out: string[] = [];\n try {\n for (let i = 0; i < ls.length; i++) {\n const k = ls.key(i);\n if (k && k.startsWith(this.prefix)) out.push(k.slice(this.prefix.length));\n }\n } catch {\n /* ignore */\n }\n return out;\n }\n}\n\n/**\n * The right adapter for the current environment: `localStorage` when a real one\n * is present (browser), otherwise an in-memory map (headless tests/CI). Pass\n * `NullStorage` explicitly when you want reads to always miss.\n */\nexport function defaultStorage(prefix?: string): StorageAdapter {\n try {\n if (typeof localStorage !== 'undefined') {\n // Feature-probe rather than trust the global: some headless runtimes expose\n // a `localStorage` object whose methods throw. A real write/read/remove is\n // the only honest test; any failure falls through to the in-memory backend.\n const probe = '__hayao_probe__';\n localStorage.setItem(probe, '1');\n localStorage.removeItem(probe);\n return new LocalStorageAdapter(prefix);\n }\n } catch {\n /* fall through to memory */\n }\n return new MemoryStorage();\n}\n", "// Compact string codecs for levels and state \u2014 the js13k byte-squeeze trick, made\n// deterministic and fully reversible. Two independent tools:\n// \u2022 RLE \u2014 collapse runs in grid/level strings (walls, tiles), witchcat-style.\n// \u2022 varint pack \u2014 pack a list of small non-negative ints into a short URL-safe\n// string (base-64 continuation varints), soul-surf encode/decode.\n// Both are pure functions with exact round-trips; no RNG, no clock, no browser.\n\n// \u2500\u2500 Run-length encoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Reversible for ANY string. A run of \u22654 (or any literal escape char) becomes\n// `~<char><count>~`; shorter runs stay literal. Compact for repetitive maps,\n// never larger by more than the escapes it introduces.\nconst ESC = '~';\nconst RLE_MIN_RUN = 4;\n\nexport function rleEncode(input: string): string {\n let out = '';\n let i = 0;\n while (i < input.length) {\n const ch = input[i];\n let run = 1;\n while (i + run < input.length && input[i + run] === ch) run++;\n if (run >= RLE_MIN_RUN || ch === ESC) {\n out += ESC + ch + run.toString(36) + ESC;\n } else {\n out += ch.repeat(run);\n }\n i += run;\n }\n return out;\n}\n\nexport function rleDecode(input: string): string {\n let out = '';\n let i = 0;\n while (i < input.length) {\n if (input[i] === ESC) {\n const ch = input[i + 1];\n const end = input.indexOf(ESC, i + 2);\n if (ch === undefined || end < 0) throw new Error('hayao: malformed RLE stream');\n const count = parseInt(input.slice(i + 2, end), 36);\n if (!Number.isFinite(count) || count < 1) throw new Error('hayao: malformed RLE count');\n out += ch.repeat(count);\n i = end + 1;\n } else {\n out += input[i];\n i++;\n }\n }\n return out;\n}\n\n// \u2500\u2500 Base-64 variable-length integers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n// Pack non-negative integers into a URL/JSON-safe string: 6 bits per char, the\n// top bit a continuation flag (LEB128-style, base 32 per digit). Ideal for\n// coordinate lists, tile ids, and other small-int level payloads.\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\nconst INDEX: Record<string, number> = {};\nfor (let i = 0; i < ALPHABET.length; i++) INDEX[ALPHABET[i]] = i;\n\nexport function packVarints(nums: readonly number[]): string {\n let out = '';\n for (const n of nums) {\n if (!Number.isInteger(n) || n < 0) throw new Error(`hayao: packVarints expects non-negative integers, got ${n}`);\n let v = n;\n do {\n let digit = v & 0x1f; // low 5 bits\n v = Math.floor(v / 32);\n if (v > 0) digit |= 0x20; // continuation bit\n out += ALPHABET[digit];\n } while (v > 0);\n }\n return out;\n}\n\nexport function unpackVarints(input: string): number[] {\n const out: number[] = [];\n let v = 0;\n let shift = 1;\n for (const ch of input) {\n const digit = INDEX[ch];\n if (digit === undefined) throw new Error(`hayao: unpackVarints saw invalid char \"${ch}\"`);\n v += (digit & 0x1f) * shift;\n if (digit & 0x20) {\n shift *= 32; // more digits follow\n } else {\n out.push(v);\n v = 0;\n shift = 1;\n }\n }\n if (shift !== 1) throw new Error('hayao: unpackVarints hit a truncated stream');\n return out;\n}\n", "// Player-facing save/load over a pluggable StorageAdapter. Built ON TOP of the\n// existing `world.snapshot()`/`world.restore()` seam \u2014 it does NOT reinvent\n// serialization; it versions, guards, and persists what the world already emits.\n// A restored world reproduces the saved `hash()`/`probe()` exactly.\n\nimport type { World, WorldSnapshot } from '../world';\nimport { defaultStorage, type StorageAdapter } from './storage';\n\n/** Envelope stored per slot: a version tag around the raw WorldSnapshot. */\ninterface SaveEnvelope {\n v: number;\n snap: WorldSnapshot;\n}\n\n/** Bump when the snapshot shape changes in a way old saves can't satisfy. */\nexport const SAVE_FORMAT_VERSION = 1;\n\n/** Serialize a snapshot to a compact JSON string with a version envelope. */\nexport function serializeSnapshot(snap: WorldSnapshot): string {\n const envelope: SaveEnvelope = { v: SAVE_FORMAT_VERSION, snap };\n return JSON.stringify(envelope);\n}\n\n/**\n * Parse a serialized snapshot back. Returns `null` on anything malformed \u2014\n * corrupt JSON, wrong version, missing fields \u2014 so a bad save is a clean miss,\n * never a thrown exception mid-game. Guards `JSON.parse` per the invariant.\n */\nexport function parseSnapshot(text: string | null): WorldSnapshot | null {\n if (!text) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== 'object') return null;\n const env = parsed as Partial<SaveEnvelope>;\n if (env.v !== SAVE_FORMAT_VERSION || !env.snap || typeof env.snap !== 'object') return null;\n const snap = env.snap as Partial<WorldSnapshot>;\n // Minimal shape check on the fields `restore()` reads.\n if (typeof snap.seed !== 'number' || !snap.rng || !snap.clock || !snap.input || !snap.state || !snap.tree) {\n return null;\n }\n return snap as WorldSnapshot;\n}\n\n/**\n * A tiny save API bound to one World and one storage backend. Slots are named\n * ('auto', 'slot1', \u2026). Everything routes through `world.snapshot()`/`restore()`\n * so the saved and restored states share a hash.\n */\nexport class SaveManager {\n constructor(\n private readonly world: World,\n private readonly storage: StorageAdapter = defaultStorage(),\n ) {}\n\n /** Snapshot the world and persist it under `slot`. */\n save(slot = 'auto'): void {\n this.storage.set(slot, serializeSnapshot(this.world.snapshot()));\n }\n\n /** Restore `slot` into the world. Returns false if absent/corrupt (world untouched). */\n load(slot = 'auto'): boolean {\n const snap = parseSnapshot(this.storage.get(slot));\n if (!snap) return false;\n this.world.restore(snap);\n return true;\n }\n\n /** Is there a well-formed save in `slot`? */\n has(slot = 'auto'): boolean {\n return parseSnapshot(this.storage.get(slot)) !== null;\n }\n\n /** Delete a save slot. */\n delete(slot = 'auto'): void {\n this.storage.remove(slot);\n }\n\n /** All slot names currently persisted. */\n slots(): string[] {\n return this.storage.keys();\n }\n}\n", "// Data-driven content: a small schema + interpreter for declarative game content,\n// so waves, spawn tables, and upgrade trees are DATA (hashable, editable, diff-able)\n// rather than hand-rolled control flow. Two primitives, one determinism rule \u2014\n// rolls draw from `world.rng`, scheduling reads `world.time` (fixed sim seconds):\n// \u2022 SpawnDirector \u2014 a flat wave/spawn schedule (norman) with repeats and an\n// optional weighted spawn set (cat-survivors' director).\n// \u2022 upgrade trees \u2014 availability gating by owned prerequisites (evolutions).\n// Weighted rolls reuse `logic/random` (WeightedEntry + pickEntry), not a private\n// copy. The director's cursor state is plain JSON, so it lives in `world.state`\n// and is snapshotted/hashed like everything else.\n\nimport type { Rng } from '../core/rng';\nimport { pickEntry, type WeightedEntry } from '../logic/random';\n\n// \u2500\u2500 Wave / spawn director \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * One declarative wave. Fires `count` of `spawn` at time `time` (sim seconds).\n * When `every` is set it repeats on that interval until `end` (exclusive),\n * modelling a continuous spawn stream. `spawn` may be a single id or a weighted\n * table, in which case each firing rolls the table via `world.rng`.\n */\nexport interface WaveDef {\n /** First fire time, in fixed sim seconds (compare against `world.time`). */\n time: number;\n /** What to spawn: a fixed id, or a weighted set rolled per firing. */\n spawn: string | WeightedEntry<string>[];\n /** How many per firing (default 1). */\n count?: number;\n /** Repeat interval in seconds; omit for a one-shot wave. */\n every?: number;\n /** Repeats stop once the next fire time reaches this (seconds). */\n end?: number;\n}\n\n/** Mutable director cursor \u2014 plain JSON, keep it in `world.state`. */\nexport interface DirectorState {\n /** Next fire time per wave index; Infinity once a wave is exhausted. */\n next: number[];\n}\n\n/** One resolved spawn instruction emitted by the director. */\nexport interface SpawnEvent {\n /** Concrete spawn id (already rolled if the wave used a weighted set). */\n spawn: string;\n count: number;\n /** Source wave index, for callers that want to key behavior off the wave. */\n wave: number;\n}\n\n/** Initialize a director cursor for a schedule. */\nexport function initDirector(waves: readonly WaveDef[]): DirectorState {\n return { next: waves.map((w) => w.time) };\n}\n\n/**\n * Advance the director to `time` (sim seconds) and return every spawn that is\n * now due, in wave order. Mutates `state.next` in place. Deterministic: it emits\n * the same events for the same (schedule, time, rng-state) on every machine.\n * A repeating wave can fire multiple times in one poll if the frame straddled\n * several intervals (e.g. after a restore), so catch-up never drops spawns.\n */\nexport function pollDirector(waves: readonly WaveDef[], state: DirectorState, time: number, rng?: Rng): SpawnEvent[] {\n const out: SpawnEvent[] = [];\n for (let i = 0; i < waves.length; i++) {\n const w = waves[i];\n let next = state.next[i] ?? w.time;\n while (next <= time) {\n let spawn: string;\n if (typeof w.spawn === 'string') {\n spawn = w.spawn;\n } else {\n if (!rng) throw new Error('hayao: pollDirector needs an Rng to roll a weighted wave');\n spawn = pickEntry(rng, w.spawn);\n }\n out.push({ spawn, count: w.count ?? 1, wave: i });\n if (w.every && w.every > 0) {\n next += w.every;\n if (w.end !== undefined && next >= w.end) {\n next = Infinity;\n break;\n }\n } else {\n next = Infinity;\n break;\n }\n }\n state.next[i] = next;\n }\n return out;\n}\n\n// \u2500\u2500 Upgrade / evolution trees \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n/**\n * A declarative upgrade or evolution node. `requires` lists ids that must all be\n * owned before this one can be offered \u2014 the cat-survivors evolution gate and a\n * deckbuilder's upgrade prerequisites are the same shape.\n */\nexport interface UpgradeDef {\n id: string;\n /** Ids that must all be owned before this becomes available. */\n requires?: string[];\n /** Optional: only offer while UNDER this many owned copies (repeatable upgrades). */\n maxStacks?: number;\n}\n\n/**\n * Which upgrades are offerable given what's owned: prerequisites all met, and\n * not already at `maxStacks` (default 1 \u2014 offered until owned once). `owned` may\n * repeat ids to represent stacks. Ordered by definition order for hash stability.\n */\nexport function availableUpgrades(defs: readonly UpgradeDef[], owned: readonly string[]): UpgradeDef[] {\n const counts = new Map<string, number>();\n for (const id of owned) counts.set(id, (counts.get(id) ?? 0) + 1);\n const has = (id: string) => (counts.get(id) ?? 0) > 0;\n return defs.filter((d) => {\n const stacks = counts.get(d.id) ?? 0;\n if (stacks >= (d.maxStacks ?? 1)) return false;\n return (d.requires ?? []).every(has);\n });\n}\n", "// Levels as DATA, not code. A LevelData is a plain-JSON description of a stage \u2014\n// ASCII terrain, a spawn, a goal, and legend-tagged entities \u2014 that an agent can\n// emit, diff, and (crucially) PROVE before a single node is built. This is the\n// artifact the \"core vs. recipes\" split turns on: geometry lives in data a solver\n// can bite on, not in imperative build() calls only a human can eyeball.\n//\n// Two proofs ship with the format:\n// \u2022 levelReachable \u2014 4/8-neighbour flood connectivity (top-down/roguelike).\n// \u2022 platformerReachable \u2014 foothold + jump-arc reachability (a real \"can you\n// actually climb to the goal?\" proof for platformers).\n// Both run on the data alone \u2014 the FUN.md \"procgen connectivity gate FIRST, before\n// any numeric tuning\" made checkable for hand-authored stages too.\n//\n// Reserved ASCII: 'S' spawn \u00B7 'G' goal \u00B7 '#' solid \u00B7 '-' one-way \u00B7 '^' hazard \u00B7\n// '.'/' ' empty. Any other char is an entity if it appears in `legend`.\n\nimport { tilemapFromAscii, TILE, type TilemapData } from '../physics/tilemap';\nimport { floodFill, type Cell, type Passable } from '../logic/graph';\n\nexport interface LevelEntity {\n /** Entity kind, resolved from the legend (e.g. 'crystal', 'gust'). */\n kind: string;\n /** Tile coordinates. */\n tx: number;\n ty: number;\n /** Center of the tile in design-space px. */\n x: number;\n y: number;\n}\n\n/** The authored input: rows + a legend. Everything else is derived. */\nexport interface LevelSpec {\n name: string;\n /** Tile edge in px (default 32). */\n tileSize?: number;\n /** ASCII rows, top to bottom. Ragged rows are padded with empty on the right. */\n rows: string[];\n /** Non-terrain marker char \u2192 entity kind. 'S'/'G' are reserved and need no legend. */\n legend?: Record<string, string>;\n}\n\n/** The resolved, validated level \u2014 plain JSON, safe to hash/snapshot/diff. */\nexport interface LevelData extends Required<Omit<LevelSpec, 'legend'>> {\n legend: Record<string, string>;\n cols: number;\n rowCount: number;\n spawn: Cell;\n goal: Cell;\n entities: LevelEntity[];\n}\n\nconst TERRAIN = new Set(['#', '-', '^', '.', ' ']);\nconst isSolid = (id: number): boolean => id === TILE.SOLID;\nconst isHazard = (id: number): boolean => id === TILE.HAZARD;\n\n/** Center of a tile in design-space px. */\nexport const tileCenter = (tx: number, ty: number, tileSize: number): { x: number; y: number } => ({\n x: (tx + 0.5) * tileSize,\n y: (ty + 0.5) * tileSize,\n});\n\n/**\n * Resolve a LevelSpec into a full LevelData: find the spawn/goal markers, extract\n * legend entities, and record dimensions. Throws only on the two structural sins\n * that make a level meaningless (no spawn, no goal); everything else is surfaced\n * as a soft issue by `levelIssues` so an agent can see ALL problems at once.\n */\nexport function defineLevel(spec: LevelSpec): LevelData {\n const tileSize = spec.tileSize ?? 32;\n const legend = spec.legend ?? {};\n const rows = spec.rows;\n const cols = Math.max(0, ...rows.map((r) => r.length));\n let spawn: Cell | null = null;\n let goal: Cell | null = null;\n const entities: LevelEntity[] = [];\n rows.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) {\n const ch = row[tx];\n if (ch === 'S') spawn = { x: tx, y: ty };\n else if (ch === 'G') goal = { x: tx, y: ty };\n else if (ch in legend) {\n const c = tileCenter(tx, ty, tileSize);\n entities.push({ kind: legend[ch], tx, ty, x: c.x, y: c.y });\n }\n }\n });\n if (!spawn) throw new Error(`level \"${spec.name}\": no spawn marker 'S'`);\n if (!goal) throw new Error(`level \"${spec.name}\": no goal marker 'G'`);\n return { name: spec.name, tileSize, rows, legend, cols, rowCount: rows.length, spawn, goal, entities };\n}\n\n/**\n * Validate a level's data. Returns human-readable issues (empty = clean), in the\n * layoutIssues idiom. Catches unknown glyphs, spawn/goal buried in solid, and\n * markers off the map \u2014 the authoring mistakes that produce a broken stage.\n */\nexport function levelIssues(data: LevelData): string[] {\n const issues: string[] = [];\n const map = levelToTilemap(data);\n const at = (c: Cell): number => map.tiles[c.y * map.cols + c.x] ?? TILE.EMPTY;\n data.rows.forEach((row, ty) => {\n for (let tx = 0; tx < row.length; tx++) {\n const ch = row[tx];\n if (ch === 'S' || ch === 'G' || TERRAIN.has(ch) || ch in data.legend) continue;\n issues.push(`unknown glyph '${ch}' at (${tx},${ty}) \u2014 add it to the legend or use terrain '#/-/^/.'`);\n }\n });\n if (isSolid(at(data.spawn))) issues.push(`spawn (${data.spawn.x},${data.spawn.y}) is inside a solid tile`);\n if (isSolid(at(data.goal))) issues.push(`goal (${data.goal.x},${data.goal.y}) is inside a solid tile`);\n return [...new Set(issues)];\n}\n\n/** Build the collision tilemap from the level's terrain (markers \u2192 empty). */\nexport function levelToTilemap(data: LevelData): TilemapData {\n return tilemapFromAscii(data.rows, data.tileSize);\n}\n\nexport interface ReachReport {\n ok: boolean;\n /** Labels of things the spawn cannot reach ('goal', or 'entity@tx,ty'). */\n unreachable: string[];\n /** Count of reachable cells/footholds (search size). */\n reached: number;\n}\n\n/**\n * Generic connectivity proof: flood-fill non-solid cells from the spawn and check\n * the goal (and every entity) is reachable. Right for top-down / roguelike stages\n * where movement is grid-walking. `passable` defaults to \"not a solid tile\".\n */\nexport function levelReachable(data: LevelData, opts: { passable?: Passable; diagonal?: boolean } = {}): ReachReport {\n const map = levelToTilemap(data);\n const tileAt = (x: number, y: number): number => map.tiles[y * map.cols + x] ?? TILE.EMPTY;\n const passable = opts.passable ?? ((x: number, y: number) => !isSolid(tileAt(x, y)));\n const reached = floodFill(data.spawn, passable, { cols: map.cols, rows: map.rows, diagonal: opts.diagonal });\n const seen = new Set(reached.map((c) => `${c.x},${c.y}`));\n const unreachable: string[] = [];\n if (!seen.has(`${data.goal.x},${data.goal.y}`)) unreachable.push('goal');\n for (const e of data.entities) if (!seen.has(`${e.tx},${e.ty}`)) unreachable.push(`entity@${e.tx},${e.ty}`);\n return { ok: unreachable.length === 0, unreachable, reached: reached.length };\n}\n\nexport interface PlatformerReachOptions {\n /** Max tiles the body can rise in one jump (derive from jumpHeight / tileSize). */\n jumpTiles: number;\n /** Max horizontal tiles cleared in a jump (derive from jumpDistance / tileSize). */\n runTiles: number;\n}\n\n/**\n * Platformer reachability: build the graph of FOOTHOLDS (a non-solid, non-hazard\n * cell with solid/one-way ground directly below) and connect two footholds when a\n * jump arc can carry the body between them \u2014 up to `jumpTiles` of rise, any drop,\n * within `runTiles` horizontally. Then BFS from the spawn's foothold and confirm\n * the goal's foothold is reachable. This is the honest \"can you actually climb it?\"\n * proof a flat flood-fill can't give \u2014 it respects gravity and jump limits.\n */\nexport function platformerReachable(data: LevelData, opts: PlatformerReachOptions): ReachReport {\n const map = levelToTilemap(data);\n const { cols, rows } = map;\n const tileAt = (x: number, y: number): number => (x < 0 || y < 0 || x >= cols || y >= rows ? TILE.SOLID : map.tiles[y * cols + x]);\n const grounded = (x: number, y: number): boolean => {\n const below = tileAt(x, y + 1);\n return below === TILE.SOLID || below === TILE.ONEWAY;\n };\n const isFoothold = (x: number, y: number): boolean => !isSolid(tileAt(x, y)) && !isHazard(tileAt(x, y)) && grounded(x, y);\n\n // Spawn falls to the foothold at or below its marker (you drop onto the ground).\n const snapDown = (c: Cell): Cell | null => {\n for (let y = c.y; y < rows; y++) if (isFoothold(c.x, y)) return { x: c.x, y };\n return null;\n };\n const start = snapDown(data.spawn);\n if (!start) return { ok: false, unreachable: ['goal'], reached: 0 };\n\n // A jump arc connects footholds within runTiles horizontally and jumpTiles of\n // RISE (any fall is allowed \u2014 gravity is free). Same test decides \"can I touch\n // a target cell from this foothold\", so a floating goal keeps its height cost.\n const reachesArc = (from: Cell, to: Cell): boolean => Math.abs(to.x - from.x) <= opts.runTiles && from.y - to.y <= opts.jumpTiles;\n\n const footholds: Cell[] = [];\n for (let y = 0; y < rows; y++) for (let x = 0; x < cols; x++) if (isFoothold(x, y)) footholds.push({ x, y });\n const key = (c: Cell): string => `${c.x},${c.y}`;\n const seen = new Set<string>([key(start)]);\n const frontier: Cell[] = [start];\n while (frontier.length) {\n const cur = frontier.shift()!;\n for (const f of footholds) {\n const k = key(f);\n if (!seen.has(k) && reachesArc(cur, f)) {\n seen.add(k);\n frontier.push(f);\n }\n }\n }\n // Goal is touched if its cell is a reached foothold OR sits within a jump arc of\n // one \u2014 a marooned goal five tiles above every foothold is correctly unreachable.\n const reachedCells = [...seen].map((s) => { const [x, y] = s.split(',').map(Number); return { x, y }; });\n const goalTouched = !isSolid(tileAt(data.goal.x, data.goal.y)) && (seen.has(key(data.goal)) || reachedCells.some((f) => reachesArc(f, data.goal)));\n const unreachable: string[] = goalTouched ? [] : ['goal'];\n return { ok: unreachable.length === 0, unreachable, reached: seen.size };\n}\n\nexport interface LevelChange {\n kind: 'tile' | 'entity+' | 'entity-' | 'spawn' | 'goal';\n detail: string;\n}\n\n/**\n * Structural diff between two levels \u2014 the primitive that makes data-authored\n * stages iterable: change three tiles, see exactly three changes, not a whole\n * rewritten build() function. Compares terrain cell-by-cell, entities by position,\n * and the spawn/goal markers.\n */\nexport function diffLevels(a: LevelData, b: LevelData): LevelChange[] {\n const out: LevelChange[] = [];\n const rows = Math.max(a.rowCount, b.rowCount);\n const cols = Math.max(a.cols, b.cols);\n const cellOf = (d: LevelData, x: number, y: number): string => d.rows[y]?.[x] ?? ' ';\n for (let y = 0; y < rows; y++) {\n for (let x = 0; x < cols; x++) {\n const ca = cellOf(a, x, y);\n const cb = cellOf(b, x, y);\n if (ca !== cb) out.push({ kind: 'tile', detail: `(${x},${y}) '${ca}' \u2192 '${cb}'` });\n }\n }\n const eKey = (e: LevelEntity): string => `${e.kind}@${e.tx},${e.ty}`;\n const aE = new Set(a.entities.map(eKey));\n const bE = new Set(b.entities.map(eKey));\n for (const e of b.entities) if (!aE.has(eKey(e))) out.push({ kind: 'entity+', detail: eKey(e) });\n for (const e of a.entities) if (!bE.has(eKey(e))) out.push({ kind: 'entity-', detail: eKey(e) });\n if (a.spawn.x !== b.spawn.x || a.spawn.y !== b.spawn.y) out.push({ kind: 'spawn', detail: `(${a.spawn.x},${a.spawn.y}) \u2192 (${b.spawn.x},${b.spawn.y})` });\n if (a.goal.x !== b.goal.x || a.goal.y !== b.goal.y) out.push({ kind: 'goal', detail: `(${a.goal.x},${a.goal.y}) \u2192 (${b.goal.x},${b.goal.y})` });\n return out;\n}\n", "// Solver-backed level GENERATION \u2014 the piece that turns \"an agent hand-authors\n// forty balanced rooms\" (unreliable) into \"an agent calls a generator and gets\n// forty PROVEN rooms\" (reliable). This is the content-volume unlock: the solver\n// (verify/solver) already proves one hand-authored level winnable; here we run it\n// in a loop over procedurally-seeded candidates and keep only the ones that are\n// both winnable AND land inside a target difficulty band.\n//\n// Genre-agnostic by construction. You pass a `factory(rng) \u2192 Puzzle` that builds\n// ONE candidate level from a seeded stream (a Sokoban layout, a tactics board, a\n// wiring puzzle \u2014 anything that implements the pure `Puzzle` contract). The\n// generator derives an independent, reproducible sub-seed per attempt, builds the\n// candidate, solves it, and accepts it only if the proof lands in-band. Every kept\n// level carries the sub-seed that reproduces it exactly, so the campaign that\n// ships is data (a list of seeds), not forty hand-written maps.\n//\n// Determinism: the same (seed, count, band, factory) yields the same set on every\n// machine \u2014 sub-seeds come from `hashString`, never wall-clock or Math.random.\n\nimport { Rng, hashString } from '../core/rng';\nimport { solve, type Puzzle, type SolveOptions } from '../verify/solver';\n\n/** A difficulty window expressed on the solver's own proof metrics. */\nexport interface DifficultyBand {\n /** Minimum solution length (shortest winning move count). Below this = trivial. */\n minDepth?: number;\n /** Maximum solution length. Above this = a slog / likely unfair. */\n maxDepth?: number;\n /** Minimum nodes the solver expanded (a branchiness / \"how much thinking\" proxy). */\n minNodes?: number;\n /** Maximum nodes expanded \u2014 caps combinatorial monsters. */\n maxNodes?: number;\n}\n\nexport interface GenerateOptions<State, Move> extends DifficultyBand {\n /** How many verified levels to return. */\n count: number;\n /** Base seed; the whole run is a pure function of it (default 1). */\n seed?: number;\n /** Cap on candidate attempts before giving up (default count * 60). */\n maxAttempts?: number;\n /** Search budget handed to the solver per candidate. */\n solve?: SolveOptions;\n /**\n * Extra rejection hook \u2014 return true to discard an otherwise in-band candidate\n * (e.g. a genre-specific \"too few boxes\" or \"spawn adjacent to goal\" rule).\n */\n reject?: (puzzle: Puzzle<State, Move>, result: AcceptedProof<Move>, subSeed: number) => boolean;\n /**\n * Canonical de-dup key for a candidate. Defaults to the puzzle's own initial\n * state key, so two seeds that happen to build the same layout collapse to one.\n */\n dedupeKey?: (puzzle: Puzzle<State, Move>, result: AcceptedProof<Move>) => string;\n}\n\n/** The solver proof carried by an accepted candidate. */\nexport interface AcceptedProof<Move> {\n /** Shortest winning move sequence (the existence proof). */\n path: Move[];\n /** Its length \u2014 the primary difficulty metric. */\n depth: number;\n /** Nodes the solver expanded to find it \u2014 a complexity proxy. */\n nodes: number;\n}\n\n/** A generated, solver-verified level: reproducible from `seed`, ramped by `depth`. */\nexport interface GeneratedLevel<State, Move> extends AcceptedProof<Move> {\n /** Position in the returned (difficulty-sorted) sequence. */\n index: number;\n /** The sub-seed that rebuilds this exact puzzle via `factory(new Rng(seed))`. */\n seed: number;\n /** The built puzzle instance (single-level: `initial()` returns this candidate). */\n puzzle: Puzzle<State, Move>;\n}\n\nexport interface GenerateReport<State, Move> {\n levels: GeneratedLevel<State, Move>[];\n /** Candidates tried. */\n attempts: number;\n /** How many were solvable at all (in-band or not). */\n solvable: number;\n /** True if `count` levels were found before `maxAttempts` ran out. */\n complete: boolean;\n /** Reproduce the whole run: the sub-seeds, in ramp order. */\n seeds: number[];\n}\n\n/** Derive an independent, reproducible sub-seed for attempt `i` of a base run. */\nexport function subSeed(seed: number, i: number): number {\n return hashString(`hayao/gen:${seed >>> 0}:${i}`);\n}\n\nconst inBand = (depth: number, nodes: number, band: DifficultyBand): boolean =>\n (band.minDepth === undefined || depth >= band.minDepth) &&\n (band.maxDepth === undefined || depth <= band.maxDepth) &&\n (band.minNodes === undefined || nodes >= band.minNodes) &&\n (band.maxNodes === undefined || nodes <= band.maxNodes);\n\n/**\n * Generate `count` solver-verified levels inside a difficulty band. Builds\n * candidates from `factory`, proves each with the BFS solver, and keeps the\n * in-band, non-duplicate ones \u2014 sorted by solution depth so the returned\n * sequence already ramps. Pure: same options \u2192 same levels, everywhere.\n *\n * A capped solver search (`exhausted`) is treated as \"unknown, reject\" \u2014 a level\n * only ships if it was actually PROVEN winnable within budget.\n */\nexport function generateLevelsReport<State, Move>(\n factory: (rng: Rng) => Puzzle<State, Move>,\n opts: GenerateOptions<State, Move>,\n): GenerateReport<State, Move> {\n const seed = opts.seed ?? 1;\n const maxAttempts = opts.maxAttempts ?? opts.count * 60;\n const dedupeKey = opts.dedupeKey ?? ((p) => p.key(p.initial()));\n const kept: GeneratedLevel<State, Move>[] = [];\n const seen = new Set<string>();\n let attempts = 0;\n let solvable = 0;\n\n for (let i = 0; i < maxAttempts && kept.length < opts.count; i++) {\n attempts++;\n const s = subSeed(seed, i);\n const puzzle = factory(new Rng(s));\n const res = solve(puzzle, opts.solve);\n if (!res.solvable || res.exhausted || res.depth === undefined) continue;\n solvable++;\n const proof: AcceptedProof<Move> = { path: res.path ?? [], depth: res.depth, nodes: res.nodes };\n if (!inBand(proof.depth, proof.nodes, opts)) continue;\n const k = dedupeKey(puzzle, proof);\n if (seen.has(k)) continue;\n if (opts.reject?.(puzzle, proof, s)) continue;\n seen.add(k);\n kept.push({ ...proof, index: 0, seed: s, puzzle });\n }\n\n // Ramp: shortest solution first, nodes as a stable tiebreak, then seed.\n kept.sort((a, b) => a.depth - b.depth || a.nodes - b.nodes || a.seed - b.seed);\n kept.forEach((l, idx) => (l.index = idx));\n\n return {\n levels: kept,\n attempts,\n solvable,\n complete: kept.length >= opts.count,\n seeds: kept.map((l) => l.seed),\n };\n}\n\n/** Convenience: just the ramped levels. Throws if the band was too tight to fill. */\nexport function generateLevels<State, Move>(\n factory: (rng: Rng) => Puzzle<State, Move>,\n opts: GenerateOptions<State, Move>,\n): GeneratedLevel<State, Move>[] {\n const report = generateLevelsReport(factory, opts);\n if (!report.complete) {\n throw new Error(\n `hayao: generator found only ${report.levels.length}/${opts.count} in-band levels ` +\n `in ${report.attempts} attempts (${report.solvable} solvable). ` +\n `Widen the band [depth ${opts.minDepth ?? 0}..${opts.maxDepth ?? '\u221E'}] or raise maxAttempts.`,\n );\n }\n return report.levels;\n}\n\n/** Rebuild the exact puzzle for a stored sub-seed \u2014 the campaign ships seeds, not maps. */\nexport function levelFromSeed<State, Move>(\n factory: (rng: Rng) => Puzzle<State, Move>,\n seed: number,\n): Puzzle<State, Move> {\n return factory(new Rng(seed));\n}\n", "// Campaign composition \u2014 the layer that turns a solver-backed GENERATOR into an\n// hour of shaped content. `generate.ts` yields a pile of proven, in-band levels;\n// this stitches them into an ordered, multi-act progression whose difficulty\n// escalates act over act, with an honest length estimate. The whole campaign is\n// DATA \u2014 a list of reproducible sub-seeds and act boundaries \u2014 so it hashes,\n// diffs, and ships without ever hand-authoring a map.\n//\n// Each act declares its own difficulty band; because later acts sit in higher\n// bands, the concatenated curve rises across the whole game. Feed the resulting\n// `.difficulty` series straight to `rampIssues`/`assertRamp` (verify/ramp) to\n// PROVE the hour is well-shaped, the same way `assertSolvable` proves one level.\n\nimport type { Rng } from '../core/rng';\nimport type { Puzzle } from '../verify/solver';\nimport type { SolveOptions } from '../verify/solver';\nimport {\n generateLevels,\n type DifficultyBand,\n type GeneratedLevel,\n} from './generate';\n\n/** One named stretch of the campaign, generated inside its own difficulty band. */\nexport interface ActSpec<State = unknown, Move = unknown> extends DifficultyBand {\n /** Display name (\"The Shallows\", \"Deep Roots\", \u2026). */\n name: string;\n /** How many verified levels this act contributes. */\n count: number;\n /**\n * Optional per-act candidate factory \u2014 overrides the campaign default. This is\n * how an act introduces a NEW mechanic or board size (a bigger grid, a new tile\n * kind) while the earlier acts keep the simpler one: mechanic-gating as data.\n */\n factory?: (rng: Rng) => Puzzle<State, Move>;\n /** Optional per-act solver budget override. */\n solve?: SolveOptions;\n /** Optional per-act attempt cap override. */\n maxAttempts?: number;\n}\n\nexport interface CampaignSpec<State, Move> {\n /** Default candidate factory \u2014 used by any act that doesn't bring its own. */\n factory?: (rng: Rng) => Puzzle<State, Move>;\n /** Ordered acts; earlier acts should sit in lower difficulty bands. */\n acts: ActSpec<State, Move>[];\n /** Base seed for the whole campaign (default 1). */\n seed?: number;\n /** Default solver budget for acts that don't override it. */\n solve?: SolveOptions;\n /** Rough authoring estimate: minutes a median player spends per level (default 1.5). */\n minutesPerLevel?: number;\n}\n\n/** A generated level tagged with the act it belongs to and its campaign index. */\nexport interface CampaignLevel<State, Move> extends GeneratedLevel<State, Move> {\n /** Zero-based act index. */\n act: number;\n /** The act's display name. */\n actName: string;\n /** Position within its act. */\n actIndex: number;\n}\n\nexport interface ActBounds {\n name: string;\n /** First campaign index (inclusive). */\n from: number;\n /** Last campaign index (inclusive). */\n to: number;\n}\n\nexport interface Campaign<State, Move> {\n levels: CampaignLevel<State, Move>[];\n acts: ActBounds[];\n /** Per-level difficulty (solver depth), campaign order \u2014 feed to `rampIssues`. */\n difficulty: number[];\n /** Reproduce the campaign: every level's sub-seed, in order. */\n seeds: number[];\n /** Honest length estimate in minutes (levels \u00D7 minutesPerLevel). */\n estMinutes: number;\n}\n\n/**\n * Compose a full campaign by generating each act inside its band and concatenating\n * them in order. Deterministic: same spec \u2192 same campaign everywhere. Acts are\n * seeded independently (base seed mixed with the act index) so re-tuning one act's\n * band or count never reshuffles the others.\n *\n * Throws (via `generateLevels`) if any act's band is too tight to fill \u2014 a loud,\n * early failure beats silently shipping a short act.\n */\nexport function composeCampaign<State, Move>(spec: CampaignSpec<State, Move>): Campaign<State, Move> {\n const baseSeed = spec.seed ?? 1;\n const minutesPerLevel = spec.minutesPerLevel ?? 1.5;\n const levels: CampaignLevel<State, Move>[] = [];\n const acts: ActBounds[] = [];\n\n spec.acts.forEach((act, a) => {\n const factory = act.factory ?? spec.factory;\n if (!factory) throw new Error(`hayao: act \"${act.name}\" has no factory and the campaign has no default`);\n // Mix the act index into the seed so acts draw from disjoint candidate streams.\n const actSeed = (baseSeed ^ ((a + 1) * 0x9e3779b9)) >>> 0;\n const generated = generateLevels(factory, {\n count: act.count,\n seed: actSeed,\n minDepth: act.minDepth,\n maxDepth: act.maxDepth,\n minNodes: act.minNodes,\n maxNodes: act.maxNodes,\n solve: act.solve ?? spec.solve,\n maxAttempts: act.maxAttempts,\n });\n const from = levels.length;\n generated.forEach((lvl, actIndex) => {\n levels.push({ ...lvl, index: levels.length, act: a, actName: act.name, actIndex });\n });\n acts.push({ name: act.name, from, to: levels.length - 1 });\n });\n\n return {\n levels,\n acts,\n difficulty: levels.map((l) => l.depth),\n seeds: levels.map((l) => l.seed),\n estMinutes: levels.length * minutesPerLevel,\n };\n}\n", "// World-graph progression \u2014 the verifiable spine of a metroidvania. A world is\n// REGIONS connected by ABILITY-GATED edges, with PICKUPS that grant abilities.\n// The insight: progression IS a Puzzle. State = (region, pickups taken); a move\n// is \"traverse a gated edge\" or \"collect a pickup here\". So the engine's BFS\n// `solve()` proves a completion order EXISTS (no circular gating), and \u2014 because\n// abilities are monotonic (never lost) \u2014 enumerating the reachable state graph\n// proves NO SOFTLOCK (no reachable state from which the goal becomes unreachable,\n// the only remaining hazard once one-way drops are in play).\n//\n// Pure data + pure functions, no engine/scene imports beyond the solver contract.\n// Deterministic: every iteration is over sorted arrays / insertion order.\n\nimport { solve, type Puzzle, type SolveResult } from '../verify/solver';\n\n/** A place in the world (a room or a named area). */\nexport interface WorldRegion {\n id: string;\n name?: string;\n biome?: string;\n}\n\n/** A traversal between two regions, gated behind abilities. Bidirectional unless `oneWay`. */\nexport interface WorldEdge {\n from: string;\n to: string;\n /** Ability ids ALL required to pass. Empty/undefined = open. */\n requires?: string[];\n /** If true, only `from \u2192 to` (a drop you can't climb back up). */\n oneWay?: boolean;\n}\n\n/** A collectible that grants an ability, located in a region. */\nexport interface WorldPickup {\n id: string;\n region: string;\n /** Ability id this pickup grants. */\n grants: string;\n}\n\n/** The whole world as pure data. */\nexport interface WorldGraphDef {\n regions: WorldRegion[];\n edges: WorldEdge[];\n pickups: WorldPickup[];\n /** Starting region id. */\n start: string;\n /** Goal region id (the \"heart\" \u2014 where a minimal completion ends). */\n goal: string;\n}\n\n// \u2500\u2500 progression as a Puzzle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A progression state: where you are + which pickups you've taken (sorted). */\nexport interface ProgressState {\n region: string;\n taken: string[];\n}\n\nexport type ProgressMove =\n | { kind: 'move'; to: string }\n | { kind: 'take'; pickup: string };\n\n/** 'complete' = reach the goal; 'full' = reach the goal with 100% pickups. */\nexport type CompletionMode = 'complete' | 'full';\n\n/** Ability ids granted by a set of taken pickup ids. */\nexport function abilitiesOf(world: WorldGraphDef, taken: readonly string[]): Set<string> {\n const byId = new Map(world.pickups.map((p) => [p.id, p.grants]));\n const out = new Set<string>();\n for (const t of taken) {\n const g = byId.get(t);\n if (g) out.add(g);\n }\n return out;\n}\n\nfunction canTraverse(edge: WorldEdge, abilities: Set<string>): boolean {\n return (edge.requires ?? []).every((a) => abilities.has(a));\n}\n\n/** Regions reachable from `region` by one edge, given the current abilities. */\nfunction stepRegions(world: WorldGraphDef, region: string, abilities: Set<string>): string[] {\n const out: string[] = [];\n for (const e of world.edges) {\n if (e.from === region && canTraverse(e, abilities)) out.push(e.to);\n else if (!e.oneWay && e.to === region && canTraverse(e, abilities)) out.push(e.from);\n }\n return out;\n}\n\n/** Build the progression Puzzle for `solve()` to prove. */\nexport function progressionPuzzle(\n world: WorldGraphDef,\n mode: CompletionMode = 'complete',\n): Puzzle<ProgressState, ProgressMove> {\n const pickupsHere = (region: string): WorldPickup[] => world.pickups.filter((p) => p.region === region);\n const totalPickups = world.pickups.length;\n\n return {\n initial: () => ({ region: world.start, taken: [] }),\n moves: (s) => {\n const abilities = abilitiesOf(world, s.taken);\n const out: ProgressMove[] = [];\n // Collect any uncollected pickup in this region first (stable order).\n for (const p of pickupsHere(s.region)) {\n if (!s.taken.includes(p.id)) out.push({ kind: 'take', pickup: p.id });\n }\n // Then traversals (deterministic: edge order \u2192 dedup).\n const seen = new Set<string>();\n for (const to of stepRegions(world, s.region, abilities)) {\n if (!seen.has(to)) {\n seen.add(to);\n out.push({ kind: 'move', to });\n }\n }\n return out;\n },\n apply: (s, m) => {\n if (m.kind === 'move') return { region: m.to, taken: s.taken };\n const taken = [...s.taken, m.pickup].sort();\n return { region: s.region, taken };\n },\n isWin: (s) =>\n s.region === world.goal && (mode === 'complete' || s.taken.length === totalPickups),\n key: (s) => `${s.region}|${s.taken.join(',')}`,\n };\n}\n\nconst SOLVE_OPTS = { maxDepth: 2000, nodeCap: 5_000_000 };\n\n/** Prove a minimal completion (reach the goal) exists. */\nexport function proveCompletable(world: WorldGraphDef): SolveResult<ProgressMove> {\n return solve(progressionPuzzle(world, 'complete'), SOLVE_OPTS);\n}\n\n/** Prove a 100% completion (all pickups + reach the goal) exists. */\nexport function proveFullCompletion(world: WorldGraphDef): SolveResult<ProgressMove> {\n return solve(progressionPuzzle(world, 'full'), SOLVE_OPTS);\n}\n\n// \u2500\u2500 reachability + softlock analysis \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Regions reachable from the start with a FIXED ability set (no collecting). */\nexport function reachableRegions(world: WorldGraphDef, abilities: Iterable<string>): string[] {\n const abil = new Set(abilities);\n const seen = new Set<string>([world.start]);\n const frontier = [world.start];\n while (frontier.length) {\n const r = frontier.shift()!;\n for (const to of stepRegions(world, r, abil)) {\n if (!seen.has(to)) {\n seen.add(to);\n frontier.push(to);\n }\n }\n }\n return [...seen];\n}\n\nexport interface SoftlockReport {\n ok: boolean;\n /** Reachable states (as keys) from which the goal can never be reached. */\n deadEnds: string[];\n /** How many progression states are reachable from the start (a size proxy). */\n statesExplored: number;\n}\n\n/**\n * Prove no softlock: enumerate every reachable progression state and confirm the\n * goal stays reachable from each. Only one-way edges can create a dead end;\n * with all-bidirectional edges a completable world is softlock-free by\n * construction, but this checks it directly regardless.\n */\nexport function findSoftlocks(world: WorldGraphDef, mode: CompletionMode = 'complete'): SoftlockReport {\n const puzzle = progressionPuzzle(world, mode);\n const start = puzzle.initial();\n const startKey = puzzle.key(start);\n\n // Forward BFS: enumerate reachable states + their successor edges.\n const states = new Map<string, ProgressState>([[startKey, start]]);\n const succ = new Map<string, string[]>();\n const winKeys = new Set<string>();\n const queue = [start];\n if (puzzle.isWin(start)) winKeys.add(startKey);\n while (queue.length) {\n const s = queue.shift()!;\n const sk = puzzle.key(s);\n const outs: string[] = [];\n for (const mv of puzzle.moves(s)) {\n const ns = puzzle.apply(s, mv);\n const nk = puzzle.key(ns);\n outs.push(nk);\n if (!states.has(nk)) {\n states.set(nk, ns);\n if (puzzle.isWin(ns)) winKeys.add(nk);\n queue.push(ns);\n }\n }\n succ.set(sk, outs);\n }\n\n // Backward reachability from winning states over the successor edges.\n const pred = new Map<string, string[]>();\n for (const [from, tos] of succ) {\n for (const to of tos) {\n (pred.get(to) ?? pred.set(to, []).get(to)!).push(from);\n }\n }\n const canWin = new Set<string>(winKeys);\n const back = [...winKeys];\n while (back.length) {\n const k = back.shift()!;\n for (const p of pred.get(k) ?? []) {\n if (!canWin.has(p)) {\n canWin.add(p);\n back.push(p);\n }\n }\n }\n\n const deadEnds = [...states.keys()].filter((k) => !canWin.has(k)).sort();\n return { ok: deadEnds.length === 0, deadEnds, statesExplored: states.size };\n}\n\n// \u2500\u2500 authoring hygiene \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Structural problems a solver can't express (dangling ids, dupes, isolation). */\nexport function validateWorld(world: WorldGraphDef): string[] {\n const issues: string[] = [];\n const ids = new Set<string>();\n for (const r of world.regions) {\n if (ids.has(r.id)) issues.push(`duplicate region id \"${r.id}\"`);\n ids.add(r.id);\n }\n const known = (id: string): boolean => ids.has(id);\n if (!known(world.start)) issues.push(`start region \"${world.start}\" is not defined`);\n if (!known(world.goal)) issues.push(`goal region \"${world.goal}\" is not defined`);\n for (const e of world.edges) {\n if (!known(e.from)) issues.push(`edge references unknown region \"${e.from}\"`);\n if (!known(e.to)) issues.push(`edge references unknown region \"${e.to}\"`);\n }\n const pids = new Set<string>();\n for (const p of world.pickups) {\n if (pids.has(p.id)) issues.push(`duplicate pickup id \"${p.id}\"`);\n pids.add(p.id);\n if (!known(p.region)) issues.push(`pickup \"${p.id}\" is in unknown region \"${p.region}\"`);\n }\n // Every region should be reachable once you hold every ability.\n const allAbilities = world.pickups.map((p) => p.grants);\n const reachable = new Set(reachableRegions(world, allAbilities));\n for (const r of world.regions) {\n if (!reachable.has(r.id)) issues.push(`region \"${r.id}\" is unreachable even with every ability`);\n }\n return issues;\n}\n", "// Multiplayer inputs without touching the sim kernel: each player's actions are\n// namespaced (`p1:left`, `p2:jump`) and merged into the single flat action set\n// that `world.step()` already takes. The whole verify harness (InputLog, replay,\n// determinism checks) works on multiplayer games unchanged \u2014 a merged frame is\n// just a frame.\n\nimport type { World } from '../world';\n\n/** A player identity: 'p1', 'p2', \u2026 (any short string without ':' works). */\nexport type PlayerId = string;\n\n/** The canonical roster for n players: ['p1', \u2026, 'pn']. */\nexport function playerIds(count: number): PlayerId[] {\n const out: PlayerId[] = [];\n for (let i = 1; i <= count; i++) out.push(`p${i}`);\n return out;\n}\n\n/** Namespace one action for a player: ('p2', 'left') \u2192 'p2:left'. */\nexport const playerAction = (player: PlayerId, action: string): string => `${player}:${action}`;\n\n/**\n * Merge per-player action sets into one flat, sorted frame for `world.step()`.\n * Deterministic: players are processed in roster order and the result is sorted,\n * so every peer computes the identical frame from the same inputs.\n */\nexport function mergePlayerFrames(players: readonly PlayerId[], inputs: ReadonlyMap<PlayerId, readonly string[]>): string[] {\n const out: string[] = [];\n for (const p of players) {\n const actions = inputs.get(p) ?? [];\n for (const a of actions) out.push(playerAction(p, a));\n }\n return out.sort();\n}\n\n/**\n * A per-player view over the world's input state. Game logic asks\n * `player.isDown('left')` and never sees the namespacing.\n */\nexport class PlayerInput {\n constructor(\n private readonly world: World,\n readonly player: PlayerId,\n ) {}\n\n isDown(action: string): boolean {\n return this.world.input.isDown(playerAction(this.player, action));\n }\n justPressed(action: string): boolean {\n return this.world.input.justPressed(playerAction(this.player, action));\n }\n justReleased(action: string): boolean {\n return this.world.input.justReleased(playerAction(this.player, action));\n }\n}\n\n/** Convenience: the input view for one player. */\nexport const playerInput = (world: World, player: PlayerId): PlayerInput => new PlayerInput(world, player);\n", "// The wire protocol. Plain JSON messages over a bus transport (every peer sees\n// every message; `to` filters when a message is for one endpoint). Two layers\n// share the bus: the room layer (hello/welcome/join/leave/start \u2014 owned by\n// RoomHost/RoomClient) and the session layer (input/hash \u2014 owned by the\n// lockstep/rollback sessions).\n\nimport type { WorldSnapshot } from '../world';\nimport type { PlayerId } from './players';\n\nexport const NET_PROTOCOL_VERSION = 1;\n\n/** Session tuning shared by every peer (the host dictates it in `welcome`). */\nexport interface NetSessionConfig {\n mode: 'lockstep' | 'rollback';\n /** Frames of input delay (lockstep) \u2014 hides transport latency. */\n inputDelay: number;\n /** Exchange a state hash every N frames to catch desyncs early. */\n hashInterval: number;\n /** Rollback: how many frames of history can be rewound. */\n maxRollback: number;\n /** How many recent frames each input message re-sends (loss tolerance). */\n redundancy: number;\n}\n\nexport const DEFAULT_SESSION_CONFIG: NetSessionConfig = {\n mode: 'lockstep',\n inputDelay: 2,\n hashInterval: 20,\n maxRollback: 12,\n redundancy: 3,\n};\n\nexport type NetMessage =\n // \u2500\u2500 room layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** A new endpoint asks to join. `uid` is its transport-unique id. */\n | { v: number; t: 'hello'; uid: string; name?: string }\n /** Host \u2192 one endpoint: your player id + everything needed to start/join. */\n | {\n v: number;\n t: 'welcome';\n to: string;\n player: PlayerId;\n players: PlayerId[];\n seed: number;\n config: NetSessionConfig;\n /** Frame the joiner starts at (0 for a fresh game). */\n startFrame: number;\n /** Mid-game join: the world state at `startFrame`. */\n snapshot?: WorldSnapshot;\n /** Other joins announced but not yet live (their bootstrap frames). */\n joins?: Array<{ player: PlayerId; atFrame: number }>;\n }\n /** Host \u2192 all: a player will exist from `atFrame` on (late join). */\n | { v: number; t: 'join'; player: PlayerId; atFrame: number }\n /** Host \u2192 all: a player's inputs end at `atFrame` (disconnect/quit). */\n | { v: number; t: 'leave'; player: PlayerId; atFrame: number }\n /** Host \u2192 all: begin simulating from frame 0 with this final roster. */\n | { v: number; t: 'start'; players: PlayerId[] }\n /** Any endpoint \u2192 host: polite disconnect. */\n | { v: number; t: 'bye'; uid: string }\n /** Host \u2192 one endpoint: join refused (room full, mode without late join\u2026). */\n | { v: number; t: 'deny'; to: string; reason: string }\n // \u2500\u2500 session layer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n /** Player inputs for frames [from, from+frames.length). Re-sends a small\n * window so a dropped message doesn't stall anyone. */\n | { v: number; t: 'input'; player: PlayerId; from: number; frames: string[][] }\n /** Structural world hash at a frame \u2014 cross-checked by every peer. */\n | { v: number; t: 'hash'; player: PlayerId; frame: number; hash: string };\n\nexport function encodeMessage(msg: NetMessage): string {\n return JSON.stringify(msg);\n}\n\n/** Decode + shallow-validate. Returns null for junk or version mismatch. */\nexport function decodeMessage(data: string): NetMessage | null {\n try {\n const msg = JSON.parse(data) as NetMessage;\n if (!msg || typeof msg !== 'object' || msg.v !== NET_PROTOCOL_VERSION || typeof msg.t !== 'string') return null;\n return msg;\n } catch {\n return null;\n }\n}\n\n/** Build a message with the protocol version stamped in. */\nexport function netMessage<T extends Omit<NetMessage, 'v'>>(msg: T): T & { v: number } {\n return { v: NET_PROTOCOL_VERSION, ...msg };\n}\n", "// Transports: how bytes move between peers. All transports are BUSES \u2014 send()\n// reaches every other peer on the same medium. That matches BroadcastChannel\n// (multi-tab), a dumb WebSocket relay (one room = one bus), and the in-memory\n// loopback hub (tests) with a single semantics, so sessions never care which\n// one they run on. Addressing, when needed, lives in the message (`to` field).\n\nexport interface Transport {\n /** Deliver to every other peer on the bus. */\n send(data: string): void;\n /** Subscribe to incoming data. Returns an unsubscribe function. */\n onMessage(cb: (data: string) => void): () => void;\n /** Fires when the transport goes away (socket close, hub shutdown). */\n onClose(cb: () => void): () => void;\n close(): void;\n readonly isOpen: boolean;\n}\n\n// \u2500\u2500 loopback: deterministic in-memory bus for tests \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface LoopbackOptions {\n /** Delivery delay in ticks (calls to hub.tick()). Default 0 = next tick. */\n delay?: number;\n /** Drop every Nth message (deterministic loss pattern). 0 = lossless. */\n dropEvery?: number;\n}\n\ninterface QueuedMessage {\n data: string;\n from: number;\n dueTick: number;\n seq: number;\n}\n\n/**\n * An in-memory bus with explicit, deterministic time: nothing is delivered\n * until `tick()` runs, messages arrive in send order, and loss follows a fixed\n * pattern. Network tests stay exactly reproducible \u2014 no timers, no races.\n */\nexport class LoopbackHub {\n private peers: LoopbackTransport[] = [];\n private queue: QueuedMessage[] = [];\n private tickCount = 0;\n private seq = 0;\n private sent = 0;\n private readonly delay: number;\n private readonly dropEvery: number;\n\n constructor(opts: LoopbackOptions = {}) {\n this.delay = opts.delay ?? 0;\n this.dropEvery = opts.dropEvery ?? 0;\n }\n\n /** Create a new endpoint on this bus. */\n connect(): LoopbackTransport {\n const t = new LoopbackTransport(this, this.peers.length);\n this.peers.push(t);\n return t;\n }\n\n /** @internal */\n enqueue(data: string, from: number): void {\n this.sent++;\n if (this.dropEvery > 0 && this.sent % this.dropEvery === 0) return;\n this.queue.push({ data, from, dueTick: this.tickCount + this.delay, seq: this.seq++ });\n }\n\n /** Advance one network tick, delivering everything that is due. */\n tick(): void {\n const due = this.queue.filter((m) => m.dueTick <= this.tickCount).sort((a, b) => a.seq - b.seq);\n this.queue = this.queue.filter((m) => m.dueTick > this.tickCount);\n this.tickCount++;\n for (const m of due) {\n for (const peer of this.peers) {\n if (peer.peerIndex !== m.from && peer.isOpen) peer.deliver(m.data);\n }\n }\n }\n\n /** Deliver everything in flight (repeated ticks until the queue drains). */\n flush(): void {\n while (this.queue.length > 0) this.tick();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n}\n\nexport class LoopbackTransport implements Transport {\n private listeners: Array<(data: string) => void> = [];\n private closeListeners: Array<() => void> = [];\n private open = true;\n\n constructor(\n private readonly hub: LoopbackHub,\n readonly peerIndex: number,\n ) {}\n\n send(data: string): void {\n if (this.open) this.hub.enqueue(data, this.peerIndex);\n }\n onMessage(cb: (data: string) => void): () => void {\n this.listeners.push(cb);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== cb);\n };\n }\n onClose(cb: () => void): () => void {\n this.closeListeners.push(cb);\n return () => {\n this.closeListeners = this.closeListeners.filter((l) => l !== cb);\n };\n }\n close(): void {\n if (!this.open) return;\n this.open = false;\n for (const cb of this.closeListeners) cb();\n }\n get isOpen(): boolean {\n return this.open;\n }\n /** @internal */\n deliver(data: string): void {\n for (const cb of this.listeners) cb(data);\n }\n}\n\n// \u2500\u2500 BroadcastChannel: zero-server multi-tab play \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A bus over the browser's BroadcastChannel \u2014 every tab on the same origin\n * that opens the same room name is a peer. Perfect for local two-tab netplay\n * and demos: no server at all.\n */\nexport class BroadcastChannelTransport implements Transport {\n private channel: BroadcastChannel;\n private listeners: Array<(data: string) => void> = [];\n private closeListeners: Array<() => void> = [];\n private open = true;\n\n constructor(room: string) {\n this.channel = new BroadcastChannel(`hayao-net:${room}`);\n this.channel.onmessage = (e: MessageEvent) => {\n if (typeof e.data === 'string') for (const cb of this.listeners) cb(e.data);\n };\n }\n\n send(data: string): void {\n if (this.open) this.channel.postMessage(data);\n }\n onMessage(cb: (data: string) => void): () => void {\n this.listeners.push(cb);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== cb);\n };\n }\n onClose(cb: () => void): () => void {\n this.closeListeners.push(cb);\n return () => {\n this.closeListeners = this.closeListeners.filter((l) => l !== cb);\n };\n }\n close(): void {\n if (!this.open) return;\n this.open = false;\n this.channel.close();\n for (const cb of this.closeListeners) cb();\n }\n get isOpen(): boolean {\n return this.open;\n }\n}\n\n// \u2500\u2500 WebSocket: real network play via the relay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * A bus over a WebSocket to the hayao relay (`npm run relay`): everyone\n * connected to the same room URL is a peer; the relay forwards each message to\n * the room's other sockets. Resolves once the socket is open.\n */\nexport function connectWebSocket(url: string): Promise<Transport> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(url);\n const listeners: Array<(data: string) => void> = [];\n const closeListeners: Array<() => void> = [];\n let open = false;\n\n const transport: Transport = {\n send(data: string) {\n if (open) ws.send(data);\n },\n onMessage(cb) {\n listeners.push(cb);\n return () => {\n const i = listeners.indexOf(cb);\n if (i >= 0) listeners.splice(i, 1);\n };\n },\n onClose(cb) {\n closeListeners.push(cb);\n return () => {\n const i = closeListeners.indexOf(cb);\n if (i >= 0) closeListeners.splice(i, 1);\n };\n },\n close() {\n open = false;\n ws.close();\n },\n get isOpen() {\n return open;\n },\n };\n\n ws.onopen = () => {\n open = true;\n resolve(transport);\n };\n ws.onmessage = (e: MessageEvent) => {\n if (typeof e.data === 'string') for (const cb of listeners) cb(e.data);\n };\n ws.onclose = () => {\n const wasOpen = open;\n open = false;\n if (wasOpen) for (const cb of closeListeners) cb();\n };\n ws.onerror = () => {\n if (!open) reject(new Error(`hayao-net: could not connect to ${url}`));\n };\n });\n}\n", "// Per-player input history. Both session kinds keep one: lockstep asks \"do I\n// have everyone's frame N?\", rollback asks \"what changed vs. my prediction?\".\n// First-write-wins per (player, frame) so duplicated or reordered redundancy\n// windows can never rewrite history.\n\nimport type { PlayerId } from './players';\n\nexport class InputBuffer {\n /** player \u2192 frame \u2192 actions (sorted). */\n private frames = new Map<PlayerId, Map<number, string[]>>();\n /** player \u2192 highest contiguous frame received (for prediction + confirm). */\n private contiguous = new Map<PlayerId, number>();\n\n addPlayer(player: PlayerId): void {\n if (!this.frames.has(player)) {\n this.frames.set(player, new Map());\n this.contiguous.set(player, -1);\n }\n }\n\n removePlayer(player: PlayerId): void {\n this.frames.delete(player);\n this.contiguous.delete(player);\n }\n\n players(): PlayerId[] {\n return [...this.frames.keys()];\n }\n\n /**\n * Record a player's actions for a frame. Returns true if this was new\n * information (first write for that slot).\n */\n set(player: PlayerId, frame: number, actions: readonly string[]): boolean {\n const perPlayer = this.frames.get(player);\n if (!perPlayer || perPlayer.has(frame)) return false;\n perPlayer.set(frame, [...actions].sort());\n // Advance the contiguous watermark as far as the new frame allows.\n let c = this.contiguous.get(player) ?? -1;\n while (perPlayer.has(c + 1)) c++;\n this.contiguous.set(player, c);\n return true;\n }\n\n has(player: PlayerId, frame: number): boolean {\n return this.frames.get(player)?.has(frame) ?? false;\n }\n\n get(player: PlayerId, frame: number): string[] | undefined {\n return this.frames.get(player)?.get(frame);\n }\n\n /** The last actions at or before `frame` \u2014 the rollback predictor's guess. */\n latestAt(player: PlayerId, frame: number): string[] {\n const perPlayer = this.frames.get(player);\n if (!perPlayer) return [];\n for (let f = frame; f >= 0; f--) {\n const a = perPlayer.get(f);\n if (a) return a;\n }\n return [];\n }\n\n /** Highest frame such that this player's inputs 0..frame are all known. */\n contiguousThrough(player: PlayerId): number {\n return this.contiguous.get(player) ?? -1;\n }\n\n /** Highest frame with ALL players' inputs known contiguously. */\n confirmedFrame(): number {\n let min = Infinity;\n for (const c of this.contiguous.values()) min = Math.min(min, c);\n return min === Infinity ? -1 : min;\n }\n\n /** Forget a player's frames at/after `frame` (leave cutoff). */\n clearFrom(player: PlayerId, frame: number): void {\n const perPlayer = this.frames.get(player);\n if (!perPlayer) return;\n for (const f of perPlayer.keys()) if (f >= frame) perPlayer.delete(f);\n let c = this.contiguous.get(player) ?? -1;\n if (c >= frame) c = frame - 1;\n this.contiguous.set(player, c);\n }\n\n /** Drop history strictly before `frame` (memory hygiene on long sessions). */\n prune(frame: number): void {\n for (const perPlayer of this.frames.values()) {\n for (const f of perPlayer.keys()) if (f < frame) perPlayer.delete(f);\n }\n }\n}\n", "// Deterministic lockstep: every peer runs the identical sim and only steps\n// frame N once it holds EVERY active player's input for N. Local input is\n// scheduled `inputDelay` frames ahead to hide transport latency. Because\n// `world.step(mergedFrame)` is already a pure transition, the network layer\n// never touches the sim \u2014 it only decides when a step may run and what the\n// merged frame contains.\n//\n// Desync safety: every `hashInterval` frames each peer broadcasts its\n// `world.hash()`; any mismatch surfaces the frame, both hashes, and the full\n// merged input log \u2014 which `replay()` can binary-search offline.\n\nimport type { World } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { InputBuffer } from './inputBuffer';\nimport { mergePlayerFrames, type PlayerId } from './players';\nimport { DEFAULT_SESSION_CONFIG, decodeMessage, encodeMessage, netMessage, type NetSessionConfig } from './protocol';\nimport type { Transport } from './transport';\n\nexport interface DesyncInfo {\n frame: number;\n player: PlayerId;\n localHash: string;\n remoteHash: string;\n /** Merged frames from this session's startFrame \u2014 replay fodder. */\n log: InputLog;\n startFrame: number;\n}\n\nexport interface LockstepOptions {\n world: World;\n transport: Transport;\n localPlayer: PlayerId;\n /** Roster at startFrame, in canonical order. */\n players: PlayerId[];\n /** Frame this session begins at (0 for a fresh game, >0 for a late joiner). */\n startFrame?: number;\n config?: Partial<NetSessionConfig>;\n onDesync?: (info: DesyncInfo) => void;\n /** Fired when a step is blocked waiting on a player's input. */\n onStall?: (player: PlayerId, frame: number) => void;\n}\n\ninterface RosterEntry {\n player: PlayerId;\n from: number;\n until: number; // exclusive; Infinity = still present\n}\n\nexport class LockstepSession {\n readonly world: World;\n readonly localPlayer: PlayerId;\n readonly config: NetSessionConfig;\n readonly startFrame: number;\n\n private readonly transport: Transport;\n private readonly buffer = new InputBuffer();\n private roster: RosterEntry[] = [];\n private mergedLog: string[][] = [];\n private localHashes = new Map<number, string>();\n private pendingRemoteHashes: Array<{ player: PlayerId; frame: number; hash: string }> = [];\n private sentThrough: number;\n private stallCount = 0;\n private desynced = false;\n private afterStepListeners: Array<(frame: number) => void> = [];\n private unsubscribe: () => void;\n private readonly onDesync?: (info: DesyncInfo) => void;\n private readonly onStall?: (player: PlayerId, frame: number) => void;\n\n constructor(opts: LockstepOptions) {\n this.world = opts.world;\n this.transport = opts.transport;\n this.localPlayer = opts.localPlayer;\n this.config = { ...DEFAULT_SESSION_CONFIG, ...opts.config, mode: 'lockstep' };\n this.startFrame = opts.startFrame ?? 0;\n this.onDesync = opts.onDesync;\n this.onStall = opts.onStall;\n\n for (const p of opts.players) {\n this.roster.push({ player: p, from: this.startFrame, until: Infinity });\n this.buffer.addPlayer(p);\n // Bootstrap: a player's first `inputDelay` frames are empty \u2014 identical\n // on every peer without a single message. At a fresh start that is\n // everyone; a late joiner seeds only ITSELF (the veterans have real\n // inputs at its startFrame, which must be used, not zeroed).\n if (this.startFrame === 0 || p === this.localPlayer) {\n for (let f = this.startFrame; f < this.startFrame + this.config.inputDelay; f++) this.buffer.set(p, f, []);\n }\n }\n this.sentThrough = this.startFrame + this.config.inputDelay - 1;\n\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n // \u2500\u2500 the roster (players can come and go at agreed frames) \u2500\u2500\u2500\u2500\n activePlayers(frame: number): PlayerId[] {\n return this.roster.filter((r) => r.from <= frame && frame < r.until).map((r) => r.player);\n }\n\n /** All peers must call this with the SAME atFrame (the room layer's job). */\n addPlayer(player: PlayerId, atFrame: number): void {\n if (this.roster.some((r) => r.player === player && r.until === Infinity)) return; // already present\n this.roster.push({ player, from: atFrame, until: Infinity });\n this.buffer.addPlayer(player);\n for (let f = atFrame; f < atFrame + this.config.inputDelay; f++) this.buffer.set(player, f, []);\n }\n\n /** All peers must call this with the SAME atFrame. */\n removePlayer(player: PlayerId, atFrame: number): void {\n const entry = this.roster.find((r) => r.player === player && r.until === Infinity);\n if (entry) entry.until = atFrame;\n // Frames at/after the cutoff must never merge, even if they arrived.\n this.buffer.clearFrom(player, atFrame);\n }\n\n // \u2500\u2500 driving the sim \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n get frame(): number {\n return this.world.frame;\n }\n\n /** Highest frame every currently-active player's input is known for. */\n get confirmedFrame(): number {\n let min = Infinity;\n for (const p of this.activePlayers(this.world.frame)) min = Math.min(min, this.buffer.contiguousThrough(p));\n return min === Infinity ? -1 : min;\n }\n\n get stalls(): number {\n return this.stallCount;\n }\n\n /**\n * Try to advance exactly one frame with the local player's current actions.\n * Returns 1 if the world stepped, 0 if blocked waiting for a remote input.\n */\n tick(localActions: readonly string[] = []): number {\n if (this.desynced) return 0;\n const f = this.world.frame;\n this.scheduleLocal(localActions);\n\n const active = this.activePlayers(f);\n for (const p of active) {\n if (!this.buffer.has(p, f)) {\n this.stallCount++;\n this.onStall?.(p, f);\n return 0;\n }\n }\n\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of active) inputs.set(p, this.buffer.get(p, f)!);\n const merged = mergePlayerFrames(active, inputs);\n this.world.step(merged);\n this.mergedLog.push(merged);\n this.afterStep(this.world.frame);\n return 1;\n }\n\n /**\n * Feed real elapsed ms (the browser loop's dt). Runs the fixed steps the\n * clock grants \u2014 stalling drops time (the sim slows rather than desyncs) \u2014\n * then catches up if we're measurably behind the other peers.\n */\n advance(realMs: number, localActions: readonly string[] = []): number {\n let stepped = 0;\n const steps = this.world.clock.advance(realMs);\n for (let i = 0; i < steps; i++) {\n if (this.tick(localActions) === 0) break;\n stepped++;\n }\n // Catch-up: if remote inputs prove peers are ahead, step extra frames now.\n let guard = 0;\n while (guard++ < 8 && this.world.frame < this.remoteFrameEstimate() && this.tick(localActions) === 1) stepped++;\n return stepped;\n }\n\n /** The merged input log from startFrame \u2014 replayable when startFrame is 0. */\n inputLog(): InputLog {\n return { frames: this.mergedLog.map((f) => f.slice()) };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n\n /** Feed a raw transport message that arrived before this session existed. */\n deliver(data: string): void {\n this.receive(data);\n }\n\n /** Subscribe to \"the world just reached frame N\" (room layer uses this). */\n onAfterStep(cb: (frame: number) => void): () => void {\n this.afterStepListeners.push(cb);\n return () => {\n this.afterStepListeners = this.afterStepListeners.filter((l) => l !== cb);\n };\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private scheduleLocal(localActions: readonly string[]): void {\n const target = this.world.frame + this.config.inputDelay;\n if (this.sentThrough >= target) return;\n while (this.sentThrough < target) {\n this.sentThrough++;\n this.buffer.set(this.localPlayer, this.sentThrough, localActions);\n }\n // Send a small window ending at the newest frame so one lost message\n // cannot stall the room.\n const from = Math.max(this.startFrame, target - this.config.redundancy + 1);\n const frames: string[][] = [];\n for (let f = from; f <= target; f++) frames.push(this.buffer.get(this.localPlayer, f) ?? []);\n this.transport.send(encodeMessage(netMessage({ t: 'input', player: this.localPlayer, from, frames })));\n }\n\n private afterStep(frame: number): void {\n if (frame % this.config.hashInterval === 0) {\n const hash = this.world.hash();\n this.localHashes.set(frame, hash);\n this.transport.send(encodeMessage(netMessage({ t: 'hash', player: this.localPlayer, frame, hash })));\n this.checkPendingHashes();\n }\n // Memory hygiene: keep a generous tail, drop ancient history.\n if (frame % 64 === 0) {\n this.buffer.prune(frame - 128);\n for (const f of this.localHashes.keys()) if (f < frame - 512) this.localHashes.delete(f);\n }\n for (const cb of this.afterStepListeners) cb(frame);\n }\n\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'input' && msg.player !== this.localPlayer) {\n for (let i = 0; i < msg.frames.length; i++) this.buffer.set(msg.player, msg.from + i, msg.frames[i]);\n } else if (msg.t === 'hash' && msg.player !== this.localPlayer) {\n this.pendingRemoteHashes.push({ player: msg.player, frame: msg.frame, hash: msg.hash });\n this.checkPendingHashes();\n }\n }\n\n private checkPendingHashes(): void {\n const still: typeof this.pendingRemoteHashes = [];\n for (const remote of this.pendingRemoteHashes) {\n const local = this.localHashes.get(remote.frame);\n if (local === undefined) {\n // We haven't reached (or have already pruned) that frame \u2014 keep it\n // unless it is ancient.\n if (remote.frame > this.world.frame - 512) still.push(remote);\n continue;\n }\n if (local !== remote.hash && !this.desynced) {\n this.desynced = true;\n this.onDesync?.({\n frame: remote.frame,\n player: remote.player,\n localHash: local,\n remoteHash: remote.hash,\n log: this.inputLog(),\n startFrame: this.startFrame,\n });\n }\n }\n this.pendingRemoteHashes = still;\n }\n\n private remoteFrameEstimate(): number {\n let max = -1;\n for (const entry of this.roster) {\n if (entry.player === this.localPlayer || entry.until !== Infinity) continue;\n // A peer schedules input `inputDelay` ahead of its sim frame.\n max = Math.max(max, this.buffer.contiguousThrough(entry.player) - this.config.inputDelay);\n }\n return max;\n }\n}\n", "// Predict-rollback netcode (GGPO/Rune-style) on top of the engine's proven\n// snapshot/restore. Every frame: send local input immediately, predict remote\n// inputs (repeat-last), step. When a real input contradicts a prediction,\n// restore the snapshot at the mispredicted frame and re-simulate to the\n// present with corrected inputs. `assertSnapshotStable` already proves\n// restore is lossless, so a rollback is exactly \"rewind + replay\".\n//\n// One engine-specific caveat: `World.restore()` rebuilds the scene tree from\n// data, and behaviors (closures) do not survive that. Games played under\n// rollback must either keep all sim logic in `world.state` + `onProcess`-free\n// nodes, or pass `attach(world)` to re-wire behaviors after every restore \u2014\n// the same hook scene code already uses for save/load.\n\nimport type { World, WorldSnapshot } from '../world';\nimport type { InputLog } from '../input/actions';\nimport { hashValue } from '../core/hash';\nimport { InputBuffer } from './inputBuffer';\nimport { mergePlayerFrames, type PlayerId } from './players';\nimport { DEFAULT_SESSION_CONFIG, decodeMessage, encodeMessage, netMessage, type NetSessionConfig } from './protocol';\nimport type { Transport } from './transport';\nimport type { DesyncInfo } from './lockstep';\n\nexport interface RollbackOptions {\n world: World;\n transport: Transport;\n localPlayer: PlayerId;\n players: PlayerId[];\n config?: Partial<NetSessionConfig>;\n /** Re-attach behaviors/controllers after every restore (save/load hook). */\n attach?: (world: World) => void;\n onDesync?: (info: DesyncInfo) => void;\n /** A correction arrived deeper than maxRollback \u2014 unrecoverable. */\n onRollbackOverflow?: (frame: number) => void;\n}\n\ninterface RingEntry {\n frame: number;\n snap: WorldSnapshot;\n}\n\nexport class RollbackSession {\n readonly world: World;\n readonly localPlayer: PlayerId;\n readonly config: NetSessionConfig;\n\n private readonly transport: Transport;\n private readonly players: PlayerId[];\n private readonly buffer = new InputBuffer();\n private readonly attach?: (world: World) => void;\n private readonly onDesync?: (info: DesyncInfo) => void;\n private readonly onRollbackOverflow?: (frame: number) => void;\n\n /** Snapshot AT frame f (state before stepping f), keyed f % ring length. */\n private ring: Array<RingEntry | null>;\n /** What we actually fed `step()` per frame \u2014 prediction bookkeeping. */\n private usedInputs = new Map<number, Map<PlayerId, string>>();\n private earliestBad = Infinity;\n private rollbackCount = 0;\n private resimulatedFrames = 0;\n private localHashes = new Map<number, string>();\n /** player \u2192 cutoff frame: their inputs are [] from there on (departed). */\n private dropped = new Map<PlayerId, number>();\n private pendingRemoteHashes: Array<{ player: PlayerId; frame: number; hash: string }> = [];\n private hashedThrough = -1;\n private desynced = false;\n private overflowed = false;\n private unsubscribe: () => void;\n\n constructor(opts: RollbackOptions) {\n this.world = opts.world;\n this.transport = opts.transport;\n this.localPlayer = opts.localPlayer;\n this.players = [...opts.players];\n this.config = { ...DEFAULT_SESSION_CONFIG, mode: 'rollback', inputDelay: 0, ...opts.config };\n this.attach = opts.attach;\n this.onDesync = opts.onDesync;\n this.onRollbackOverflow = opts.onRollbackOverflow;\n this.ring = new Array(this.config.maxRollback + 1).fill(null);\n for (const p of this.players) this.buffer.addPlayer(p);\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n get frame(): number {\n return this.world.frame;\n }\n\n /** Highest frame all players' real inputs are known for (inclusive). */\n get confirmedFrame(): number {\n let min = Infinity;\n for (const p of this.players) {\n const cut = this.dropped.get(p);\n let c = this.buffer.contiguousThrough(p);\n // A departed player's inputs are [] forever from the cutoff \u2014 known.\n if (cut !== undefined && c >= cut - 1) c = Infinity;\n min = Math.min(min, c);\n }\n return min === Infinity ? -1 : min;\n }\n\n /** Highest contiguous frame received from `player` \u2014 the drop-cutoff basis. */\n lastKnownFrame(player: PlayerId): number {\n return this.buffer.contiguousThrough(player);\n }\n\n /**\n * A player left (or vanished): their inputs are [] from `atFrame` on, so the\n * session stops waiting on them. All peers must apply the SAME atFrame (the\n * room layer broadcasts it). Frames already simulated with a non-empty\n * prediction for the departed player roll back and re-simulate as usual.\n */\n removePlayer(player: PlayerId, atFrame: number): void {\n if (player === this.localPlayer || this.dropped.has(player)) return;\n this.dropped.set(player, atFrame);\n // Inputs at/after the cutoff must never merge, even if they arrived.\n this.buffer.clearFrom(player, atFrame);\n for (let f = atFrame; f < this.world.frame; f++) {\n const used = this.usedInputs.get(f)?.get(player);\n if (used !== undefined && used !== '[]') this.earliestBad = Math.min(this.earliestBad, f);\n }\n this.settleHashes();\n }\n\n get stats(): { rollbacks: number; resimulatedFrames: number } {\n return { rollbacks: this.rollbackCount, resimulatedFrames: this.resimulatedFrames };\n }\n\n /**\n * Advance one frame: publish local input, apply any pending correction,\n * then step with confirmed-or-predicted inputs. Returns 1 unless the sim\n * has outrun its rollback window (backpressure) or is desynced.\n */\n tick(localActions: readonly string[] = []): number {\n if (this.desynced || this.overflowed) return 0;\n const f = this.world.frame;\n\n // Backpressure: never outrun the ring \u2014 a correction must always land.\n if (f - (this.confirmedFrame + 1) >= this.config.maxRollback) return 0;\n\n this.publishLocal(f, localActions);\n if (!this.resolveCorrections()) return 0;\n\n this.storeSnapshot(f);\n this.stepFrame(f);\n this.settleHashes();\n if (f % 64 === 0) this.pruneOld(f);\n return 1;\n }\n\n /** Feed real elapsed ms; runs the fixed steps the clock grants. */\n advance(realMs: number, localActions: readonly string[] = []): number {\n let stepped = 0;\n const steps = this.world.clock.advance(realMs);\n for (let i = 0; i < steps; i++) {\n if (this.tick(localActions) === 0) break;\n stepped++;\n }\n return stepped;\n }\n\n /** Merged CONFIRMED input log from frame 0 \u2014 replayable ground truth. */\n inputLog(): InputLog {\n const frames: string[][] = [];\n const through = this.confirmedFrame;\n for (let f = 0; f <= through; f++) {\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of this.players) inputs.set(p, this.buffer.get(p, f) ?? []);\n frames.push(mergePlayerFrames(this.players, inputs));\n }\n return { frames };\n }\n\n dispose(): void {\n this.unsubscribe();\n }\n\n /** Feed a raw transport message that arrived before this session existed. */\n deliver(data: string): void {\n this.receive(data);\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private publishLocal(frame: number, actions: readonly string[]): void {\n if (!this.buffer.set(this.localPlayer, frame, actions)) return;\n const from = Math.max(0, frame - this.config.redundancy + 1);\n const frames: string[][] = [];\n for (let f = from; f <= frame; f++) frames.push(this.buffer.get(this.localPlayer, f) ?? []);\n this.transport.send(encodeMessage(netMessage({ t: 'input', player: this.localPlayer, from, frames })));\n }\n\n private inputsFor(frame: number): Map<PlayerId, readonly string[]> {\n const inputs = new Map<PlayerId, readonly string[]>();\n for (const p of this.players) {\n const cut = this.dropped.get(p);\n if (cut !== undefined && frame >= cut) inputs.set(p, []);\n else inputs.set(p, this.buffer.get(p, frame) ?? this.buffer.latestAt(p, frame));\n }\n return inputs;\n }\n\n private stepFrame(frame: number): void {\n const inputs = this.inputsFor(frame);\n const used = new Map<PlayerId, string>();\n for (const p of this.players) used.set(p, JSON.stringify(inputs.get(p)));\n this.usedInputs.set(frame, used);\n this.world.step(mergePlayerFrames(this.players, inputs));\n }\n\n /** Apply pending corrections. False = overflow (fatal). */\n private resolveCorrections(): boolean {\n if (this.earliestBad === Infinity) return true;\n const target = this.world.frame;\n const bad = this.earliestBad;\n this.earliestBad = Infinity;\n\n const entry = this.ring[bad % this.ring.length];\n if (!entry || entry.frame !== bad) {\n this.overflowed = true;\n this.onRollbackOverflow?.(bad);\n return false;\n }\n\n this.rollbackCount++;\n this.world.restore(entry.snap);\n this.attach?.(this.world);\n for (let f = bad; f < target; f++) {\n this.storeSnapshot(f);\n this.stepFrame(f);\n this.resimulatedFrames++;\n }\n return true;\n }\n\n private storeSnapshot(frame: number): void {\n this.ring[frame % this.ring.length] = { frame, snap: this.world.snapshot() };\n }\n\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'input' && msg.player !== this.localPlayer) {\n const cut = this.dropped.get(msg.player);\n for (let i = 0; i < msg.frames.length; i++) {\n const frame = msg.from + i;\n if (cut !== undefined && frame >= cut) continue; // post-cutoff never merges\n if (!this.buffer.set(msg.player, frame, msg.frames[i])) continue;\n // Did we already simulate this frame with a different guess?\n if (frame < this.world.frame) {\n const used = this.usedInputs.get(frame)?.get(msg.player);\n const actual = JSON.stringify([...msg.frames[i]].sort());\n if (used !== undefined && used !== actual) this.earliestBad = Math.min(this.earliestBad, frame);\n }\n }\n this.settleHashes();\n } else if (msg.t === 'hash' && msg.player !== this.localPlayer) {\n this.pendingRemoteHashes.push({ player: msg.player, frame: msg.frame, hash: msg.hash });\n this.compareHashes();\n }\n }\n\n /**\n * Hash exchange runs on CONFIRMED frames only (predicted state is\n * provisional by design). A snapshot has exactly the shape `world.hash()`\n * hashes, so ring entries give us hashes of past frames for free.\n */\n private settleHashes(): void {\n // Frames \u2264 confirmed+? \u2014 state AT frame h is confirmed once every input\n // for frames < h is known and no correction below h is pending.\n const settled = Math.min(this.confirmedFrame + 1, this.world.frame, this.earliestBad === Infinity ? Infinity : this.earliestBad);\n const interval = this.config.hashInterval;\n let h = (Math.floor(this.hashedThrough / interval) + 1) * interval;\n for (; h <= settled; h += interval) {\n const entry = this.ring[h % this.ring.length];\n if (!entry || entry.frame !== h) continue; // already recycled \u2014 skip\n const hash = hashValue(entry.snap);\n this.localHashes.set(h, hash);\n this.hashedThrough = h;\n this.transport.send(encodeMessage(netMessage({ t: 'hash', player: this.localPlayer, frame: h, hash })));\n }\n this.compareHashes();\n }\n\n private compareHashes(): void {\n const still: typeof this.pendingRemoteHashes = [];\n for (const remote of this.pendingRemoteHashes) {\n const local = this.localHashes.get(remote.frame);\n if (local === undefined) {\n if (remote.frame > this.hashedThrough - 512) still.push(remote);\n continue;\n }\n if (local !== remote.hash && !this.desynced) {\n this.desynced = true;\n this.onDesync?.({\n frame: remote.frame,\n player: remote.player,\n localHash: local,\n remoteHash: remote.hash,\n log: this.inputLog(),\n startFrame: 0,\n });\n }\n }\n this.pendingRemoteHashes = still;\n }\n\n private pruneOld(frame: number): void {\n this.buffer.prune(frame - 128);\n for (const f of this.usedInputs.keys()) if (f < frame - 128) this.usedInputs.delete(f);\n for (const f of this.localHashes.keys()) if (f < frame - 512) this.localHashes.delete(f);\n }\n}\n", "// The room layer: who is in the game, what seed it runs, when it starts.\n// Star topology over a bus transport \u2014 one endpoint is the RoomHost (assigns\n// player ids, dictates seed + session config, orchestrates late joins and\n// leaves); everyone else is a RoomClient. Both end up owning the same thing:\n// a World plus a running net session.\n//\n// Late join (lockstep only): the host schedules the newcomer at a future\n// frame, snapshots the world exactly when it reaches that frame, and ships\n// the snapshot; every peer adds the player at the same agreed frame, so all\n// rosters stay identical. Rollback rooms reject late joins \u2014 a joiner would\n// need a *confirmed* snapshot, which is future work.\n\nimport type { World, WorldSnapshot } from '../world';\nimport type { PlayerId } from './players';\nimport {\n DEFAULT_SESSION_CONFIG,\n decodeMessage,\n encodeMessage,\n netMessage,\n type NetMessage,\n type NetSessionConfig,\n} from './protocol';\nimport type { Transport } from './transport';\nimport { LockstepSession, type DesyncInfo } from './lockstep';\nimport { RollbackSession } from './rollback';\n\n/** A live networked game, the same shape on host and client. */\nexport interface NetGame {\n world: World;\n session: LockstepSession | RollbackSession;\n localPlayer: PlayerId;\n /** Roster at the time the game handle was created. */\n players: PlayerId[];\n /** Drive this from the render loop instead of world.advance(). */\n advance(realMs: number, localActions?: readonly string[]): number;\n dispose(): void;\n}\n\nexport interface RoomCallbacks {\n onDesync?: (info: DesyncInfo) => void;\n onPlayerJoin?: (player: PlayerId, atFrame: number) => void;\n onPlayerLeave?: (player: PlayerId, atFrame: number) => void;\n}\n\nfunction makeUid(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction buildSession(\n mode: NetSessionConfig['mode'],\n world: World,\n transport: Transport,\n localPlayer: PlayerId,\n players: PlayerId[],\n startFrame: number,\n config: NetSessionConfig,\n attach: ((world: World) => void) | undefined,\n callbacks: RoomCallbacks,\n): LockstepSession | RollbackSession {\n if (mode === 'rollback') {\n return new RollbackSession({ world, transport, localPlayer, players, config, attach, onDesync: callbacks.onDesync });\n }\n return new LockstepSession({ world, transport, localPlayer, players, startFrame, config, onDesync: callbacks.onDesync });\n}\n\nfunction makeGame(\n world: World,\n session: LockstepSession | RollbackSession,\n localPlayer: PlayerId,\n players: PlayerId[],\n extraDispose?: () => void,\n): NetGame {\n return {\n world,\n session,\n localPlayer,\n players,\n advance: (realMs, localActions = []) => session.advance(realMs, localActions),\n dispose: () => {\n session.dispose();\n extraDispose?.();\n },\n };\n}\n\n// \u2500\u2500 host \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RoomHostOptions extends RoomCallbacks {\n transport: Transport;\n /** Build the deterministic world every peer will run. */\n makeWorld: (seed: number) => World;\n seed?: number;\n config?: Partial<NetSessionConfig>;\n maxPlayers?: number;\n /** Frames between \"a joiner exists\" and their first live frame. */\n joinMargin?: number;\n /** Re-attach behaviors after restore (rollback / late-join snapshot). */\n attach?: (world: World) => void;\n}\n\nexport class RoomHost {\n readonly localPlayer: PlayerId = 'p1';\n readonly seed: number;\n readonly config: NetSessionConfig;\n\n private readonly transport: Transport;\n private readonly makeWorld: (seed: number) => World;\n private readonly maxPlayers: number;\n private readonly joinMargin: number;\n private readonly attach?: (world: World) => void;\n private readonly callbacks: RoomCallbacks;\n\n private players: PlayerId[] = ['p1'];\n private uidToPlayer = new Map<string, PlayerId>();\n private nextPlayerIndex = 2;\n private started = false;\n private game: NetGame | null = null;\n private pendingSnapshots: Array<{ uid: string; player: PlayerId; atFrame: number }> = [];\n private unsubscribe: () => void;\n\n constructor(opts: RoomHostOptions) {\n this.transport = opts.transport;\n this.makeWorld = opts.makeWorld;\n this.seed = opts.seed ?? 1;\n this.config = { ...DEFAULT_SESSION_CONFIG, ...opts.config };\n this.maxPlayers = opts.maxPlayers ?? 4;\n this.joinMargin = opts.joinMargin ?? 30;\n this.attach = opts.attach;\n this.callbacks = opts;\n this.unsubscribe = this.transport.onMessage((data) => this.receive(data));\n }\n\n /** Players currently in the room (host first). */\n get roster(): PlayerId[] {\n return [...this.players];\n }\n\n get isStarted(): boolean {\n return this.started;\n }\n\n /** Freeze the roster's frame 0 and begin simulating. */\n start(): NetGame {\n if (this.game) return this.game;\n this.started = true;\n const world = this.makeWorld(this.seed);\n const session = buildSession(\n this.config.mode,\n world,\n this.transport,\n this.localPlayer,\n this.players,\n 0,\n this.config,\n this.attach,\n this.callbacks,\n );\n if (session instanceof LockstepSession) {\n session.onAfterStep((frame) => this.serviceSnapshots(frame, world));\n }\n this.transport.send(encodeMessage(netMessage({ t: 'start', players: [...this.players] })));\n this.game = makeGame(world, session, this.localPlayer, this.players, () => this.unsubscribe());\n return this.game;\n }\n\n /** Announce a player's departure (disconnect handling is the app's call). */\n dropPlayer(player: PlayerId): void {\n const session = this.game?.session;\n if (!session) return;\n // Cut at the first frame nobody can have merged yet: one past the last\n // contiguous input everyone received from the departed player. Peers on a\n // reliable bus share the same received set, so the cutoff is consistent.\n // Rollback peers may already have PREDICTED past the cutoff \u2014 that's an\n // ordinary misprediction; removePlayer rolls back and re-simulates.\n const atFrame =\n session instanceof LockstepSession\n ? Math.max(session.frame, session.confirmedFrame + 1)\n : session.lastKnownFrame(player) + 1;\n this.transport.send(encodeMessage(netMessage({ t: 'leave', player, atFrame })));\n session.removePlayer(player, atFrame);\n this.players = this.players.filter((p) => p !== player);\n this.callbacks.onPlayerLeave?.(player, atFrame);\n }\n\n dispose(): void {\n this.unsubscribe();\n this.game?.dispose();\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n private receive(data: string): void {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'hello') this.handleHello(msg);\n else if (msg.t === 'bye') {\n const player = this.uidToPlayer.get(msg.uid);\n if (player && this.started) this.dropPlayer(player);\n else if (player) {\n this.players = this.players.filter((p) => p !== player);\n this.uidToPlayer.delete(msg.uid);\n }\n }\n }\n\n private handleHello(msg: Extract<NetMessage, { t: 'hello' }>): void {\n if (this.uidToPlayer.has(msg.uid)) return; // duplicate hello \u2014 already welcomed\n if (this.players.length >= this.maxPlayers) {\n this.transport.send(encodeMessage(netMessage({ t: 'deny', to: msg.uid, reason: 'room full' })));\n return;\n }\n if (this.started && this.config.mode === 'rollback') {\n this.transport.send(encodeMessage(netMessage({ t: 'deny', to: msg.uid, reason: 'rollback rooms cannot be joined mid-game' })));\n return;\n }\n\n const player: PlayerId = `p${this.nextPlayerIndex++}`;\n this.uidToPlayer.set(msg.uid, player);\n this.players.push(player);\n\n if (!this.started) {\n this.transport.send(\n encodeMessage(\n netMessage({\n t: 'welcome',\n to: msg.uid,\n player,\n players: [...this.players],\n seed: this.seed,\n config: this.config,\n startFrame: 0,\n }),\n ),\n );\n this.callbacks.onPlayerJoin?.(player, 0);\n return;\n }\n\n // Late join: everyone (including us) adds the player at a future frame;\n // the snapshot ships when the host's world actually reaches it.\n const session = this.game!.session as LockstepSession;\n const atFrame = session.frame + this.joinMargin;\n this.transport.send(encodeMessage(netMessage({ t: 'join', player, atFrame })));\n session.addPlayer(player, atFrame);\n this.pendingSnapshots.push({ uid: msg.uid, player, atFrame });\n this.callbacks.onPlayerJoin?.(player, atFrame);\n }\n\n private serviceSnapshots(frame: number, world: World): void {\n if (this.pendingSnapshots.length === 0) return;\n const due = this.pendingSnapshots.filter((p) => p.atFrame === frame);\n if (due.length === 0) return;\n this.pendingSnapshots = this.pendingSnapshots.filter((p) => p.atFrame !== frame);\n const snapshot: WorldSnapshot = world.snapshot();\n for (const join of due) {\n // Joiners scheduled but not yet live go in `joins`, not the roster \u2014\n // the newcomer must add them at THEIR frame, not its own startFrame.\n const stillPending = this.pendingSnapshots.filter((p) => p.player !== join.player);\n const pendingIds = new Set(stillPending.map((p) => p.player));\n this.transport.send(\n encodeMessage(\n netMessage({\n t: 'welcome',\n to: join.uid,\n player: join.player,\n players: this.players.filter((p) => !pendingIds.has(p)),\n seed: this.seed,\n config: this.config,\n startFrame: frame,\n snapshot,\n joins: stillPending.map((p) => ({ player: p.player, atFrame: p.atFrame })),\n }),\n ),\n );\n }\n }\n}\n\n// \u2500\u2500 client \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RoomClientOptions extends RoomCallbacks {\n transport: Transport;\n makeWorld: (seed: number) => World;\n attach?: (world: World) => void;\n name?: string;\n}\n\n/**\n * Join a room: send hello, wait for welcome (+start or snapshot), come back\n * with a NetGame. Session-layer messages that arrive while the snapshot is in\n * flight are buffered and replayed so no input is ever missed.\n */\nexport function joinRoom(opts: RoomClientOptions): Promise<NetGame> {\n const uid = makeUid();\n const transport = opts.transport;\n\n return new Promise((resolve, reject) => {\n let welcome: Extract<NetMessage, { t: 'welcome' }> | null = null;\n let started = false;\n /** Final frame-0 roster from `start` (a lobby can grow after our welcome). */\n let startRoster: PlayerId[] | null = null;\n const buffered: string[] = [];\n const pendingRoster: Array<Extract<NetMessage, { t: 'join' } | { t: 'leave' }>> = [];\n\n const finish = () => {\n if (!welcome || !started) return;\n unsub();\n const roster = startRoster ?? welcome.players;\n const world = opts.makeWorld(welcome.seed);\n if (welcome.snapshot) {\n world.restore(welcome.snapshot);\n opts.attach?.(world);\n }\n const session = buildSession(\n welcome.config.mode,\n world,\n transport,\n welcome.player,\n roster,\n welcome.startFrame,\n welcome.config,\n opts.attach,\n opts,\n );\n // Joins the host announced before our welcome (still-pending joiners):\n if (welcome.joins && session instanceof LockstepSession) {\n for (const j of welcome.joins) session.addPlayer(j.player, j.atFrame);\n }\n // Roster changes and inputs that raced past us while restoring:\n for (const m of pendingRoster) {\n if (m.t === 'join' && session instanceof LockstepSession) session.addPlayer(m.player, m.atFrame);\n if (m.t === 'leave') session.removePlayer(m.player, m.atFrame);\n }\n const roomUnsub = transport.onMessage((data) => {\n const msg = decodeMessage(data);\n if (!msg) return;\n if (msg.t === 'join' && session instanceof LockstepSession) {\n session.addPlayer(msg.player, msg.atFrame);\n opts.onPlayerJoin?.(msg.player, msg.atFrame);\n } else if (msg.t === 'leave') {\n session.removePlayer(msg.player, msg.atFrame);\n opts.onPlayerLeave?.(msg.player, msg.atFrame);\n }\n });\n const game = makeGame(world, session, welcome.player, roster, () => {\n roomUnsub();\n transport.send(encodeMessage(netMessage({ t: 'bye', uid })));\n });\n // Replay whatever the session missed while the snapshot was in flight.\n for (const data of buffered) session.deliver(data);\n resolve(game);\n };\n\n const unsub = transport.onMessage((data) => {\n const msg = decodeMessage(data);\n if (!msg) return;\n switch (msg.t) {\n case 'welcome':\n if (msg.to === uid) {\n welcome = msg;\n // A snapshot welcome means the game is already running.\n if (msg.snapshot || msg.startFrame > 0) started = true;\n finish();\n }\n break;\n case 'deny':\n if (msg.to === uid) {\n unsub();\n reject(new Error(`hayao-net: join denied \u2014 ${msg.reason}`));\n }\n break;\n case 'start':\n started = true;\n startRoster = msg.players;\n finish();\n break;\n case 'join':\n case 'leave':\n pendingRoster.push(msg);\n break;\n case 'input':\n case 'hash':\n buffered.push(data);\n break;\n }\n });\n\n transport.send(encodeMessage(netMessage({ t: 'hello', uid, name: opts.name })));\n });\n}\n\n/** Create a room host over a transport. Call `start()` when the lobby is set. */\nexport function hostRoom(opts: RoomHostOptions): RoomHost {\n return new RoomHost(opts);\n}\n", "// Browser driver for networked games \u2014 the net twin of runBrowser(). Same\n// mount/renderer/input wiring, but the world is created only after the room\n// handshake settles the seed and roster, and the RAF loop drives\n// `session.advance()` (which gates steps on network input) instead of\n// `world.advance()`.\n\nimport type { GameDefinition } from '../app/game';\nimport { createWorld } from '../app/game';\nimport { KeyboardSource } from '../input/source';\nimport { SvgRenderer } from '../render/svg';\nimport { Canvas2DRenderer } from '../render/canvas';\nimport type { Renderer } from '../render/renderer';\nimport { setOverlayHost } from '../ui/overlay';\nimport type { World } from '../world';\nimport type { Transport } from './transport';\nimport type { NetSessionConfig } from './protocol';\nimport type { NetGame, RoomCallbacks } from './room';\nimport { hostRoom, joinRoom, type RoomHost } from './room';\nimport type { PlayerId } from './players';\n\nexport interface NetRunOptions extends RoomCallbacks {\n transport: Transport;\n /** 'host' owns the lobby (first tab); 'join' connects to it. */\n role: 'host' | 'join';\n seed?: number;\n config?: Partial<NetSessionConfig>;\n maxPlayers?: number;\n /** Re-attach behaviors after any restore (rollback / late join). */\n attach?: (world: World) => void;\n renderer?: 'svg' | 'canvas';\n /** Lobby feedback (\"waiting for players\u2026\", \"connected as p2\"). */\n onStatus?: (status: string) => void;\n}\n\nexport interface NetGameHandle {\n /** Host only: freeze the lobby and start the game. No-op for joiners. */\n start(): void;\n /** The live game once running (null while in the lobby). */\n readonly game: NetGame | null;\n readonly localPlayer: PlayerId | null;\n readonly roster: PlayerId[];\n input: KeyboardSource;\n stop(): void;\n}\n\n/**\n * Run a game as a networked session. Host flow: call, wait for peers\n * (onPlayerJoin fires), then `handle.start()`. Join flow: call \u2014 the render\n * loop begins automatically when the host starts (or immediately mid-game\n * via snapshot late join).\n */\nexport function runBrowserNet(def: GameDefinition, mount: HTMLElement, opts: NetRunOptions): NetGameHandle {\n const width = def.width ?? 1280;\n const height = def.height ?? 720;\n const background = def.background ?? '#f3ecdb';\n\n const renderer: Renderer =\n opts.renderer === 'canvas'\n ? new Canvas2DRenderer({ width, height, background })\n : new SvgRenderer({ width, height, background });\n mount.style.position = mount.style.position || 'relative';\n renderer.mount?.(mount);\n setOverlayHost(mount);\n\n const input = new KeyboardSource(def.inputMap ?? {}, document);\n const makeWorld = (seed: number) => createWorld(def, seed);\n\n let game: NetGame | null = null;\n let host: RoomHost | null = null;\n let raf = 0;\n let stopped = false;\n\n const loop = (last: number) => (now: number) => {\n if (!stopped && game) {\n const stepped = game.advance(now - last, input.currentActions());\n if (stepped > 0) input.clearPressed();\n renderer.draw(game.world.render());\n }\n raf = requestAnimationFrame(loop(now));\n };\n\n const begin = (g: NetGame) => {\n game = g;\n opts.onStatus?.(`playing as ${g.localPlayer} (${g.players.length} players)`);\n raf = requestAnimationFrame(loop(performance.now()));\n };\n\n if (opts.role === 'host') {\n host = hostRoom({\n transport: opts.transport,\n makeWorld,\n seed: opts.seed ?? def.seed ?? 1,\n config: opts.config,\n maxPlayers: opts.maxPlayers,\n attach: opts.attach,\n onDesync: opts.onDesync,\n onPlayerJoin: (p, f) => {\n opts.onStatus?.(`${p} joined`);\n opts.onPlayerJoin?.(p, f);\n },\n onPlayerLeave: opts.onPlayerLeave,\n });\n opts.onStatus?.('hosting \u2014 waiting for players');\n } else {\n opts.onStatus?.('joining\u2026');\n joinRoom({\n transport: opts.transport,\n makeWorld,\n attach: opts.attach,\n onDesync: opts.onDesync,\n onPlayerJoin: opts.onPlayerJoin,\n onPlayerLeave: opts.onPlayerLeave,\n })\n .then(begin)\n .catch((err: Error) => opts.onStatus?.(err.message));\n }\n\n return {\n start() {\n if (host && !game) begin(host.start());\n },\n get game() {\n return game;\n },\n get localPlayer() {\n return game?.localPlayer ?? (opts.role === 'host' ? 'p1' : null);\n },\n get roster() {\n return host?.roster ?? game?.players ?? [];\n },\n input,\n stop() {\n stopped = true;\n cancelAnimationFrame(raf);\n game?.dispose();\n host?.dispose();\n input.dispose();\n renderer.dispose?.();\n },\n };\n}\n", "// SessionRecorder: accumulates a PlaytestSession during live play. DOM-free so\n// tests can drive it directly; runStudio (run.ts) wires it to the browser\n// driver's onAdvance hook, the shell/overlay observers, and the wall clock.\n\nimport type {\n Annotation,\n EndReason,\n KnobEvent,\n PlaytestSession,\n ScreenEvent,\n VariantRef,\n WallClockMark,\n} from './session';\nimport type { TuningValues } from '../app/tuning';\nimport type { WorldSnapshot } from '../world';\n\nexport interface RecorderInit {\n game: string;\n seed: number;\n tuningValues: TuningValues;\n variant?: VariantRef;\n buildRef?: string;\n startedAt?: string;\n id?: string;\n /** Segment sessions (post hot-swap) replay from this snapshot. */\n startSnapshot?: WorldSnapshot;\n}\n\nlet counter = 0;\n/** Collision-safe within a page; slugified so the id is filesystem/URL-safe. */\nfunction sessionId(game: string, startedAt: string): string {\n const slug = game.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'game';\n return `${slug}-${startedAt.replace(/[:.]/g, '-').toLowerCase()}-${(counter++).toString(36)}`;\n}\n\nexport class SessionRecorder {\n private frames: string[][] = [];\n private axesLog: Array<[number, string, number]> = [];\n private lastAxes = new Map<string, number>();\n private knobEvents: KnobEvent[] = [];\n private screenEvents: ScreenEvent[] = [];\n private wallClockMarks: WallClockMark[] = [];\n private annotations: Annotation[] = [];\n private readonly init: RecorderInit;\n private readonly startedAt: string;\n readonly id: string;\n /** Set once the dev server reports the git sha (fetched async by runStudio). */\n buildRef: string;\n\n constructor(init: RecorderInit) {\n this.init = init;\n this.startedAt = init.startedAt ?? new Date().toISOString();\n this.id = init.id ?? sessionId(init.game, this.startedAt);\n this.buildRef = init.buildRef ?? 'unknown';\n }\n\n /** Frames recorded so far \u2014 event hooks stamp themselves with this. */\n get frame(): number {\n return this.frames.length;\n }\n\n /** Live view of the recorded input frames (the scrub timeline re-steps these). */\n get liveInputFrames(): readonly string[][] {\n return this.frames;\n }\n\n /** Live view of the delta-encoded axes log. */\n get liveAxesLog(): ReadonlyArray<readonly [number, string, number]> {\n return this.axesLog;\n }\n\n /** Live view of mid-play knob changes (scrubbing reapplies them exactly). */\n get liveKnobEvents(): readonly KnobEvent[] {\n return this.knobEvents;\n }\n\n /**\n * Record one sim step: the action set it saw and (optionally) the analog\n * axes. Axes are delta-encoded \u2014 an entry lands only when a value changed.\n */\n step(actions: readonly string[], axes?: ReadonlyMap<string, number>): void {\n if (axes) {\n for (const [name, value] of axes) {\n if (this.lastAxes.get(name) !== value) {\n this.axesLog.push([this.frames.length, name, value]);\n this.lastAxes.set(name, value);\n }\n }\n }\n this.frames.push([...actions].sort());\n }\n\n knob(key: string, value: number | string): void {\n this.knobEvents.push({ frame: this.frames.length, key, value });\n this.screen('knob', `${key}=${value}`);\n }\n\n screen(kind: ScreenEvent['kind'], detail?: string): void {\n this.screenEvents.push({ frame: this.frames.length, kind, ...(detail !== undefined ? { detail } : {}) });\n }\n\n mark(kind: WallClockMark['kind'], t: number): void {\n this.wallClockMarks.push({ frame: this.frames.length, t, kind });\n }\n\n annotate(tag: string, note?: string): void {\n this.annotations.push({ frame: this.frames.length, tag, ...(note !== undefined ? { note } : {}) });\n }\n\n /**\n * A rewind-and-resume forked the timeline: everything after `frame` never\n * happened in the final run. Drop those frames plus the events stamped in\n * them, so the artifact stays exactly replayable as what the player kept.\n */\n truncate(frame: number): void {\n if (frame >= this.frames.length) return;\n this.frames.length = frame;\n this.axesLog = this.axesLog.filter(([f]) => f < frame);\n this.lastAxes.clear();\n for (const [f, name, value] of this.axesLog) if (f < frame) this.lastAxes.set(name, value);\n this.knobEvents = this.knobEvents.filter((e) => e.frame <= frame);\n this.screenEvents = this.screenEvents.filter((e) => e.frame <= frame);\n this.wallClockMarks = this.wallClockMarks.filter((m) => m.frame <= frame);\n this.annotations = this.annotations.filter((a) => a.frame <= frame);\n }\n\n /** Finalize into the artifact. The recorder can keep recording afterwards (autosave). */\n toSession(endReason: EndReason): PlaytestSession {\n return {\n id: this.id,\n game: this.init.game,\n startedAt: this.startedAt,\n buildRef: this.buildRef,\n seed: this.init.seed,\n variant: this.init.variant ?? { name: 'dev', kind: 'dev' },\n tuningValues: { ...this.init.tuningValues },\n ...(this.init.startSnapshot ? { startSnapshot: this.init.startSnapshot } : {}),\n knobEvents: this.knobEvents.slice(),\n inputLog: { frames: this.frames.map((f) => f.slice()) },\n axesLog: this.axesLog.slice(),\n screenEvents: this.screenEvents.slice(),\n wallClockMarks: this.wallClockMarks.slice(),\n annotations: this.annotations.slice(),\n endReason,\n };\n }\n}\n", "// The scrub timeline: a ring of periodic world snapshots + the session's own\n// input log = exact time travel. Scrubbing restores the nearest snapshot at or\n// before the target frame and re-steps the RECORDED inputs to it \u2014 determinism\n// makes the result identical to having stopped there live. Pure module (no\n// DOM): runStudio drives it in the browser, tests drive it headlessly.\n\nimport type { GameDefinition } from '../app/game';\nimport type { World, WorldSnapshot } from '../world';\nimport type { KnobEvent } from './session';\n\nexport interface TimelineEntry {\n frame: number;\n snap: WorldSnapshot;\n}\n\n/**\n * Periodic snapshot keeper. Every `stride` frames costs one snapshot; `cap`\n * bounds memory (oldest evicted), so scrub range \u2248 stride \u00D7 cap frames back.\n */\nexport class SnapshotRing {\n private entries: TimelineEntry[] = [];\n constructor(\n readonly stride = 30,\n readonly cap = 240,\n ) {}\n\n /** Call after every recorded step; keeps frame 0 and every stride-th frame. */\n push(frame: number, world: World): void {\n if (frame % this.stride !== 0) return;\n this.entries.push({ frame, snap: world.snapshot() });\n if (this.entries.length > this.cap) this.entries.shift();\n }\n\n /** Nearest entry at or before `frame` (null if it fell off the ring). */\n nearest(frame: number): TimelineEntry | null {\n let best: TimelineEntry | null = null;\n for (const e of this.entries) {\n if (e.frame <= frame && (!best || e.frame > best.frame)) best = e;\n }\n return best;\n }\n\n /** Oldest reachable frame (scrubbing earlier than this is off the ring). */\n get minFrame(): number {\n return this.entries.length > 0 ? this.entries[0].frame : 0;\n }\n\n /** Drop entries after `frame` \u2014 a rewind-and-resume forked the timeline. */\n truncate(frame: number): void {\n this.entries = this.entries.filter((e) => e.frame <= frame);\n }\n\n clear(): void {\n this.entries = [];\n }\n}\n\n/**\n * Scrub a live world to `target`: restore the nearest ring snapshot, then\n * re-step the recorded inputs. `inputFrames[i]` is the input DURING step i, so\n * stepping frames[entry..target-1] lands the world exactly AT `target`.\n * Returns the frame actually reached (clamped to the ring's reachable range),\n * or null if the ring is empty. `def.attach` runs after the restore \u2014 the same\n * contract as every other restore path.\n */\nexport function scrubTo(\n world: World,\n def: GameDefinition,\n ring: SnapshotRing,\n inputFrames: readonly string[][],\n axesLog: ReadonlyArray<readonly [number, string, number]>,\n knobEvents: readonly KnobEvent[],\n target: number,\n): number | null {\n const clamped = Math.max(ring.minFrame, Math.min(target, inputFrames.length));\n const entry = ring.nearest(clamped);\n if (!entry) return null;\n world.restore(structuredClone(entry.snap));\n def.attach?.(world);\n // Axes are inputs, not snapshotted state: CLEAR the live world's stale\n // values (replaySession starts fresh; a scrub reuses the world), then\n // rebuild them at the snapshot frame and feed deltas as we re-step.\n world.input.axes.clear();\n const axesNow = new Map<string, number>();\n let axisIdx = 0;\n while (axisIdx < axesLog.length && axesLog[axisIdx][0] < entry.frame) {\n const [, name, value] = axesLog[axisIdx++];\n axesNow.set(name, value);\n }\n for (const [name, value] of axesNow) world.input.axes.set(name, value);\n let knobIdx = knobEvents.findIndex((k) => k.frame >= entry.frame);\n if (knobIdx < 0) knobIdx = knobEvents.length;\n for (let i = entry.frame; i < clamped; i++) {\n // Mid-play knob changes replay at their exact frame (same as replaySession).\n while (knobIdx < knobEvents.length && knobEvents[knobIdx].frame === i) {\n const k = knobEvents[knobIdx++];\n const snap = world.snapshot();\n snap.tuning = { ...snap.tuning, [k.key]: k.value };\n world.restore(snap);\n def.attach?.(world);\n }\n while (axisIdx < axesLog.length && axesLog[axisIdx][0] === i) {\n const [, name, value] = axesLog[axisIdx++];\n world.input.axes.set(name, value);\n }\n world.step(inputFrames[i]);\n }\n return clamped;\n}\n", "// runStudio: the Studio-instrumented browser driver. Wraps runBrowser (which\n// stays lean for shipped games) with: URL overrides (?seed=, ?tuning=), the\n// session recorder riding the onAdvance hook, shell/overlay/wall-clock\n// observers, autosave + pagehide flush to the dev server, and a window.__studio\n// API the Studio shell page drives across the iframe boundary.\n\nimport { runBrowser, type GameHandle, type RunOptions } from '../app/browser';\nimport { resolveTuning, type TuningSpec, type TuningValues, type Variant } from '../app/tuning';\nimport { createWorld, type GameDefinition } from '../app/game';\nimport { setScreenObserver } from '../ui/overlay';\nimport { SessionRecorder } from './record';\nimport { SnapshotRing, scrubTo } from './timeline';\nimport type { EndReason, PlaytestSession, VariantRef } from './session';\n\n/** The slice of Vite's import.meta.hot the carryover needs (structural, no vite type dep). */\nexport interface HotContext {\n data: Record<string, unknown>;\n dispose(cb: (data: Record<string, unknown>) => void): void;\n}\n\nexport interface StudioOptions extends RunOptions {\n /**\n * Named A/B variants of this game. `?variant=<name>` picks one: its `patch`\n * rewrites the definition, its `tuning` seeds the knob values (explicit\n * `?tuning=`/opts overrides still win). Sessions are stamped with the name.\n */\n variants?: Record<string, Variant>;\n /** Variant identity override (worktree builds stamp commit info here). */\n variant?: VariantRef;\n /**\n * Pass `import.meta.hot` (only the game's own entry module has it) to carry\n * the live world ACROSS code hot-swaps: snapshot on dispose, restore into\n * the re-executed module. The old session flushes as 'hot-swap'; the new\n * segment records the restored snapshot so it stays fully replayable.\n *\n * The entry MUST also contain the literal line `import.meta.hot?.accept();`\n * \u2014 Vite decides HMR boundaries by statically scanning module source, so an\n * accept() call inside this library cannot mark your entry self-accepting.\n */\n hot?: HotContext;\n}\n\nexport interface StudioHandle extends GameHandle {\n /** Live-change a tuning knob: rebuild-with-carryover, recorded as a knob event. */\n setKnob(key: string, value: number | string): void;\n /** Current resolved tuning values. */\n knobValues(): TuningValues;\n /** The game's declared knob spec (the Studio panel builds its controls from this). */\n tuningSpec(): TuningSpec | undefined;\n /** Declared A/B variants: name \u2192 label. */\n variants(): Record<string, string>;\n /** The variant this run is playing (name + kind, worktrees include commit). */\n activeVariant(): VariantRef;\n /** The game title (the Studio page labels panes with it). */\n title(): string;\n /** Drop a human annotation at the current frame (\"felt bad here\"). */\n annotate(tag: string, note?: string): void;\n /** Freeze/unfreeze the sim (rendering continues; no pause overlay). */\n setFrozen(frozen: boolean): void;\n frozen(): boolean;\n /**\n * Time-travel to a recorded frame (freezes first). Exact: restores the\n * nearest ring snapshot and re-steps the recorded inputs. Returns the frame\n * reached, or null if it's off the ring. Resuming after a rewind FORKS the\n * timeline: the discarded future is truncated from the session.\n */\n scrub(frame: number): number | null;\n /** Scrub bounds + position: min reachable frame, current, recorded max. */\n timeline(): { min: number; frame: number; max: number };\n /**\n * 'live' = playing + recording; 'replay' = watching a past session loaded\n * via ?session=<id> (read-only: scrub/playback over the whole recording,\n * knobs and annotation disabled, nothing records).\n */\n mode(): 'live' | 'replay';\n /** Flush the session artifact to the dev server now. */\n flush(reason?: EndReason): void;\n /** The in-progress session (for inspection/tests). */\n session(): PlaytestSession;\n}\n\ndeclare global {\n interface Window {\n __studio?: StudioHandle;\n }\n}\n\n/** Parse ?seed= and ?tuning= (base64 JSON) \u2014 silently ignore malformed input. */\nfunction urlOverrides(): { seed?: number; tuning?: TuningValues } {\n if (typeof location === 'undefined') return {};\n const params = new URLSearchParams(location.search);\n const out: { seed?: number; tuning?: TuningValues } = {};\n const seed = params.get('seed');\n if (seed !== null && Number.isFinite(Number(seed))) out.seed = Number(seed);\n const tuning = params.get('tuning');\n if (tuning) {\n try {\n const parsed = JSON.parse(atob(tuning)) as TuningValues;\n if (parsed && typeof parsed === 'object') out.tuning = parsed;\n } catch {\n /* malformed ?tuning= is a no-op, not a crash */\n }\n }\n return out;\n}\n\nexport function runStudio(baseDef: GameDefinition, mount: HTMLElement, opts: StudioOptions = {}): StudioHandle {\n const url = urlOverrides();\n\n // Variant resolution: ?variant= picks a named alternative; its patch rewrites\n // the def, its tuning seeds the overrides (explicit URL/opts tuning wins).\n const variantName = typeof location !== 'undefined' ? new URLSearchParams(location.search).get('variant') : null;\n const variantDef = variantName ? opts.variants?.[variantName] : undefined;\n const def = variantDef?.patch ? variantDef.patch(baseDef) : baseDef;\n const variantRef: VariantRef = opts.variant ?? (variantDef && variantName ? { name: variantName, kind: 'module' } : { name: 'dev', kind: 'dev' });\n\n const seed = opts.world?.seed ?? url.seed ?? def.seed ?? 1;\n const overrides = { ...variantDef?.tuning, ...url.tuning, ...opts.world?.tuning };\n const tuningValues = resolveTuning(def.tuning, overrides);\n const values: TuningValues = { ...tuningValues };\n const start = typeof performance !== 'undefined' ? performance.now() : 0;\n\n let recorder = new SessionRecorder({\n game: def.title,\n seed,\n tuningValues,\n variant: variantRef,\n });\n let flushed = false;\n\n const post = (session: PlaytestSession, beacon: boolean) => {\n const body = JSON.stringify(session);\n if (beacon && typeof navigator !== 'undefined' && navigator.sendBeacon) {\n navigator.sendBeacon('/__studio/session', new Blob([body], { type: 'application/json' }));\n return;\n }\n void fetch('/__studio/session', { method: 'POST', headers: { 'content-type': 'application/json' }, body }).catch(() => {\n /* dev server gone \u2014 the session still lives in memory */\n });\n };\n const flush = (reason: EndReason = 'quit', beacon = false) => {\n if (replay) return; // replay mode records nothing \u2014 the artifact already exists\n if (recorder.frame === 0 && flushed) return; // nothing new since the last write\n post(recorder.toSession(reason), beacon);\n flushed = true;\n };\n\n // \u2500\u2500 replay mode (\"watch the tape\"): ?session=<id> loads a past artifact \u2500\u2500\u2500\u2500\u2500\n const replayId = typeof location !== 'undefined' ? new URLSearchParams(location.search).get('session') : null;\n let replay: { session: PlaytestSession; pos: number } | null = null;\n let playbackTimer: number | null = null;\n\n // \u2500\u2500 scrub timeline: periodic snapshots + the recorder's own log \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // (`let`: replay mode swaps in a ring whose stride covers the whole tape.)\n let ring = new SnapshotRing();\n let isFrozen = false;\n let scrubbedTo: number | null = null; // set while paused earlier than the recorded tip\n\n /**\n * Commit a rewound position as the new present: the discarded future never\n * happened \u2014 truncate it from the recorder and the ring so the session\n * artifact stays exactly what the player kept.\n */\n const forkIfRewound = () => {\n if (scrubbedTo === null || scrubbedTo >= recorder.frame) {\n scrubbedTo = null;\n return;\n }\n recorder.truncate(scrubbedTo);\n ring.truncate(scrubbedTo);\n recorder.screen('scrub', `forked@${scrubbedTo}`);\n scrubbedTo = null;\n };\n\n const handle = runBrowser(def, mount, {\n ...opts,\n world: { seed, tuning: overrides },\n isHeld: () => isFrozen || (opts.isHeld?.() ?? false),\n onAdvance: (world, steps, actions) => {\n for (let i = 0; i < steps; i++) {\n recorder.step(actions, world.input.axes);\n ring.push(recorder.frame, world);\n }\n opts.onAdvance?.(world, steps, actions);\n },\n onPause: (paused) => {\n recorder.screen(paused ? 'pause' : 'resume');\n opts.onPause?.(paused);\n },\n onRestart: () => {\n // A restart ends the run: flush it, then record into a fresh session.\n flush('restart');\n recorder = new SessionRecorder({\n game: def.title,\n seed,\n tuningValues: { ...values },\n variant: variantRef,\n buildRef: recorder.buildRef,\n });\n (opts.onRestart ?? handle.restart)();\n },\n });\n\n // \u2500\u2500 HMR carryover: play continues across code edits \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const carried = opts.hot?.data.hayaoSnap as ReturnType<typeof handle.world.snapshot> | undefined;\n if (carried) {\n delete opts.hot!.data.hayaoSnap;\n const snap = structuredClone(carried);\n snap.tuning = { ...values }; // the NEW module's resolved tuning wins\n handle.world.restore(snap);\n def.attach?.(handle.world);\n // The new segment replays from this exact state \u2014 record it as the origin.\n recorder = new SessionRecorder({\n game: def.title,\n seed,\n tuningValues: { ...values },\n variant: variantRef,\n startSnapshot: snap,\n });\n recorder.screen('hot-swap');\n }\n opts.hot?.dispose((data) => {\n data.hayaoSnap = handle.world.snapshot();\n cleanup('hot-swap');\n });\n // Seed the scrub floor: frame 0 of this run (post-carryover if any).\n ring.push(0, handle.world);\n\n /**\n * Load a past session into the live pane: rebuild its exact starting world,\n * fast-replay the whole recording once to fill the snapshot ring, then land\n * scrubbed at `at` (or frame 0). Determinism turns the artifact into footage.\n */\n async function enterReplay(id: string, at: number): Promise<void> {\n const res = await fetch(`/__studio/session/${encodeURIComponent(id)}`);\n if (!res.ok) return;\n const artifact = (await res.json()) as PlaytestSession;\n isFrozen = true;\n const w = handle.world;\n // Transplant the artifact's origin into the live world (seed, rng, tuning).\n const base = createWorld(def, { seed: artifact.seed, tuning: artifact.tuningValues });\n w.restore(artifact.startSnapshot ? structuredClone(artifact.startSnapshot) : base.snapshot());\n def.attach?.(w);\n w.input.axes.clear();\n const frames = artifact.inputLog.frames;\n // Adaptive stride so the WHOLE tape stays scrubbable within the ring cap\n // (a fixed 30 would evict the start of any session longer than ~2 min).\n const stride = Math.max(30, Math.ceil(frames.length / 220 / 30) * 30);\n ring = new SnapshotRing(stride);\n ring.push(0, w);\n let axisIdx = 0;\n let knobIdx = 0;\n for (let i = 0; i < frames.length; i++) {\n while (knobIdx < artifact.knobEvents.length && artifact.knobEvents[knobIdx].frame === i) {\n const k = artifact.knobEvents[knobIdx++];\n const snap = w.snapshot();\n snap.tuning = { ...snap.tuning, [k.key]: k.value };\n w.restore(snap);\n def.attach?.(w);\n }\n while (axisIdx < artifact.axesLog.length && artifact.axesLog[axisIdx][0] === i) {\n const [, name, value] = artifact.axesLog[axisIdx++];\n w.input.axes.set(name, value);\n }\n w.step(frames[i]);\n ring.push(i + 1, w);\n }\n replay = { session: artifact, pos: frames.length };\n studio.scrub(Number.isFinite(at) ? at : 0);\n }\n\n /**\n * Playback: step recorded frames in real time while \"unfrozen\" in replay.\n * Elapsed-time accumulator, not per-tick stepping \u2014 browsers throttle timers\n * in hidden tabs, so each tick steps however many frames wall time owes\n * (capped, to avoid a giant catch-up after a long throttle).\n */\n function startPlayback(): void {\n if (!replay || playbackTimer !== null) return;\n const s = replay.session;\n let last = performance.now();\n playbackTimer = window.setInterval(() => {\n if (!replay) return;\n const nowMs = performance.now();\n const owed = Math.min(120, Math.floor((nowMs - last) / (1000 / 60)));\n if (owed <= 0) return;\n last = nowMs;\n const w = handle.world;\n for (let n = 0; n < owed; n++) {\n const i = replay.pos;\n if (i >= s.inputLog.frames.length) {\n stopPlayback();\n return;\n }\n for (const k of s.knobEvents) {\n if (k.frame === i) {\n const snap = w.snapshot();\n snap.tuning = { ...snap.tuning, [k.key]: k.value };\n w.restore(snap);\n def.attach?.(w);\n }\n }\n for (const [f, name, value] of s.axesLog) if (f === i) w.input.axes.set(name, value);\n w.step(s.inputLog.frames[i]);\n replay.pos = i + 1;\n }\n }, 1000 / 60);\n }\n function stopPlayback(): void {\n if (playbackTimer !== null) {\n window.clearInterval(playbackTimer);\n playbackTimer = null;\n }\n }\n\n if (replayId) void enterReplay(replayId, Number(new URLSearchParams(location.search).get('at') ?? 'NaN'));\n\n // Build identity comes from the dev server (git sha) \u2014 best-effort, async.\n void fetch('/__studio/state')\n .then((r) => (r.ok ? r.json() : null))\n .then((s: { buildRef?: string } | null) => {\n if (s?.buildRef) recorder.buildRef = s.buildRef;\n })\n .catch(() => {});\n\n setScreenObserver((kind, title) => recorder.screen(kind === 'show' ? 'overlay-show' : 'overlay-hide', title));\n\n const now = () => (typeof performance !== 'undefined' ? performance.now() - start : 0);\n const onVisibility = () => recorder.mark(document.hidden ? 'visibility-hidden' : 'visibility-visible', now());\n const onBlur = () => recorder.mark('blur', now());\n const onFocus = () => recorder.mark('focus', now());\n const onPageHide = () => flush('quit', true);\n document.addEventListener('visibilitychange', onVisibility);\n window.addEventListener('blur', onBlur);\n window.addEventListener('focus', onFocus);\n window.addEventListener('pagehide', onPageHide);\n // Mobile Safari kills tabs without ceremony \u2014 autosave so a session is never lost.\n const autosave = window.setInterval(() => flush('idle'), 10_000);\n\n /** Flush + release everything this run owns (stop() and HMR dispose share it). */\n const cleanup = (reason: EndReason) => {\n stopPlayback();\n flush(reason, reason === 'hot-swap');\n document.removeEventListener('visibilitychange', onVisibility);\n window.removeEventListener('blur', onBlur);\n window.removeEventListener('focus', onFocus);\n window.removeEventListener('pagehide', onPageHide);\n window.clearInterval(autosave);\n setScreenObserver(null);\n handle.stop();\n };\n\n const studio: StudioHandle = {\n ...handle,\n get world() {\n return handle.world;\n },\n setKnob(key, value) {\n if (replay) return; // the tape is read-only\n forkIfRewound(); // a knob turned while rewound commits that position first\n values[key] = value;\n const snap = handle.world.snapshot();\n snap.tuning = { ...values };\n handle.world.restore(snap);\n def.attach?.(handle.world);\n recorder.knob(key, value);\n },\n knobValues: () => ({ ...values }),\n tuningSpec: () => def.tuning,\n variants: () => Object.fromEntries(Object.entries(opts.variants ?? {}).map(([name, v]) => [name, v.label])),\n activeVariant: () => ({ ...variantRef }),\n title: () => def.title,\n annotate: (tag, note) => {\n if (!replay) recorder.annotate(tag, note);\n },\n setFrozen(frozen) {\n if (replay) {\n // In replay, \"unfrozen\" means the tape plays; the sim stays held.\n frozen ? stopPlayback() : startPlayback();\n return;\n }\n if (frozen === isFrozen) return;\n if (frozen) {\n isFrozen = true;\n return;\n }\n const wasRewound = scrubbedTo !== null;\n forkIfRewound();\n if (wasRewound) {\n // Knob values may have been rewound past \u2014 resync from the live world.\n const t = handle.world.snapshot().tuning ?? {};\n for (const key of Object.keys(values)) if (key in t) values[key] = t[key];\n }\n isFrozen = false;\n },\n frozen: () => (replay ? playbackTimer === null : isFrozen),\n scrub(frame) {\n if (replay) {\n stopPlayback();\n const s = replay.session;\n const reached = scrubTo(handle.world, def, ring, s.inputLog.frames, s.axesLog, s.knobEvents, frame);\n if (reached !== null) replay.pos = reached;\n return reached;\n }\n isFrozen = true;\n const reached = scrubTo(handle.world, def, ring, recorder.liveInputFrames, recorder.liveAxesLog, recorder.liveKnobEvents, frame);\n if (reached !== null) scrubbedTo = reached < recorder.frame ? reached : null;\n return reached;\n },\n timeline: () =>\n replay\n ? { min: ring.minFrame, frame: replay.pos, max: replay.session.inputLog.frames.length }\n : { min: ring.minFrame, frame: scrubbedTo ?? recorder.frame, max: recorder.frame },\n mode: () => (replay ? 'replay' : 'live'),\n flush: (reason = 'idle') => flush(reason),\n session: () => recorder.toSession('idle'),\n stop: () => cleanup('navigate'),\n };\n\n window.__studio = studio;\n return studio;\n}\n", "// @hayao \u2014 the single public seam. Games and examples import ONLY from here.\n// Everything below the barrel is swappable; this file is the whole API surface,\n// greppable in one place (an AI-first invariant).\n\n// \u2500\u2500 core: the deterministic kernel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './core/math';\nexport * from './core/projection';\nexport * from './core/dmath';\nexport * from './core/rng';\nexport * from './core/clock';\nexport * from './core/events';\nexport * from './core/hash';\n\n// \u2500\u2500 scene: the Godot-style node tree \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './scene/node';\n// Node2D is an alias for Node \u2014 the base node already carries a 2D transform.\nexport { Node as Node2D } from './scene/node';\nexport * from './scene/nodes';\nexport * from './scene/iso';\nexport * from './scene/cameraController';\nexport * from './scene/parallax';\nexport * from './scene/pool';\nexport * from './scene/tween';\nexport * from './scene/particles';\nexport * from './scene/floatingText';\nexport * from './scene/verletChain';\nexport * from './scene/registry';\n\n// \u2500\u2500 input: actions, sampling, record/replay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './input/actions';\nexport * from './input/source';\nexport * from './input/gamepad';\n\n// \u2500\u2500 physics: tilemaps, kinematic AABB, character controllers \u2500\u2500\u2500\u2500\nexport * from './physics/tilemap';\nexport * from './physics/aabb';\nexport * from './physics/platformer';\nexport * from './physics/spatialHash';\nexport * from './physics/raycast';\n// \u2500\u2500 physics: rigid-body dynamics (plain-data world \u2192 hash/snapshot free) \u2500\nexport * from './physics/rigidBody';\nexport * from './physics/rigidCollide';\nexport * from './physics/rigidJoints';\nexport * from './physics/rigidStep';\nexport * from './physics/rigidQueries';\n\n// \u2500\u2500 render: display list + backends \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './render/commands';\nexport * from './render/paint';\nexport * from './render/renderer';\nexport * from './render/svgString';\nexport * from './render/svg';\nexport * from './render/canvas';\nexport * from './render/webgl';\nexport * from './render/headless';\nexport * from './render/nineSlice';\n\n// \u2500\u2500 art: code-as-art helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './art/palette';\nexport * from './art/shapes';\nexport * from './art/texture';\nexport * from './art/font5';\nexport * from './art/bitmapFont';\nexport * from './art/autotile';\n\n// \u2500\u2500 procgen: deterministic generators + stateless scatter \u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './procgen/grid';\nexport * from './procgen/scatter';\nexport * from './procgen/cave';\nexport * from './procgen/terrain';\nexport * from './procgen/rooms';\n\n// \u2500\u2500 audio \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './audio/audio';\nexport * from './audio/pcm';\nexport * from './audio/synth';\nexport * from './audio/analysis';\nexport * from './audio/theory';\nexport * from './audio/chord';\nexport * from './audio/reverb';\nexport * from './audio/music';\nexport * from './audio/lint';\nexport * from './audio/match';\nexport * from './audio/adaptive';\nexport * from './audio/quality';\nexport * from './audio/genres';\nexport * from './audio/zzfx';\nexport * from './audio/album';\n\n// \u2500\u2500 ui: DOM overlays + shell + settings \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './ui/overlay';\nexport * from './ui/settings';\nexport * from './ui/shell';\nexport * from './ui/touch';\nexport * from './ui/transition';\n\n// \u2500\u2500 verify: the AI-first harness \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './verify/solver';\nexport * from './verify/determinism';\nexport * from './verify/playthrough';\nexport * from './verify/capture';\nexport * from './verify/driver';\nexport * from './verify/bot';\nexport * from './verify/layout';\nexport * from './verify/feel';\nexport * from './verify/gates';\nexport * from './verify/ramp';\nexport * from './verify/filmstrip';\nexport * from './verify/audioFilmstrip';\nexport * from './verify/ethnography';\nexport * from './verify/dom';\n\n// \u2500\u2500 logic: pure engine primitives (FSM, weighted tables, graph search) \u2500\nexport * from './logic/fsm';\nexport * from './logic/coroutine';\nexport * from './logic/random';\nexport * from './logic/graph';\nexport * from './logic/history';\n\n// \u2500\u2500 persist: save/load over a pluggable storage adapter + compact codecs \u2500\nexport * from './persist/storage';\nexport * from './persist/codec';\nexport * from './persist/save';\n\n// \u2500\u2500 content: data-driven wave/spawn directors + upgrade trees \u2500\u2500\u2500\nexport * from './content/dsl';\nexport * from './content/level';\nexport * from './content/generate';\nexport * from './content/campaign';\nexport * from './content/worldgraph';\n\n// \u2500\u2500 net: deterministic multiplayer (lockstep / rollback) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './net/players';\nexport * from './net/protocol';\nexport * from './net/transport';\nexport * from './net/inputBuffer';\nexport * from './net/lockstep';\nexport * from './net/rollback';\nexport * from './net/room';\nexport * from './net/browser';\n\n// \u2500\u2500 world + app \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nexport * from './world';\nexport * from './app/game';\nexport * from './app/tuning';\nexport * from './app/browser';\n\n// \u2500\u2500 studio (browser-safe parts; the vite plugin ships via `hayao/studio`) \u2500\u2500\nexport * from './studio/session';\nexport * from './studio/record';\nexport * from './studio/timeline';\nexport * from './studio/run';\n\n/** Engine version. */\nexport const VERSION = '0.4.0';\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["n", "n", "n", "mix", "n", "walk", "host", "n", "at", "rest", "at", "n", "rest", "n", "pad", "dx", "dy", "n", "area", "n", "m", "i", "n", "k", "j", "ex", "ey", "nx", "ny", "vax", "vay", "vbx", "vby", "ix", "iy", "warm", "n", "n", "n", "n", "r", "n", "n", "n", "n", "n", "n", "n", "off", "n", "n", "n", "n", "mix", "n", "n", "active", "n", "mono", "n", "vinyl", "all", "approach", "ride", "n", "rest", "approach", "STYLE_ID", "CSS", "ensureStyle", "knob", "hold", "smoothstep", "n", "hold", "n", "overlaps", "pad", "dedupe", "n", "dedupe", "n", "n", "pad", "n", "n", "rest", "host", "n", "EPS", "n", "n", "n", "n", "at", "tileAt", "resolve", "active", "resolve", "host", "replay", "at", "n", "reached"]
|
|
7
7
|
}
|