From 552428a7be20bb87567628ffd7655b6520cf6da2 Mon Sep 17 00:00:00 2001 From: acamilo Date: Wed, 23 Sep 2026 09:46:04 +0000 Subject: [PATCH] survey: the route probe reads the room on the fly's Nth arrival on a map FLY_PROBE_CATCH_MAP and FLY_PROBE_CATCH_ENTRIES stop the route survey forty frames after the fly's Nth arrival on a map (the first frames on a new map byte still carry the old map's warps), and the dump lists every person the macros can see with its talked, blocked and reached entries. Row 58's pad was one door in and one door out, and what it needed read was the room on the far side of the door. --- .../crates/flysim/examples/scene_probe.rs | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/services/flysim/crates/flysim/examples/scene_probe.rs b/services/flysim/crates/flysim/examples/scene_probe.rs index 5f83667..717001a 100644 --- a/services/flysim/crates/flysim/examples/scene_probe.rs +++ b/services/flysim/crates/flysim/examples/scene_probe.rs @@ -1379,6 +1379,14 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64) let mut outcomes: BTreeMap = BTreeMap::new(); let mut single_refusals = 0u32; let mut caught_at: Option = None; + // `FLY_PROBE_CATCH_MAP=54` with `FLY_PROBE_CATCH_ENTRIES=4` reads the frame the fly is given + // the buttons back on its fourth arrival on map 54 (row 58: the pad in and out of one door). + let catch_map: Option = + std::env::var("FLY_PROBE_CATCH_MAP").ok().and_then(|value| value.parse().ok()); + let catch_entries = env_usize("FLY_PROBE_CATCH_ENTRIES", 4); + let mut entries = 0usize; + let mut arrived_at = 0usize; + let mut last_map: Option = None; // `FLY_PROBE_HOLD=right:96,up:32` holds raw directions first and prints where the fly is // every eight frames: what the cartridge does with a press, before any macro is asked. @@ -1502,6 +1510,25 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64) caught_at = Some(frame); break; } + if let (Some(want), Some(player)) = (catch_map, player) { + if player.map == want && last_map != Some(want) { + entries += 1; + arrived_at = frame; + } + last_map = Some(player.map); + // Forty frames in: the first frames on a new map byte still carry the old map's + // warps (the tear 12.16 names), and a reading there says nothing about the room. + if player.map == want + && entries >= catch_entries + && frame >= arrived_at + 40 + && !running + && matches!(observed.scene, flybrain_gb::SceneId::Overworld) + && !observed.bindings.is_empty() + { + caught_at = Some(frame); + break; + } + } } println!("```\n"); println!("- refusals: {refusals:?}"); @@ -1512,8 +1539,13 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64) return; }; println!( - "\n## Caught on frame {frame} ({:.1} brain minutes): one button, refused twenty holds running\n", - frame as f64 * MS_PER_FRAME / 60_000.0 + "\n## Caught on frame {frame} ({:.1} brain minutes): {}\n", + frame as f64 * MS_PER_FRAME / 60_000.0, + if single_refusals >= catch_after { + "one button, refused twenty holds running".to_string() + } else { + format!("arrival {entries} on map {catch_map:?}") + } ); let (pushed, frontiers) = macros.fences(); println!("- pushed tiles (no window): {pushed:?}"); @@ -1525,6 +1557,16 @@ fn route_survey(gb: &mut Emulator, adapter: &mut PokemonRedReward, ms: &mut f64) println!("- objective: {:?}", state.objective()); println!("- `objective_goals`: {:?}", palette::objective_goals(state)); println!("- `objective_targets`: {:?}", palette::objective_targets(state)); + for (tile, target) in path::person_targets(state) { + println!( + " - person {target:?} at ({:2},{:2}): talked {}, blocked {}, reached {}", + tile.x, + tile.y, + state.talked(target), + state.blocked(TargetKey::Thing(target)), + state.reached(TargetKey::Thing(target)) + ); + } println!("- `untalked_people`: {:?}", palette::untalked_people(state)); println!("- `untalked_objects`: {:?}", palette::untalked_objects(state)); println!("- `facing_untalked`: {}", palette::facing_untalked(state));