//! 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 { 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); }