MRPCI/README.md
m3ultra 0191b4680d v0.3 — AI parser lane + dialogue talker portraits
AI lane (ported from MRPGI): unknown typed sentences go to a local LLM (MRPCI_AI: ollama default / openrouter / off) that maps them onto already-legal commands; one in flight, polled per tick, hard-off under --script so replays stay byte-identical. Portraits: NPCs/props gain a portrait sprite drawn beside the dialogue window in the GUI (6x) and annotated frames (2x); sergeant + vend-bot faces in the demo. Also: --script + --render-room renders the frame a replay ends on. Verified: 5 test suites green, deterministic 25/25 playthrough, GUI boots.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 00:26:03 +10:00

7.3 KiB
Raw Blame History

MRPCI — Monster Robot Party Creative Interpreter

The SCI generation of the Monster Robot Party engine family. Where MRPGI reimagines Sierra's 1980s AGI (16 colors, text parser, one merged priority buffer), MRPCI reimagines the tech behind King's Quest V and Space Quest IV — and then fixes everything Sierra never could:

Sierra SCI (1990) MRPCI (now)
256-color VGA, hand-cut palettes 256-color palettes quantized live from any PNG (median cut), EGA/gray/ember ranges kept stable for sprites & cycles
Palette cycling (waterfalls, neon) Same trick, cycles are room data + script-toggleable
Priority + control screens Four screens: visual / priority / control / hotspot — hit-testing any pixel is one array read
Polygon avoidance that wedged egos into corners Real A* with LOS-verified edges + string-pulling; actors walk the exact verified line, so a legal path can never clip
Scale tables (SCI1.1) Per-room perspective: actors shrink toward the horizon, walk speed scales to match
CPU-speed timers → Error 52, instant Sequel Police Fixed 30Hz deterministic cycles; after() timers count ticks; the only RNG is seeded xorshift — replays are byte-identical
Error 47: Not an object → crash to DOS Missing resources = placeholders + an error event. A compile-error script = a log line, not a hang
Die 3 hours after the dead-end Checkpoint at every room entry; death rewinds to it. Save-anywhere slots on top
OOP bytecode scripts, priest-tier tooling rhai room scripts: on_enter, on_verb(v,n), on_trigger, after(ticks,"fn") — hot-swappable over the bus
Icon bar (SCI1) or parser (SCI0) Both. Clicks and typed commands converge on one verb pipeline

The architecture is inherited from MRPGI and kept sacred: mrpci-core is headless (zero windowing deps — a compile error is the guardrail). The whole sim is a GameState behind a typed Command/Event bus, and every control surface — GUI, JSONL stdio, HTTP, MCP — is a thin adapter.

Run it

cargo run -p mrpci-core --bin mrpci-headless -- --sample   # write the demo game
cargo run -p mrpci                                         # play Neon Precinct

Neon Precinct: you are Officer Morp-9. Rain, neon that actually cycles, a vend-bot with a tip, a keycard behind crates (watch the A* go around), a lethal fusebox (watch death not ruin your evening), and a case to close. 25 points.

Controls: left-click applies the verb, right-click cycles verbs, F1F4 pick one, I inventory, Enter types a command (the parser is always alive), F5/F7 save/restore, F9 new game, M mute, N scanlines.

Drive it headless (the point)

cargo build -p mrpci-core
target/debug/mrpci-headless --game games/neon-precinct              # JSONL stdio
target/debug/mrpci-headless --game games/neon-precinct --serve 8093 # HTTP
target/debug/mrpci-headless --game games/neon-precinct --mcp        # MCP for Claude
target/debug/mrpci-headless --game games/neon-precinct --script play.jsonl  # golden replay
target/debug/mrpci-headless --game games/neon-precinct --room 2 --ticks 45 --render-room out.png
target/debug/mrpci-headless --game games/neon-precinct --screens shots/  # all four screens

Register with Claude:

claude mcp add mrpci -- $PWD/target/debug/mrpci-headless --mcp --game $PWD/games/neon-precinct

