1# marbles23Seeded, emergent marble-track generator. A Deno webapp that assembles an endless4marble race from Kenney's CC0 [Marble Kit](https://kenney.nl/assets/marble-kit),5with the Nature Kit as a scenery layer. The URL fragment is the seed — every6generated track is a browser-history entry you can share, revisit, and step7back/forward through.89## Quickstart1011```sh12deno task dev # build (watch) + serve → http://localhost:800013```1415Open `http://localhost:8000/#your-seed-here` — any string is a valid seed.1617- **New run** button (or editing the hash) generates a new seed and history18 entry.19- **Follow cam / Orbit cam** or `C` toggles the camera. Drag to rotate and20 scroll to zoom. Follow zoom persists; wide views use gentler camera movement.21- **Pause / Resume** or `K` pauses the run while leaving orbit controls usable.22- **Your marble / Race leader** or Space changes the camera subject when the run23 has other racers. Solo runs omit this control.24- **Full screen** or `F` toggles full screen; Esc exits.25- **Share** copies the complete world URL, including seed and settings.26- **Settings** returns to the launch screen with the current seed and options.27- **Simulation options** contains Classic loop, Modern/Legacy steering, physical28 simulation, diagnostics and Piece gallery.29- `?debug=1` overlays the loop centerline; `?gallery=1` lays out every imported30 piece.3132## Tasks3334| task | what |35| ------------------------- | ------------------------------------------------------------ |36| `deno task dev` | bundle watch + dev server with live reload |37| `deno task build` | one-shot browser bundle → `static/dist/app.js` |38| `deno task build:physics` | rebuild Box3D shim → `static/dist/box3d.mjs` + `.wasm` |39| `deno task build:site` | rebuild JS and physics, package static files and assets |40| `deno task assets:import` | re-run the asset pipeline from the Kenney packs |41| `deno task test` | full test suite (RNG, registry, topology fuzz, golden seeds) |42| `deno task check` | type-check everything |4344`assets/` ships committed (packed GLBs + manifests), so `assets:import` is only45needed when re-importing from the source packs (path configurable via46`--source-root`).4748Physics shim changes require `build:physics` as well as the browser build. It49uses Emscripten and CMake; include both native artifacts when distributing the50site. See [the stall fix notes](docs/stall-fixes-2026-09-30.md) for the current51collision behavior and verification.5253## Deployment5455The existing Cloudflare Pages project is `marbles`, at56[marbles-3a0.pages.dev](https://marbles-3a0.pages.dev). Build the complete site,57including the native physics module and asset packs, before deploying:5859```sh60deno task build:site61npx wrangler pages deploy --project-name marbles --branch main62```6364The build output is `output/site/`; generated bundles stay out of Git.6566## How it works6768```69seed (URL fragment)70 └─ rngFamily(seed, label) one independent sfc32 stream per system;71 ├─ topology closed rectilinear cycle (closure by construction)72 ├─ elevation hill profile, Σ deltas = 0, support-grid heights73 ├─ style theme weights, palette a/b/c, solid policy74 ├─ setting scenery pack + placement rule table (Nature Kit)75 ├─ decor rule-based scenery realization around the track76 └─ wfc realization: wave-function collapse over the ring77 └─ assemble placements + supports + closed centerline78 └─ validateTrack invariants (tests/dev)79```8081Systems emit constraints and weights, never placements; the WFC pass picks the82actual pieces (windows over the ring, min-entropy collapse, occupancy vetoes,83single-cell fallbacks make contradictions impossible). Streams are derived by84label, not draw order, so adding systems later never perturbs existing seeds.8586Piece semantics (ports, channel-floor heights, arc radii, ramp tier deltas) were87measured from the GLB geometry; `tests/registry_test.ts` lints the registry's88internal consistency, and `tests/golden_tracks.json` pins fixed-seed outputs —89regenerating it breaks every seed URL in the wild, so do it knowingly.9091## Assets9293All assets are [Kenney](https://kenney.nl)'s, CC0. The import pipeline packs94each kit into a single deduped GLB (162 pieces / 2.0 MB for the Marble Kit) plus95a classification manifest. Marble Kit coverage is staged: M1 realizes straights,96corners, curves, ramps, slants, tunnels, supports, and decor; bends, s-curves,97wide pieces, waves, bumps (M2), helixes, crossings (M3), and splits, funnels,98fans-as-obstacles (M4) extend the same window/registry model.