MRPCI/mrpci-core/tests/walk.rs
m3ultra c83c90711d MRPCI v0.1 — the SCI-generation Monster Robot Party engine
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>
2026-07-25 22:52:39 +10:00

45 lines
1.5 KiB
Rust

//! Golden-path integration tests against the generated demo game.
//! (Run `mrpci-headless --sample` first; CI does.)
use mrpci_core::path::{find_path, nearest_open, Passable};
use mrpci_core::{Command, GameState, World};
fn game_dir() -> Option<String> {
for p in ["games/neon-precinct", "../games/neon-precinct"] {
if std::path::Path::new(p).join("game.json").exists() {
return Some(p.to_string());
}
}
None
}
#[test]
fn ego_can_cross_neon_row() {
let Some(dir) = game_dir() else {
eprintln!("demo game not generated; skipping");
return;
};
let world = World::load_game(dir);
let mut gs = GameState::new(world);
gs.apply(Command::NewGame { room: None });
let p = Passable {
s: &gs.world.screens,
half_w: 8,
water_ok: false,
min: (4, 8),
max: (316, 188),
};
let start = (gs.ego.x, gs.ego.y);
eprintln!("start {:?} open={:?}", start, nearest_open(&p, start));
eprintln!("goal open={:?}", nearest_open(&p, (316, 150)));
let path = find_path(&p, start, (316, 150));
eprintln!("path: {:?}", path);
assert!(!path.is_empty(), "no path across Neon Row");
let evs = gs.apply(Command::WalkTo { x: 316, y: 150 });
let moved = format!("{:?}", (gs.ego.x, gs.ego.y, gs.world.current));
eprintln!("after walk: {} events={}", moved, evs.len());
assert_eq!(gs.world.current, 2, "edge exit east should reach Rain Alley (ego at {})", moved);
}