Headless core (mrpci-core) + macroquad GUI (mrpci), inheriting MRPGI's Command/Event bus architecture and jumping a Sierra generation: - 256-color palettes with live median-cut quantization + palette cycling - four screens: visual / priority / control / hotspot - A* pathfinding with LOS-verified edges and line-exact path following - perspective scale tables (actors shrink toward the horizon) - point-and-click verb bar AND a text parser, one shared verb pipeline - rhai room scripts (on_enter/on_verb/on_trigger + after() tick timers) - deterministic 30Hz cycles, seeded RNG — byte-identical script replays - checkpoint at room entry; death rewinds instead of restarting - save-anywhere slots; multi-voice chip synth; JSONL/HTTP/MCP surfaces - demo game: Neon Precinct (3 rooms, 25 points, one merciful fusebox) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
110 lines
5.9 KiB
Markdown
110 lines
5.9 KiB
Markdown
# MRPCI — Monster Robot Party Creative Interpreter
|
||
|
||
The **SCI generation** of the Monster Robot Party engine family. Where
|
||
[MRPGI](../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
|
||
|
||
```sh
|
||
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, F1–F4 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)
|
||
|
||
```sh
|
||
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:
|
||
|
||
```sh
|
||
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](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 `PicOp`s — rects, polygons, floods, **dithered gradients** —
|
||
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.
|
||
|
||
## 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) |
|
||
|
||
## Roadmap
|
||
|
||
- [x] v0.1 — the engine above + Neon Precinct
|
||
- [ ] Priority-mask art workflow polish (paint depth in any image editor)
|
||
- [ ] In-engine room editor (MRPGI's, upgraded to four screens)
|
||
- [ ] AI parser lane (LLM maps free text onto already-legal commands, like MRPGI)
|
||
- [ ] Portraits/talkers in dialogue windows
|
||
- [ ] wasm build (`mrpci-core` is already windowless — the web is an adapter away)
|