diff --git a/README.md b/README.md index 7c5a307..9671ad1 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ A game is a folder of JSON + PNGs β an LLM expansion is just JSON that deserializes. See **[docs/CONTROL.md](docs/CONTROL.md)** for the full guide (commands, events, HTTP routes, MCP tools, authoring JSON reference). +**π The deep read:** [THE MRPGI BOOK](web/manual.html) β the combined +user/dev manual with the authoring cookbook, AI prompt patterns with real +outputs, and engine internals. Live at +[monsterrobot.games/engine/manual.html](https://monsterrobot.games/engine/manual.html) +and under **Game β Manual** in the engine itself. + ## How it works (the AGI model, faithfully) Every room is drawn into **two buffers at once**: diff --git a/mrpgi/src/main.rs b/mrpgi/src/main.rs index 5d8f0f9..b3138d9 100644 --- a/mrpgi/src/main.rs +++ b/mrpgi/src/main.rs @@ -44,9 +44,24 @@ enum MenuAct { ToggleCrt, ToggleSound, Say(&'static str), + Manual, About, } +const MANUAL_URL: &str = "https://monsterrobot.games/engine/manual.html"; + +/// Open the Book: a new tab on the web, the default browser natively. +fn open_manual() { + #[cfg(target_arch = "wasm32")] + unsafe { + web_bridge::mrpgi_open_manual(); + } + #[cfg(not(target_arch = "wasm32"))] + { + let _ = std::process::Command::new("open").arg(MANUAL_URL).spawn(); + } +} + fn build_menus(crt: bool, sound_on: bool) -> Vec<(&'static str, Vec<(String, MenuAct)>)> { let onoff = |b: bool| if b { "on" } else { "off" }; vec![ @@ -57,6 +72,7 @@ fn build_menus(crt: bool, sound_on: bool) -> Vec<(&'static str, Vec<(String, Men ("Edit Mode Tab".to_string(), MenuAct::EditMode), (format!("CRT: {} F1", onoff(crt)), MenuAct::ToggleCrt), (format!("Sound: {} F2", onoff(sound_on)), MenuAct::ToggleSound), + ("Manual".to_string(), MenuAct::Manual), ("About MRPGI".to_string(), MenuAct::About), ], ), @@ -138,6 +154,7 @@ mod web_bridge { extern "C" { pub fn mrpgi_world_saved(ptr: *const u8, len: usize); + pub fn mrpgi_open_manual(); } /// JS asks for a buffer to write into. @@ -355,6 +372,10 @@ async fn main() { audio.set_muted(m); } Some(MenuAct::Say(s)) => events.extend(gs.apply(Command::Parse { text: s.to_string() })), + Some(MenuAct::Manual) => { + open_manual(); + gs.transcript.push("(the Book opens in a new tab.)".to_string()); + } Some(MenuAct::About) => { gs.transcript.push("MRPGI \u{2014} Monster Robot Party Game Interpreter.".to_string()); gs.transcript.push("A new-school Sierra AGI engine. Tab opens the room painter.".to_string()); diff --git a/web/build.sh b/web/build.sh index 38d02ec..1c3e3b7 100755 --- a/web/build.sh +++ b/web/build.sh @@ -13,5 +13,5 @@ cd "$(dirname "$0")/.." cargo build -p mrpgi --release --target wasm32-unknown-unknown mkdir -p web/dist cp target/wasm32-unknown-unknown/release/mrpgi.wasm web/dist/ -cp web/index.html web/mq_js_bundle.js web/dist/ +cp web/index.html web/manual.html web/mq_js_bundle.js web/dist/ echo "web build ready: $(du -sh web/dist | cut -f1) in web/dist/" diff --git a/web/index.html b/web/index.html index acd113c..01188a6 100644 --- a/web/index.html +++ b/web/index.html @@ -115,6 +115,10 @@
F1 CRT scanlines · F2 sound · whole thing is ~1 MB · also drivable headlessly by terminals, Python, and AIs (it's an MCP server). Made by Monster Robot Party.
+→ THE MRPGI BOOK — + the deep manual: authoring games as JSON, AI prompt patterns, driving the + engine from code, and the engine internals. Also under + Game → Manual in the menu bar.