Bugs found by playing the game over the bus: - hotspots now have positions: 'walk to precinct door' pathfinds there, and touch verbs walk over to hotspots like they do to props/NPCs - GameState::settle(): the MCP surface resolves walk-then-act in one call instead of returning zero events on a distant verb - typed 'use X on Y' walks over like a clicked use (was unlimited range) - taking/deleting a solid prop rebakes — no more lingering invisible walls - sergeant dialogue no longer loops back to its greeting - serde-facing maps are BTreeMap: room JSON and --sample are byte-stable Engine: - sprite-sheet actor views: <name>-sheet<C>x<R>.png slices into C frames x R direction loops (vend-bot now rolls on animated treads) - pixel-accurate click targeting with 1px slop; typed commands click mid-sprite (a feet click lands between an actor's legs) - parser: compass walking (go east / n), 'bye' ends conversations, 'look' lists exits GUI: - hover hot-text: cursor reads the sentence a click would say - death banner + '+N' score toast Tests: full-playthrough regression suite (win path, death rewind, walk-over dialogue, solid-prop footprint) + sheet slicing unit test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
52 lines
2.4 KiB
Markdown
52 lines
2.4 KiB
Markdown
# MRPCI — working notes for Claude
|
|
|
|
SCI-generation adventure engine (sibling of MRPGI). Rust workspace:
|
|
`mrpci-core` (headless sim — **must never depend on macroquad**; that's the
|
|
architectural guardrail) and `mrpci` (the macroquad GUI, a thin bus client).
|
|
|
|
## Build / test / run
|
|
|
|
```sh
|
|
cargo build --workspace
|
|
cargo test --workspace # includes full-playthrough regression tests
|
|
cargo run -p mrpci # play Neon Precinct in a window
|
|
target/debug/mrpci-headless --game games/neon-precinct --render-room out.png
|
|
```
|
|
|
|
## Invariants — do not break
|
|
|
|
- **Everything goes through the bus.** All mutation is a `Command` on
|
|
`GameState::apply`; all output is `Event`s. GUI, stdio, HTTP, MCP and the
|
|
in-engine editor are thin adapters with zero private powers.
|
|
- **Determinism.** Fixed 30Hz cycles; timers count ticks; the only RNG is
|
|
the seeded xorshift in `ScriptCtx`. `--script` replays must stay
|
|
byte-identical (the AI parser lane is force-disabled there). Weather
|
|
particles run a separate RNG stream on purpose.
|
|
- **Deterministic serialization.** Serde-facing maps are `BTreeMap` so room
|
|
JSON/bundles are diffable and `--sample` output is byte-stable.
|
|
- **Scripts can't corrupt the sim.** rhai reads a `ScriptCtx` snapshot,
|
|
writes queue as `Fx` — keep that airlock.
|
|
- **Missing resources degrade, never crash** (placeholders + `error` event).
|
|
|
|
## Gotchas
|
|
|
|
- `games/neon-precinct/` is **generated** by `mrpci-headless --sample`
|
|
(source: `mrpci-core/src/bin/mrpci-headless/sample.rs`). Edit the
|
|
generator, then regenerate — don't hand-edit the JSON.
|
|
- Distant verbs queue a walk-then-act (`pending_verb`); real-time surfaces
|
|
resolve it on later ticks, the MCP adapter calls `GameState::settle()`.
|
|
Raw stdio/HTTP callers must send `tick`.
|
|
- Sprites named `<base>-sheet<C>x<R>.png` are sliced into animated actor
|
|
views (rows: front/back/left/right, right falls back to mirrored left).
|
|
Sheets are for egos/NPCs; props/portraits use plain single-cel sprites.
|
|
- Solid props stamp CTL_BLOCK footprints; anything that can remove one must
|
|
`rebake()`, not just re-stamp (else invisible walls linger).
|
|
- Hit-testing is pixel-accurate with 1px slop (`cel_hit`); typed commands
|
|
"click" mid-sprite via `target_click_pos` (a feet-point click lands
|
|
between an actor's legs).
|
|
|
|
## Docs
|
|
|
|
`README.md` (architecture + game-folder format), `docs/CONTROL.md` (bus
|
|
reference: every Command, all four surfaces), `docs/EDITOR.md` (F8 editor).
|