The title screen / world picker now works in the browser, not just natively.
`./web/build.sh <folder-of-game-folders>` stages every game inside it plus
collection.json and bakes the lot into one wasm; the engine boots into the
shelf exactly as it does on the desktop. Sixteen cases of Police Squad Quest
come to 2.1 MB total.
- embedded_world() becomes embedded_world_at(prefix), so one bundle can hold
many games; embedded_games() / embedded_collection_name() are the browser
twins of world::scan_collection / collection_name.
- The picker is now keyed by String on both platforms and resolved through one
load_by_key() — a filesystem path natively, an embedded subdirectory in the
browser — so Mode::Title has a single implementation.
- Esc is a no-op on the web when there is nowhere to back out to. Breaking the
main loop in a browser just leaves a dead black canvas; found by pressing it.
- ascii_fold() on every game-text draw. macroquad's built-in font has no em
dash, curly quote, star or dagger, so room names like "— Squad Room —" and
every death card were drawing tofu boxes in both builds. Folding at the draw
layer fixes the whole engine without making game authors type worse prose.
- web/build.sh uses the rustup toolchain explicitly: cargo/rustc on PATH may be
Homebrew's, which ships no wasm32 std even though `rustup target list` shows
the target installed, and the resulting "can't find crate for core" is a
thoroughly misleading error.
Verified in a real browser: shelf renders, arrows move the selection and swap
the live room preview, Enter loads and plays the case, Esc returns to the shelf
with the selection preserved. Native --shot and all 13 core tests still pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MRPGI_WEB_GAME env (default games/lost-fuse via .cargo/config.toml)
selects the game include_dir! embeds; web/build.sh <game-dir> stages
just game.json+rooms+sprites (a repo's raw art was ballooning the wasm
to 41MB; now 1.9MB) and ships the game's web/index.html and music/.
- sound.rs: file overrides load through macroquad's loader (fs on native,
HTTP fetch on web), and AudioOut now loads inside a coroutine behind
LazyAudio — browsers gate audio decoding behind a user gesture, and
blocking boot on it was a black screen. First frame draws immediately;
music starts when ready, remembering the requested mood/mute.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- web/manual.html — 17 chapters: playing, the editor deeply, the
authoring cookbook (full JSON reference + the five load-bearing
puzzle patterns), dialogue trees, flags, the art pipeline with
sprite-generation prompts, sound, driving the engine with code
(real JSONL transcripts), AIs + MCP, prompt patterns with actual
outputs (the roof room is the real shipped expansion), the web
build & cloud saves, engine internals, extension recipes,
troubleshooting, and full command/event/palette reference.
- Game menu gains "Manual": window.open on the web (via a JS plugin
import), the default browser natively.
- README tab links the Book; repo README points at it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live at https://monsterrobot.games/engine/ (dealgod VPS, dealgod-nginx
/engine alias over /opt/dealgod/images/engine/).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- mrpgi-core: ureq/tiny_http/threads are native-only deps; the AI lane
compiles to an always-off stub on wasm32 (deterministic parser stays).
- World::from_memory + assets::cel_from_bytes — boot a game with no
filesystem.
- mrpgi GUI on wasm: embeds games/lost-fuse via include_dir, boots
straight into Play (Tab still opens the editor; saving needs a disk,
so web is play + paint-only for now).
- web/: index.html shell + macroquad JS loader + build.sh producing a
self-contained static web/dist (1.1 MB total, game included).
- .cargo/config.toml: --allow-undefined for miniquad's JS imports.
Verified in-browser: renders, typed commands reach the parser,
click-to-walk works, zero console errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>