Claude can then play the game (verbs, walks, dialogue), see it (mrpci_render_frame, plus the invisible priority/control/hotspot screens), and author it (upsert rooms and rhai scripts live, validated before commit). See docs/CONTROL.md for the full bus reference.

A game is a folder

games/mygame/
  game.json          # manifest: name, start_room, intro, verbs, flags, max_score
  rooms/room0.json   # RoomDoc: ops (paint), background, palette, cycles, scale,
                     #   spawn, exits, hotspots, props, npcs, music, script
  pics/street.png    # optional backgrounds (+ street-pri.png / street-ctl.png masks)
  sprites/*.png      # quantized per-room; filename = sprite name
  scripts/*.rhai     # main.rhai + room scripts
  sfx/ music/        # optional audio overrides (else the built-in chip synth plays)
  saves/             # save-anywhere slots (gitignored)

Rooms paint with PicOps — rects, polygons, floods, dithered gradients, plus procedural fills: fBm noise (clouds, asphalt, grime), Voronoi cells (cobbles, slabs) and scatter (stars, glints) — all seeded, all deterministic — through an Ink that writes any subset of the four screens at once. Or drop a PNG in pics/ and let the quantizer fold it into the palette. Rooms can also set weather (rain / snow / embers): a particle layer on its own RNG stream, so visuals never perturb gameplay replays.

Source map

Crate / file Role
mrpci-core/screens.rs the four aligned screens + depth bands
mrpci-core/palette.rs 256-color palettes, cycling LUTs
mrpci-core/pic.rs vector paint ops, Bayer-dithered gradients
mrpci-core/assets.rs median-cut quantizer, masks, sprite pipeline
mrpci-core/view.rs loops/cels, ASCII sprites, mirroring
mrpci-core/actor.rs ego + NPCs: scaling, line-exact path following
mrpci-core/path.rs A*, LOS smoothing, walk_line
mrpci-core/room.rs RoomDoc / World / game folders / validation
mrpci-core/script.rs rhai host: hooks, Fx airlock, tick timers
mrpci-core/state.rs the bus: GameState, Command/Event, checkpoints
mrpci-core/render.rs headless compositing → RGBA/PNG
mrpci-core/audio.rs multi-voice chip synth (square/pulse/tri/noise)
mrpci-core/bin/mrpci-headless/ stdio / HTTP / MCP / replay / sample
mrpci/ the macroquad GUI (icon bar, dialogue windows, sound)

Headless frames are annotated: --render-room, HTTP /frame.png and MCP mrpci_render_frame stamp the room name, score, open dialogue window and transcript strip into the frame with the built-in 5x7 font — an LLM sees exactly what a player reads (add --raw / /frame-raw.png to skip). The GUI renders via a GPU palette shader: the frame ships to the card as indices + a 256x1 palette strip, and the fragment shader does the lookup plus the whole CRT (curvature, scanlines, vignette, room fades).

The AI parser lane

When the deterministic parser shrugs at a typed sentence, a small local LLM (Ollama by default; OpenRouter optional) translates it into ONE command from the already-legal verb/noun tables — then that command runs through the real game logic. The AI can suggest; only the sim decides. Configure with MRPCI_AI (ollama/openrouter/off), MRPCI_AI_MODEL, MRPCI_AI_URL. --script replays force the lane off, so golden tests stay byte-identical.

Roadmap

  • v0.1 — the engine above + Neon Precinct
  • v0.2 — procedural fills (fBm/Voronoi/scatter), weather particles, in-core font + annotated frames, GPU palette/CRT shader
  • v0.3 — world bundles carry art (--export-bundle/--bundle, the wasm path), AI parser lane, dialogue talker portraits
  • Priority-mask art workflow polish (paint depth in any image editor)
  • In-engine room editor (MRPGI's, upgraded to four screens)
  • wasm build → see the MRP3GI sibling (three.js + rigged GLBs over this core)