diff --git a/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/executor.rs b/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/executor.rs index 4d90f58..90d7309 100644 --- a/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/executor.rs +++ b/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/executor.rs @@ -1088,8 +1088,20 @@ impl MacroMachine { // say (row 37 of `infra/docs/macros-traps.md`). The fly may already have been // walked a tile by the script, so the tile the macro set out from is the honest // answer when there is one and the current tile otherwise. + // + // **Except for a walk** (row 57). A walk set out from wherever the last one left + // the fly, and the script fired on the tile the walk had *reached*: Pewter City's + // youngster takes the joypad on four tiles by the road east, and a `GO ROUTE` that + // set out from the town's south entrance twenty-six tiles away walled the south + // entrance -- with no window, in the middle of the town. A dozen of those fenced + // the fly into a pocket no walk could leave. The tile a walk last stood the fly on + // is its own record of where the cartridge took over. if let Some(player) = at { - let tile = active.from.unwrap_or(Tile::new(player.x, player.y)); + let current = Tile::new(player.x, player.y); + let tile = match active.plan.front() { + Some(Step::Walk(walk)) => walk.expect.unwrap_or(current), + _ => active.from.unwrap_or(current), + }; self.pushed_tile = Some((player.map, tile)); } } diff --git a/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/tests.rs b/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/tests.rs index 72aa2a6..6688280 100644 --- a/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/tests.rs +++ b/services/flysim/crates/flybrain-gb/src/pokemon_red/macros/tests.rs @@ -4873,6 +4873,32 @@ fn a_tile_the_cartridge_pushes_the_fly_off_is_not_a_tile_to_walk_to() { ); } +// --------------------------------------------------------------------------------------------- +// Row 57: an escorted walk, and where it was escorted from +// --------------------------------------------------------------------------------------------- + +#[test] +fn an_escorted_walk_walls_the_tile_it_reached_not_the_one_it_set_out_from() { + // Row 57's other half. Pewter City's youngster takes the joypad on four tiles by the road + // east and walks the fly to the gym. A `GO ROUTE` that set out from the town's south entrance + // and reached one of those tiles wrote the *south entrance* into the pushed ledger -- a wall + // with no window, twenty-six tiles from where the script fired -- and a dozen of those fenced + // the fly into a pocket. The tile the walk had reached is where the cartridge took over. + let mut world = World::room().at(3, 6); + world.map = maps::PEWTER_CITY; + world.connections = Connections { north: true, south: false, east: false, west: false }; + // Three tiles walked north, then the script: the scene changes with the game driving the fly. + world.scripted_at = Some(52); + world.switch = Some((52, Scene::Dialog)); + + let mut machine = MacroMachine::new(1); + let _ = run_with(&mut machine, &mut world, MacroKind::GoRoute); + let (map, tile) = machine.take_pushed().expect("the script moved the fly: a push-back"); + assert_eq!(map, maps::PEWTER_CITY); + assert_ne!(tile, Tile::new(3, 6), "not the tile the walk set out from"); + assert_eq!(tile, world.player, "the tile the walk had reached when the script took over"); +} + /// The push-back writes the ledger, and it writes the *tile* rather than the target. #[test] fn a_scripted_push_back_records_the_tile_it_happened_on() {