MRPGI/EDITOR_GUIDE.md
type-two d0caf983a0 Initial commit: MRPGI — Apple-Silicon AGI adventure engine
A new-school reimagining of Sierra's 1980s AGI interpreter in Rust + macroquad:

- Dual-buffer (visual + priority) room model with hand-painted walkability
- In-engine room editor: brush/line/rect/fill/pick/erase/oval/image/spawn/object tools
- Sprite pipeline (PNG -> EGA quantize), multi-room worlds with edge exits
- Objects with look/use/needs/keys/win conditions (no code)
- Forgiving text parser + optional local-LLM lane (Ollama / OpenRouter)
- Branching NPC dialogue trees, chiptune SFX, per-room ambient music
- Content kit: 61 archetypes across fantasy/scifi/monsters/saucy/horror
- Full docs: README, EDITOR_GUIDE, MANUAL, art manifesto + Gemini prompts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 17:26:55 +10:00

13 KiB
Raw Permalink Blame History

MRPGI room editor — the dummy's guide

You draw a room, tag what's walkable, press a key, and walk around it. That's it.

Run it

cargo run

It opens in EDIT mode. Press Tab any time to flip between edit (draw) and play (walk). Esc quits.

The one rule (read this twice)

Every spot on the screen has two properties, and you set them separately:

  • LOOK = the colour (what you see). You pick it from the palette.
  • MEANING = what it is to the game (walkable? a wall?). You pick it from the meaning tags.

So a brown floor and a brown wall look identical but behave differently — because colour is just looks; the tag is the meaning. When you fill or draw a region, it gets both: the current colour and the current meaning tag.

