From cc6f06ed2a623b8bdde8977dcacbd6ca9f26ab1d Mon Sep 17 00:00:00 2001 From: flybrain Date: Wed, 23 Sep 2026 07:25:19 +0000 Subject: [PATCH] a refusal that teaches the ledger something is not held against the tile Measured with the real brain on the seeded pocket: it pressed GO ROUTE first, while the gym's door was still the second tier's answer. That refusal wrote the door to the blocked ledger and also withheld GO ROUTE on the tile, so the next deal -- the last resort, whose walk now goes where it can -- was never made, and the fly waited out the window. Only a last resort deals goals the ledger is already resting, so the refusal worth remembering where the fly stands is the one that taught the ledger nothing new. A refusal that writes a new exclusion changes the next deal by itself. --- .../src/pokemon_red/macros/executor.rs | 11 +++++++- .../src/pokemon_red/macros/tests.rs | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) 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 1d320a2..1c3667f 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 @@ -716,6 +716,13 @@ impl MacroMachine { // all" -- and the route search is the real one, so a bound macro can refuse `no route` // once per hold for ever while the candidate list never changes. Recording what it // could not reach is what empties the list and takes the button off the pad. + // Row 57: a refusal that teaches the blocked ledger nothing new -- every goal it could + // not reach is already resting there -- is one the dealer will deal again unchanged, + // because only a last resort deals goals the ledger is resting. That refusal is the + // one remembered where the fly stands. A refusal that writes a new exclusion changes + // the next deal by itself and is not held against the tile: the next deal may be the + // last resort, whose own walk can go where this one could not. + let taught = unreachable.iter().any(|key| !state.blocked(*key)); if let Some(map) = state.player().map(|player| player.map) { self.blocked.extend(unreachable.into_iter().map(|key| (map, key))); // And for the frontier, the same fact one level up: every tile of this map the @@ -726,7 +733,9 @@ impl MacroMachine { self.exhausted = Some(map); } } - refused_here(self); + if !taught { + refused_here(self); + } return refuse(self, Refusal::NoRoute); }; // The map the target was chosen on, so an entry cannot be read back on another map. 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 5fe1580..5aee4e0 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 @@ -4979,6 +4979,32 @@ fn a_last_resort_that_cannot_reach_the_objectives_door_takes_a_way_out_it_can_re "south, toward the way out on this side of the fence: {:?}", world.player ); + + // The order the real brain pressed them in, measured on the seeded pocket: `GO ROUTE` first, + // while the door is still the second tier's answer rather than the last resort's. That refusal + // teaches the ledger the door, so it is not held against the tile -- the next deal is the last + // resort, and its walk goes where the first could not. + let mut world = fenced_in_pewter(); + world.connections = Connections { north: false, south: true, east: false, west: false }; + world.seen_maps.insert(maps::ROUTE_2); + world.targets.record_blocked(world.map, south); + world.exhausted.insert(world.map); + world.objective = Some(Objective { + map: maps::PEWTER_GYM, + tile: None, + warp: None, + edge: None, + target: Some(PlaceKind::Person), + }); + assert_eq!( + run(&mut world, MacroKind::GoRoute).map_err(|refused| refused.reason), + Err(Refusal::NoRoute), + "the door, through the second tier, beyond the fence" + ); + assert!(on_the_pad(&mut world, MacroKind::GoRoute), "a refusal that taught the ledger is not held"); + let started_at = world.player; + assert!(run(&mut world, MacroKind::GoRoute).is_ok(), "the last resort walks where it can"); + assert!(world.player.y > started_at.y, "{:?}", world.player); } #[test]