# MRPGI — The Complete Manual **Monster Robot Party Game Interpreter** — a new-school, Apple-Silicon-native reimagining of Sierra's 1980s AGI adventure engine, written in Rust + macroquad. You paint rooms, drop in objects, write puzzles, and walk through them — with a text parser, optional local-AI understanding, branching dialogue, chiptune sound, and ambient music. No external level files, no build step beyond `cargo`. This manual is exhaustive. Jump around with the table of contents. --- ## Table of contents 1. [What MRPGI is](#1-what-mrpgi-is) 2. [Install & requirements](#2-install--requirements) 3. [Running it](#3-running-it) 4. [The two modes](#4-the-two-modes) 5. [Core concepts (read this)](#5-core-concepts-read-this) 6. [The editor — full reference](#6-the-editor--full-reference) 7. [Keyboard cheat sheet](#7-keyboard-cheat-sheet) 8. [Building a world (rooms & exits)](#8-building-a-world-rooms--exits) 9. [Objects & game logic](#9-objects--game-logic) 10. [The parser](#10-the-parser) 11. [The AI parser lane](#11-the-ai-parser-lane) 12. [Dialogue trees](#12-dialogue-trees) 13. [Sound & music](#13-sound--music) 14. [The art / sprite pipeline](#14-the-art--sprite-pipeline) 15. [The kit & theme packs](#15-the-kit--theme-packs) 16. [Games as folders & the file formats](#16-games-as-folders--the-file-formats) 17. [Programmatic control (CLI · HTTP · MCP · Python)](#17-programmatic-control-cli--http--mcp--python) 18. [Project layout & architecture](#18-project-layout--architecture) 19. [Troubleshooting](#19-troubleshooting) 20. [Roadmap & known gaps](#20-roadmap--known-gaps) --- ## 1. What MRPGI is AGI was the engine behind *King's Quest*, *Space Quest*, and *Police Quest*. Its genius was a **dual-buffer** model: every room is drawn into a *visual* screen (what you see) **and** a hidden *priority* screen (depth + walkability). MRPGI keeps that soul and modernizes everything around it: - **In-engine room editor** — paint walls, floors, and walkability by hand. - **Sprite pipeline** — drop PNGs in a folder; they're auto-quantized to EGA. - **Multi-room worlds** with edge exits. - **Objects** with descriptions, locks, keys, and win conditions — no code. - **A forgiving parser** + an **optional local LLM** that understands plain English. - **Branching dialogue**, **chiptune SFX**, and **ambient room music**. - **Flags & gated puzzles** — multi-step quests authored as plain JSON. - **A content kit**: 61 click-to-place archetypes across fantasy, sci-fi, monsters, "saucy" nightlife, and classic horror. - **A fully headless core** — the same engine is drivable from the command line, HTTP, Python, or an AI over MCP, with no window (§17). Everything saves to small, human-readable JSON: **a game is a folder** you can zip, share, or have an LLM write. The engine builds with `cargo` into two binaries: the GUI (`mrpgi`) and the headless multi-tool (`mrpgi-headless`). --- ## 2. Install & requirements **Required:** - **Rust** (stable, 1.85+). Install from or Homebrew. - That's it for building — macroquad pulls its own dependencies and renders natively (Metal on macOS). No system libraries to install. **Optional (for the AI parser):** - **[Ollama](https://ollama.com)** running locally with a small instruct model (e.g. a Gemma 4B). Free, offline, private. Or an **OpenRouter** API key. First build downloads the crate tree and takes a minute or two; subsequent builds are seconds. --- ## 3. Running it ```sh cargo run -p mrpgi # build + run the GUI (dev) cargo run -p mrpgi --release # optimized build (smoother), slower first compile ./run.sh # convenience launcher that points the AI lane at your model ``` ### Launch flags | Flag | Effect | |------|--------| | *(none)* | Loads the game in the current directory (`game.json` + `rooms/room0.json`) and opens in the **editor**. | | `--game DIR` | Load a game folder instead of the current directory (see §16). | | `--sample` | Writes a 3-room "escape the party" demo (+ `game.json`) then runs it (existing rooms backed up to `*.json.bak`). | | `--kit` | Generates the fantasy starter kit + placeholder sprites, and installs a 4-room fantasy world (existing → `.bak`). | ```sh cargo run -p mrpgi -- --kit # install + play the fantasy starter world cargo run -p mrpgi -- --sample # install + play the robot escape demo cargo run -p mrpgi -- --game games/lost-fuse # play the example game (§16) ``` The headless binary takes the same `--game` / `--sample` / `--kit` flags: ```sh cargo run -p mrpgi-core --bin mrpgi-headless -- --sample --game games/demo ``` ### AI environment variables | Var | Default | Meaning | |-----|---------|---------| | `MRPGI_AI` | `ollama` | `ollama` · `openrouter` · `off` | | `MRPGI_AI_MODEL` | `gemma3:4b` | the model tag (set to YOUR Ollama tag) | | `MRPGI_AI_URL` | `http://localhost:11434/api/generate` | endpoint override | | `OPENROUTER_API_KEY` | — | required when `MRPGI_AI=openrouter` | ```sh MRPGI_AI_MODEL="your-gemma-tag" cargo run MRPGI_AI=openrouter OPENROUTER_API_KEY=sk-... MRPGI_AI_MODEL=google/gemma-2-9b-it:free cargo run MRPGI_AI=off cargo run # deterministic parser only ``` --- ## 4. The two modes MRPGI is always in one of two modes; **`Tab`** flips between them: - **EDIT** — the painting/authoring mode. Left panel of tools, a canvas, a top strip for world/room controls. The engine boots here. - **PLAY** — you become the robot. Walk with arrows or click, type commands, talk to NPCs. A bottom panel shows the transcript + command line. `Esc` quits (in edit it first un-focuses a text field; in play it first ends a conversation). --- ## 5. Core concepts (read this) ### The dual buffer — LOOK vs MEANING Every pixel of a room has **two** independent properties: - **LOOK** — its colour (one of 16 EGA colours). What the player sees. - **MEANING** — what it *is* to the engine: walkable floor, a wall, water, a trigger, or a depth band. Stored in a hidden "priority" buffer. **Colour does not imply meaning.** A brown floor and a brown wall look identical but behave differently. When you paint, you set a colour *and* (optionally) a meaning tag; they're applied to the same region but stored separately. This is the single most important idea in MRPGI. ### Meaning tags | Tag | Effect on the priority buffer | |-----|-------------------------------| | **floor** | walkable, with automatic depth (lower on screen = drawn in front) | | **wall** | blocked — the robot can't enter | | **water** | reserved (special) | | **trigger** | reserved (signal line for future logic) | | **none** | paint colour only; leave walkability unchanged | By default an empty room is **entirely walkable** — you paint *walls* where you don't want walking. ### The picture The play area is **160 × 168 logical pixels**, displayed at a **2:1 pixel ratio** (each pixel is twice as wide as tall — classic AGI). Colours are the 16-colour EGA palette (indices 0–15). A perfect circle drawn in art tools looks slightly wide in-game; that's intentional retro flavour. ### EGA palette `0` black · `1` blue · `2` green · `3` cyan · `4` red · `5` magenta · `6` brown · `7` light gray · `8` dark gray · `9` light blue · `10` light green · `11` light cyan · `12` light red · `13` light magenta · `14` yellow · `15` white. ### The ego "Ego" is the AGI term for the player avatar (the little robot). Its position is its **feet** (bottom-centre of its sprite), which is what determines its depth and collision. In play it's blocked by `wall` pixels and walks off `exit` edges. --- ## 6. The editor — full reference The editor screen: a **tool panel** on the left, the **canvas** on the right, and a **world strip** across the top of the canvas. ### Tools (number keys, or click in the panel) | Key | Tool | What it does | |-----|------|--------------| | `1` | **brush** | freehand paint with the current colour + meaning (size via `,` `.`) | | `2` | **line** | click to add points; **right-click or Enter** finishes the polyline | | `3` | **rect** | drag a filled rectangle | | `4` | **fill** | flood-fill a sealed region (the bucket) — fast | | `5` | **pick** | eyedropper; grab a colour off the canvas | | `6` | **erase** | rub back to blank + walkable | | `7` | **image** | stamp a sprite from `sprites/` (`[` `]` to choose, `R` to reload) | | `8` | **oval** | drag a filled ellipse | | `9` | **spawn** | click to set where the robot appears in play (cyan circle) | | `0` | **object** | place a live object — see below | ### Colour & meaning - **Palette** (left panel): click a swatch to set the current LOOK colour. - **Meaning** buttons: floor / wall / water / trigger / none — the MEANING applied by fills, rects, brush, etc. ### View modes (`L` cycles) - **look** — the plain picture. - **both** — picture + walls tinted red, water blue, triggers green (so you can *see* what's walkable). - **ctrl** — the raw meaning map (depth + control). ### The object tool & kit browser (`0`) With the object tool active the panel shows **`kit [ ]: `**. Press `[` `]` to flip through 60+ ready-made archetypes (orc, console, cocktail, coffin…). Click an empty spot to **stamp** the selected archetype, fully written. Cycle to `(blank)` to drop a bare object named after the current sprite. Click an existing object to **select** it; the inspector then shows editable fields: - **name** — what the parser calls it. - **look text** — response to `look`. - **use text** — response to `use`/`open`. - **needs item** — an item required to `use` it (empty = unlocked). - **synonyms** — extra nouns it answers to (space-separated). - **takeable / fixed** toggle, **wins** toggle, **delete**. Click a field, type, `Enter` jumps to the next field, `Esc` finishes. ### The world strip (top) - **room N** + `<` `>` — move between rooms (also `-` `=`). Switching auto-saves. - **exits** `N E S W` — click to cycle each edge's target room number. - **♪** — cycle the room's ambient music mood (off · calm · eerie · tense · jolly · spooky). ### Saving - `K` saves the current room to `rooms/room.json` (an editable list of strokes + objects + exits + spawn + music). `O` reloads it. `C` clears, `Z`/`Backspace` undoes. The game auto-loads `rooms/room0.json` on startup. --- ## 7. Keyboard cheat sheet **Global:** `Tab` edit ⇄ play · `Esc` quit (or un-focus / end conversation) · `F1` CRT scanlines · `F2` mute sound + music. **Editor:** `1`–`0` tools · `L` view · `[` `]` choose sprite / kit archetype · `,` `.` brush size · `-` `=` prev / next room · `Z`/`Backspace` undo · `C` clear · `K` save · `O` load · `R` reload sprites + kit. **Play:** arrows / click to walk · type a command + `Enter` · `1`–`6` choose a dialogue reply · `Esc` leave a conversation. --- ## 8. Building a world (rooms & exits) A room is one screen. A world is rooms linked by their edges. 1. Paint a room. Leave a **walkable gap** in a wall where you want a doorway. 2. On the strip, set that edge's **exit** to a room number (e.g. `E: 1`). 3. Press `>` to go to that room (going past the last room makes a new blank one), paint it, and set a matching exit back. 4. In play, **walk off the edge with an exit** → you arrive in the target room, entering from the opposite side. Rooms are files: `rooms/room0.json`, `room1.json`, … Room 0 is where the game starts. The **spawn** tool sets each room's entry point (used if the edge you arrive at is walled). --- ## 9. Objects & game logic Objects are sprites you can interact with. Each carries: - a **name** + **synonyms** (what the parser matches), - **look text** (shown on `look`), - **use text** (shown on `use`/`open`), - **needs** — an item that must be in your inventory to `use` it, - **wins** — using it successfully ends the game with a victory banner, - **takeable** — whether `take` adds it to your inventory, - **requires_flag** — a flag that must be true before `use` works, - **sets_flag** — a flag set true when `use` succeeds. This is enough for the classic adventure loop **with no code**: > Put a `key` (takeable) in one room and a `gate` in another with **needs = key**, > **use text** = *"The gate grinds open…"*, **wins = on**. Now: `take key` → > travel → `use gate` → **win**. ### Flags — multi-step quests **Flags** are named booleans that live for one play session (a game's `game.json` can preset them). Objects and dialogue choices read and write them: > A `lever` with **sets_flag = power_on**. A `door` with **requires_flag = > power_on**, **wins = on**. Now `use door` says *"Nothing happens. Something > else must come first."* until you `use lever`. Chain `needs` (items) with `requires_flag`/`sets_flag` (state) and gated dialogue (§12) and you get real multi-step quests — all data, no code. The example game `games/lost-fuse/` demonstrates the whole chain (§16). Taking an object removes it from the room (runtime only — it returns on a fresh play). Objects do not block movement (walls come from the painted meaning layer). Currently `requires_flag`/`sets_flag` are JSON-authored (the editor inspector shows the older fields only). --- ## 10. The parser Type a sentence; it's lower-cased, filler words are dropped, the first word maps to a canonical verb, and the rest is the noun (matched against object names + synonyms, loosely). **Verbs (and their synonyms):** - **look** — look, l, examine, x, inspect, check, read, view, see, study - **take** — take, get, grab, pick, snatch, steal, pocket, collect, nab - **use** — use, open, unlock, activate, push, pull, turn, operate - **drop** — drop, discard, leave, put - **talk** — talk, speak, ask, chat, greet, say - **inventory** — inventory, inv, i, items, bag - **help** — help, ?, commands, verbs **Ignored filler:** the, a, an, at, to, with, on, of, my, your, some, please, go, up. `look` with no noun (or `look around`) lists what's in the room. Unknown verbs fall through to the AI lane (if enabled) or print "I don't understand". --- ## 11. The AI parser lane When the deterministic parser can't recognise your verb, MRPGI can hand the raw sentence to a small LLM, which translates it into **one allowed command** — then re-runs *that* through the normal logic. The AI bends the *language*; your game still decides what's *possible*. It never invents items or outcomes, and it runs on a background thread so the game never stalls. The chosen command is shown as `(≈ open crate)`. **Setup (local, recommended):** run Ollama with an instruct model and point MRPGI at it via `MRPGI_AI_MODEL` (see §3). Default provider is `ollama`. If Ollama isn't running or the model is missing, the lane stays silent and you get the normal deterministic behaviour — nothing breaks. **OpenRouter:** set `MRPGI_AI=openrouter`, `OPENROUTER_API_KEY`, and a `MRPGI_AI_MODEL` like `google/gemma-2-9b-it:free`. The bottom bar shows `ai: ollama/` (or `off`). --- ## 12. Dialogue trees An object can carry a **branching conversation**. In play, `talk ` starts it: the NPC speaks and you press a **number key (1–6)** to choose a reply. Choices jump to other lines; some end the chat. `Esc` leaves. Walking pauses while you talk. Dialogue is authored as a `dialogue` array on the object (a visual builder is planned). Each entry is a **node**; node 0 is the entry. See the inn barkeep in `rooms/room3.json` for a working example: ```json "dialogue": [ { "says": "You're for the cave, aren't you?", "choices": [ { "text": "What's down there?", "goto": 1 }, { "text": "Just passing through.", "goto": 3 } ] }, { "says": "Orcs. Dark. A spellbook nobody should read aloud.", "choices": [ { "text": "Thanks.", "goto": -1 } ] } ] ``` A choice's **`goto`** is the next node index, or **`-1`** to end. A node with no choices is a terminal line (shown, then the conversation ends). ### Gated choices Choices can read and write flags (§9), which makes conversations part of the puzzle chain: ```json { "text": "Hear that? I'm with the band.", "goto": 2, "requires_flag": "music_on", "sets_flag": "on_the_list" } ``` A choice with `requires_flag` is **hidden** until that flag is true — the numbering the player sees always matches what they can pick. `sets_flag` fires when the choice is chosen. So an NPC can refuse to say something until you've done a thing, and telling them can unlock a door elsewhere. --- ## 13. Sound & music By default all audio is **synthesized at runtime** (square waves → PCM, no files), in the spirit of AGI's PCjr beeper — and any of it can be **overridden per game with real audio files** (below). **SFX (play mode):** a blip when you submit a command, a ding on `take`, a chime on a successful `use`/`look`, a buzz when nothing matches, a whoosh on room change, a 4-note fanfare on **win**. **Ambient music:** each room can loop one of five moods (calm / eerie / tense / jolly / spooky), set with the **♪** strip button in the editor and saved per room. It plays in play mode and switches as you move between rooms. **`F2`** mutes music and SFX together. If a machine has no audio backend, everything degrades to silence. ### Your own audio files Drop files into the game folder and they replace the synth, cue for cue: ``` /sfx/blip|pickup|confirm|error|door|win .wav|.ogg|.mp3 /music/calm|eerie|tense|jolly|spooky .wav|.ogg|.mp3 (or 1.ogg … 5.ogg) ``` Anything you don't provide keeps its chiptune default. Prefer **OGG for looping music** (MP3 encoders pad silence that clicks at the loop seam). --- ## 14. The art / sprite pipeline Sprites live in `sprites/` as PNGs. On load, any image is **quantized to the EGA palette** (with transparency from its alpha), so it depth-sorts and walks-behind like native art. Replace any sprite and press **`R`** to reload. **The sprite spec:** - **PNG with transparency.** Transparent pixels are see-through. - **Small, at game scale.** A prop is ~12–28 px tall; draw 1:1. - **Filename = id.** lowercase, no spaces (`orc.png`). The object's `sprite` field references this name. A missing sprite shows as a magenta placeholder. - **Bottom-centre = feet.** Stand the thing on the bottom edge of the canvas. - **EGA colours** ideal but not required — load `palettes/mrpgi-ega.gpl` into Aseprite/Inkscape, or let the engine snap your colours on load. **Aseprite:** Palette → Load Palette → `palettes/mrpgi-ega.gpl`; draw small; export PNG to `sprites/`; press `R`. **Inkscape:** set a tiny px page; Export PNG (transparent) to `sprites/`. **AI (Gemini "Nano Banana" / Imagen):** each theme's `gemini_sprites.md` has a shared STYLE line + per-sprite prompts. Generate on a solid magenta background, key it out to transparency, save into `sprites/`. (See also `palettes/mrpgi-ega.gpl` and `palettes/mrpgi-ega.hex`.) --- ## 15. The kit & theme packs `cargo run -- --kit` generates the **fantasy starter kit** and installs a playable 4-room world (forest → cave → dungeon → inn, with a key/spellbook/altar quest). The reusable library lives in `kit/`: - **`kit/objects.json`** — 13 fantasy object archetypes. - **`kit/locations/`** — prefab rooms (forest, cave, dungeon, inn). - **`kit/ART_MANIFESTO.md`** — exact sprite specs to replace the placeholders. - **`kit/themes/{scifi,monsters,saucy,horror}/`** — each with `objects.json` (12 archetypes), a sample `locations/*.json`, and `gemini_sprites.md`. **Use an object:** the kit browser (object tool, `[` `]`) stamps any of these by clicking. Or copy a `{ … }` block from any `objects.json` into a room's `objects` array. **Use a location:** `cp kit/themes/horror/locations/crypt.json rooms/room5.json`, then wire its exits in the editor. --- ## 16. Games as folders & the file formats **A game is a folder.** Zip it, share it, generate it with an LLM — the engine loads it with `--game DIR` (both binaries): ``` games/mygame/ game.json the manifest (below) — optional, every field defaults rooms/room0.json one RoomDoc per room; start room comes from the manifest sprites/*.png auto-quantized to EGA; filename = sprite name sfx/ music/ optional audio-file overrides (§13) ``` A bare directory with just `rooms/` is already a valid game — that's how legacy projects keep loading. **game.json (the manifest):** ```json { "name": "The DJ's Lost Fuse", "start_room": 0, "intro_text": "The party upstairs went quiet an hour ago. Type 'help'.", "verbs": [ { "name": "use", "words": ["plug", "spin"] } ], "flags": { "met_bouncer": false } } ``` `verbs` merges extra synonyms into the built-in verb table (the AI lane's whitelist is generated from the same table, so they can't drift). `flags` are the starting flag values for each new game. A complete worked example ships in **`games/lost-fuse/`** — three rooms demonstrating every mechanic (items, locks, flags, gated dialogue, win), with a guided tour in [`games/README.md`](games/README.md). ### Room file format (full schema) A room is a `RoomDoc` serialized as JSON: ```json { "strokes": [ , ... ], "spawn": [x, y], "exits": [N, E, S, W], // each: a room number or null "objects": [ , ... ], "music": 0 // 0=silence, 1..5 = mood } ``` **Stroke** is an externally-tagged enum — exactly one key: ```json { "Rect": { "x":0,"y":0,"w":160,"h":168,"color":2,"meaning":"Floor" } } { "Line": { "pts":[[x,y],...], "color":15 } } { "Brush": { "pts":[[x,y],...], "color":6,"meaning":"Wall","size":2 } } { "Ellipse": { "x":..,"y":..,"w":..,"h":..,"color":..,"meaning":"None" } } { "Fill": { "x":..,"y":..,"color":..,"meaning":"Floor" } } { "Image": { "name":"crate","x":..,"y":..,"meaning":"Wall" } } ``` `meaning` is one of `"None"`, `"Floor"`, `"Wall"`, `"Water"`, `"Trigger"`. `color` is an EGA index 0–15. **ObjDef:** ```json { "name": "gate", "sprite": "door", "x": 80, "y": 120, "look": "A heavy gate.", "takeable": false, "synonyms": "door portcullis", "use_text": "It grinds open!", "needs": "key", "wins": true, "requires_flag": "power_on", "sets_flag": "gate_open", "dialogue": [ , ... ] } ``` **DlgNode:** `{ "says": "...", "choices": [ { "text": "...", "goto": 1, "requires_flag": "", "sets_flag": "" } ] }` — `goto` is a node index or `-1` to end; the flag fields are optional (§12). All fields except `name`/`sprite`/`x`/`y` default if omitted, so hand-written JSON can be minimal. Strokes are *replayed* into the buffers on load, so rooms stay tiny and re-editable. --- ## 17. Programmatic control (CLI · HTTP · MCP · Python) The engine core is fully headless: a `GameState` driven by JSON `Command`s in and `Event`s out. The GUI is just one consumer of that bus — the same bus is exposed as: - **JSONL stdio** — `mrpgi-headless --game DIR`; pipe `{"cmd":"parse","text":"take key"}` lines in, events stream out. - **Script replay** — `--script play.jsonl` replays a command log deterministically (byte-identical transcripts; the CI golden-test workflow). - **Headless render** — `--render-room rooms/room0.json out.png` bakes any room to a PNG with no window. - **HTTP** — `--serve 127.0.0.1:7777`: `POST /command`, `GET /state`, `GET /frame.png`, `GET /events?since=N`, `POST /rooms/{n}`. Python drives it with plain `requests`. - **MCP** — `--mcp`: a Model Context Protocol server, so Claude (or any MCP client) can both *play* the game and *author* it — including `mrpgi_render_frame`, which returns a real PNG so the model sees its work: `claude mcp add mrpgi -- /path/to/mrpgi-headless --mcp --game games/mygame` Full command/event reference and authoring contract: **[docs/CONTROL.md](docs/CONTROL.md)**. --- ## 18. Project layout & architecture Two crates in one workspace: ``` mrpgi-core/ the headless engine (ZERO window/audio deps — enforced) src/state.rs GameState + the Command/Event bus + fixed-step tick src/world.rs RoomDoc/ObjDef/dialogue data model, World, game folders src/parser.rs data-driven verb table, verb-noun parser, dialogue state src/render.rs headless compositing → RGBA / PNG src/framebuffer.rs visual + priority buffers, the band(y) depth table src/picture.rs drawing primitives (lines, rects, flood-fill, stamps) src/view.rs sprites as cels; ASCII-grid cel builder src/sprite.rs the ego + props: movement, collision, walk-cycle src/assets.rs PNG load + EGA quantize/dither; placeholder sprites src/audio.rs chiptune synthesis + audio cues (content, not output) src/ai.rs the AI parser lane (Ollama / OpenRouter, worker thread) src/kit.rs sample game + starter kit writers src/bin/mrpgi-headless/ the CLI/HTTP/MCP surfaces tests/engine.rs parser goldens + a full win-path replay test mrpgi/ the macroquad GUI (one consumer of the bus) src/main.rs window, play loop over Commands/Events, HUD src/editor.rs the paint tool (commits edits through the same bus) src/sound.rs audio out: game-folder files override the synth kit/ the archetype/theme library + art manifesto games/ game folders (lost-fuse example lives here) sprites/ rooms/ the legacy in-place game (still loads fine) palettes/ the EGA palette for Aseprite/Inkscape (.gpl, .hex) ``` **Rendering:** rooms rasterize into a 160×168 visual buffer + a priority buffer. Each frame, the ego and props are drawn back-to-front by depth; a sprite pixel is only drawn where `sprite_priority ≥ scenery_priority` (the walk-behind trick). The result is composited headlessly in the core; the GUI just uploads it to a GPU texture. A fixed-step "cycle" (20/s) drives movement, decoupled from frame rate — which is why scripted replays are bit-identical. --- ## 19. Troubleshooting - **Objects are little magenta squares** → that sprite PNG doesn't exist yet in `sprites/`. Make it (see §14) or it's just a placeholder; the object still works. - **A fill flooded the whole screen** → your outline has a gap; the region wasn't sealed. `Z` to undo and close the gap. - **Robot stuck after a room transition** → the edge you arrived at is walled; leave a walkable gap there (it otherwise falls back to the room's spawn). - **AI does nothing** → check the bottom bar `ai:` readout; ensure Ollama is running and `MRPGI_AI_MODEL` matches a pulled model (`ollama list`). It only fires on *unknown verbs*. - **No sound** → some machines lack an audio backend; MRPGI stays silent rather than crashing. Check `F2` isn't muted. - **Typing a letter flipped a mode** → in play, letters go to the command line; use `Tab`/`F1`/`F2`/`Esc` (non-letters) for controls. --- ## 20. Roadmap & known gaps - In-editor **dialogue-tree builder** and flag-field editing (both are JSON-authored for now; the `dialogue`/`requires_flag`/`sets_flag` fields work — the inspector just doesn't show them yet). - The **kit-browser villager** has no built-in dialogue yet (the live inn one does). - More theme packs; **title screen / world picker**; **save/load a playthrough**. - Water/trigger control lines are reserved but not yet wired to behaviour. - True-colour ("HD") background layer and polygon fill regions. - **Strudel** live-coded music as a browser sidecar over the HTTP surface. - Pathfinding for click-to-walk (today: greedy steering); cross-room NPC state. --- *MRPGI — built from "let's reimagine AGI" into a complete, AI-assisted, audible adventure-game maker. Have fun making weird little worlds.* 🤖🎸