Meaning tags:

  • floor — walkable (the robot can stand here). Default.
  • wall — blocked (the robot can't enter).
  • water / trigger — special (reserved for later).
  • none — paint colour only, don't change walkability.

Make your first room (the classic 3-band road)

  1. Press Tab until the panel says you're editing (you start here).
  2. Click the fill tool (or press 4).
  3. Click blue in the palette, click the wall tag, then click the top third → blue sky that blocks.
  4. Click green, keep wall, click the bottom third → green ground that blocks.
  5. Click brown, click the floor tag, click the middle band → a brown road that's walkable.
  6. Press Tab → you're now playing. Use the arrow keys — the robot can only walk the road. 🎉

Tip: tap L to cycle the viewboth tints walls red so you can see what's walkable vs blocked. look shows the plain picture; ctrl shows the meaning map.

Tools

Tool Key What it does
brush 1 freehand paint (colour + meaning)
line 2 click points; right-click or Enter to finish the line
rect 3 drag a filled box
fill 4 flood-fill a sealed area (the bucket)
pick 5 eyedropper — grab a colour off the canvas
erase 6 rub back to blank + walkable
image 7 stamp a sprite from sprites/ ([ ] choose, R reload)
oval 8 drag a filled ellipse
spawn 9 click to set where the robot appears in play
object 0 stamp a kit archetype ([ ] picks from 60+) or a blank object; click again to select

Brush/eraser size: , smaller, . bigger. The fill bucket (4) is your fast filler — outline a shape with lines, then click inside it.

Sealed areas: fill only stays inside lines that fully enclose a space. If a fill suddenly floods the whole screen, your outline has a gap — undo and close it. The status line warns you (LEAK?).

Keys

  • Tab edit ⇄ play · Esc quit
  • 10 tools · L cycle view
  • [ ] choose sprite · , . brush size · R reload sprites
  • - = previous / next room (the top strip has < > too)
  • Z or Backspace undo · C clear room · K save · O load
  • In play: arrows / click to walk · type a command + Enter (try talk <npc>) · in a conversation press 16 to choose, Esc to leave · F1 CRT · F2 sound

Saving

K saves to rooms/room.json (the editable list of your strokes, not flat pixels — so it stays re-openable and tiny). The game auto-loads that file on startup, and O reloads it. The cyan circle on the canvas is where the robot spawns in play.


Bring your own pixel art (Aseprite / Inkscape)

The dream loop: draw a thing → drop the PNG in sprites/ → press R → place it with the image tool (7).

The spec (what a sprite PNG should be)

  • Format: PNG with transparency (alpha). Transparent pixels stay see-through in game; a sprite with no transparency acts like a solid tile.
  • Size = game size. The room is 160×168 "fat" pixels — draw small, at 1:1. Rough guide: a person ≈ 1220 px tall, a crate ≈ 24 px, a door ≈ 30×50. A 500 px sprite will fill the whole screen.
  • Colours: ideally the MRPGI EGA 16 — load palettes/mrpgi-ega.gpl into your tool. Off-palette art still works; it's auto-snapped to the nearest EGA colour on load.
  • Name = id. Lowercase, no spaces: crate.png, barrel.png, becky.png. The filename (minus .png) is what shows in the sprite tray.
  • Where: the sprites/ folder. (Starter crate / barrel / sign are already there — replace them or add your own.)

Aseprite (pixel art)

  1. Load the palette: Palette panel → ☰ menu → Load Palettepalettes/mrpgi-ega.gpl. Now you're painting in the exact game colours. (Bonus: Sprite → Color Mode → Indexed = pixel-perfect, zero quantization.)
  2. New sprite, small (e.g. 24×24), transparent background.
  3. Draw. Leave everything that isn't the object transparent.
  4. Export: File → Export Sprite Sheet or just Save As a .png into sprites/.
  5. In MRPGI: press R, tool 7, [ ] to your sprite, click to place.

Inkscape (vector → pixel)

  1. Draw your art. File → Document Properties → set a small px canvas (e.g. 24×24).
  2. Export: File → Export → Page tab, set width/height in px, transparent background → export PNG into sprites/.
  3. Same place step in MRPGI (R, 7, place).

How a placed sprite behaves

The image tool stamps the sprite into the room picture and applies your current meaning tag underneath it. So:

  • want a solid crate? pick the wall tag before you stamp → you can't walk through it.
  • want a walk-over rug? pick floor (or none to leave walkability alone).

It's baked into the room and saved in room.json. (A live object — a movable entity with a name + verbs for items/NPCs — is the next slice; just ask.)

One quirk: fat pixels

Game pixels are twice as wide as tall (classic AGI). A perfect circle in Aseprite shows up slightly wide in game. Ignore it early — it's part of the retro look.


Build a world (multiple rooms)

One room is a screen. A world is rooms linked by their edges.

  • The top strip shows room N with < > to move between rooms (also keys - / =). Going > past the last room makes a fresh blank one. Switching rooms auto-saves the one you're leaving.
  • Each room saves to its own file: rooms/room0.json, rooms/room1.json, …
  • Exits (top strip): the N E S W buttons. Click one to cycle its target room number (N:-N:0N:1 … → off). So E:1 means "walk off the right edge → arrive in room 1".
  • Set the entrance with the spawn tool (9): click where the robot should appear. The cyan circle shows it.

Make two linked rooms

  1. In room 0, leave a walkable gap at the right edge (don't wall it). Set exit E:1.
  2. Press > to go to room 1, draw it, leave a walkable gap on its left edge, set exit W:0.
  3. Press < back to room 0, press Tab to play, walk off the right edge → you're in room 1. Walk back left → room 0. You built a world. 🌍

Tip: if the robot seems stuck after a transition, the edge it arrived at was walled — leave a floor gap there (it otherwise falls back to that room's spawn point).


Objects you can talk to (the parser)

This is where it becomes a game. The object tool (0) places a sprite as a real thing — and in play you can type at it.

Place an object

  1. Tool 0 (object). Press [ ] to flip through the kit — 60+ ready-made archetypes (orc, console, cocktail, coffin, sword, spellbook…), shown in the panel as kit [ ]: <name>. Click the canvas to stamp the selected one — fully written (look/use/needs/wins/synonyms all filled in). Cycle to (blank) to instead drop a bare object named after the current sprite.
  2. Click an object to select it. The inspector has editable fields — name, look text, use text, needs item, synonyms — plus takeable / wins toggles and delete.
  3. To write its description: click the look text field, type your line (a caret shows), press Enter to jump to the next field. Click the canvas or press Esc to finish typing.
  4. K saves it with the room.

Talk to it (in play)

Press Tab to play. There's a > command line at the bottom — type and hit Enter:

  • look barrel → its description
  • take key → into your inventory (if it's takeable)
  • inventory (or i) → what you're carrying
  • look around → everything in the room
  • help → the verb list

Arrows still walk while you type. The parser is forgiving now: it ignores filler words ("the", "a", "at") and knows verb synonyms — look = examine = x = check = inspect; take = get = grab = pick. And the synonyms field lets an object answer to other nouns: put box wood cargo on a crate and examine the box just works.

Try it

  1. Edit: tool 0, drop a crate and a barrel, press K.
  2. Tab to play → type look around, then look crate, then take barrel, then inventory. The game answers you. 🤖💬

Make a puzzle (locks, keys, winning)

Objects can now do things — no code, just fields. Each object's inspector has:

  • use text — what use <it> / open <it> prints.
  • needs item — an item it requires. Empty = no lock. If set, use only works when that item is in your inventory; otherwise it says "It's locked. You need: key."
  • wins toggle — using it successfully wins the game (a YOU WIN banner).

A complete 30-second game

  1. Drop a sprite, select it, set name = key, takeable = on. (That's your key.)
  2. Drop another, set name = gate, use text = "The gate groans open. You're free!", needs item = key, wins = yes.
  3. K to save, Tab to play.
  4. Type use gate"It's locked. You need: key."
  5. take key, then use gate → your line prints + ★ YOU WIN ★ 🏆

use also accepts open, unlock, push, pull, turn. Keys, locks, and a win condition — a real puzzle, authored entirely with fields.


Natural language (the local AI lane)

When the parser doesn't recognise your verb, it quietly asks a local LLM to translate your sentence into one real command — then runs THAT through the normal game logic. The AI bends the language; your game still decides what's possible. It can't invent items or outcomes. It runs on a background thread (the game never freezes) and shows what it decided, e.g. (≈ open crate).

It's already set up on your Mac

Ollama is running with your Gemma models. Because your models have custom names, point the engine at one when you launch:

./run.sh
# (which is just:  MRPGI_AI_MODEL="hf.co/OBLITERATUS/gemma-4-E4B-it-OBLITERATED:latest" cargo run )

Then in play, with a gate / key / crate around, try:

  • pry the lid off the box(≈ open crate)
  • yank the gate open(≈ use gate)
  • grab that shiny thing(≈ take key)

The bottom bar shows ai: ollama/<model> so you know it's wired.

Settings (env vars)

Var Default Meaning
MRPGI_AI ollama ollama · openrouter · off
MRPGI_AI_MODEL gemma3:4b 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

OpenRouter instead of local:

MRPGI_AI=openrouter OPENROUTER_API_KEY=sk-... MRPGI_AI_MODEL=google/gemma-2-9b-it:free cargo run

If Ollama isn't running or the model's missing, the AI lane just stays quiet and you get the normal "I don't understand" — nothing breaks.


Talk & tunes (NPCs + ambient music)

Talk to NPCs

An object can carry a branching dialogue tree. In play, talk <name> (or speak / ask / chat / greet) starts a conversation: the NPC speaks, and you pick a reply by pressing its number key (16). Choices branch to other lines; some end the chat. Esc leaves early. Walking pauses while you talk.

Try it: in the fantasy world, head south from the forest to the inn and type talk barkeep — there are a few branches to explore.

Authoring is JSON for now: a dialogue array on the object (see the inn villager in rooms/room3.json). Each node has says + choices; each choice has text + goto (a node index, or -1 to end). A visual tree-builder is a future step.

Ambient music

Each room can loop a mood. In the editor, the top strip has a ♪ button — click it to cycle: off · calm · eerie · tense · jolly · spooky. It saves with the room (K) and plays in play mode, switching as you move between rooms. F2 mutes music + SFX together.