1# Chapter 18: patches, every change we made to the bot 2 3These are the only changes to the bot's own code. Each one is a small diff 4of an upstream file, applied at build time (chapter 17), with a comment in 5the patched code that starts `Carried patch (jev):`. Each exists because the 6host (chapter 4) could not fix the problem from outside: the bad decision is 7made and acted on inside one `ap_tick`, or sits in one of upstream's static 8tables, or between two statements of a `static` function. 9 10Read in order, they are a fairly good story of what it takes to get from 11Link's bed to the Pegasus Boots: 12 13```mermaid 14flowchart TD 15 bed["Link's house"] -->|"0001: stop walking back down the stairs"| sword["the sword, from uncle"] 16 sword --> ep["Eastern Palace"] 17 ep -->|"0003: the anti-fairy circle is not an enemy to walk into"| bk["the big key ($B8)"] 18 bk -->|"0013: a big chest needs its big key"| bow["the bow, from the big chest"] 19 bow -->|"0004: let the bow shot through"| armos["the Armos Knights"] 20 armos --> pendant["the Pendant of Courage"] 21 pendant -->|"0005: the green pendant is bit 0x04"| sahas["Sahasrahla"] 22 sahas -->|"0006, 0007, 0008: walk up, talk until he gives, close the text"| boots["the Pegasus Boots"] 23 boots -->|"0009, 0010, 0031: dash"| book["the Book of Mudora (wired, not yet proven to land)"] 24``` 25 26> **Aside: two of them undo upstream's own last commit.** `bcb2537` (2020-02-06) 27> made two changes that broke things its author's earlier video had done 28> fine. One left the bot walking back down every intra-room staircase it had 29> just climbed (0001); the other cleared the Y button on the very frame the 30> bot pressed it to shoot an arrow, so the Armos Knights never took one 31> (0004). Upstream had killed them a month earlier, before the line existed. 32 33> **Aside: the gap after 0016 is not missing patches.** From 0030 the patches 34> came from a separate line of work (movement and combat), numbered apart so 35> that two streams of patches could not collide on a number. 36 37> **Try it.** `ls` this folder, open any patch, and search the patched file 38> for `Carried patch (jev)`. Then build: `nix develop -c buck2 build 39> //third-party/c:patched` applies all of them, in name order, and fails if 40> any no longer applies. 41 42## For the people who maintain it 43 44### The patches 45 46| Patch | Upstream files | What it changes | Evidence in [research/zbanks-alttp.md](../../../research/zbanks-alttp.md) | 47| --- | --- | --- | --- | 48| [0001](0001-follow-targets-on-intra-room-stairs.patch) | `alttp.c` | `bcb2537`'s early return for `$B0 != 0` also caught intra-room stairs, which count their steps in `$B0`; the bot never consumed the targets it climbed past and walked back down. | "The stairs" | 49| [0002](0002-goal-choice-hook.patch) | `ap_plan.c` | `ap_goal_choose_hook`: a host may make the goal choice. NULL by default, which is upstream exactly. This is where Jev plugs in (chapter 5). | "Jev at the goal choice" | 50| [0003](0003-anti-fairy-circle.patch) | `ap_snes.h`, `ap_map.c`, `ap_plan.c` | Eastern Palace `$B8`: the anti-fairy circle is an invulnerable obstacle, not an enemy to walk into; the room gets a kill-all script in upstream's own table; kill-all no longer gives up the first frame an enemy is out of reach. | "Eastern Palace `$B8`" | 51| [0004](0004-bow-shot-survives-follow-targets.patch) | `ap_map.c` | `ap_follow_targets` no longer clears the Y that kill-all's bow shot just pressed. | "The Armos Knights" | 52| [0005](0005-green-pendant-is-bit-4.patch) | `ap_req.c` | The green pendant is bit `0x04` of `$7EF374`, as the game and the Randomizer test it; upstream's `0x01` is the red one, which left Sahasrahla unsatisfiable. | "Sahasrahla" | 53| [0006](0006-walk-up-to-a-blocking-npc.patch) | `ap_map.c`, `ap_plan.c` | The bot can walk up to a solid talking NPC (Sahasrahla) and away again. Both exemptions are gated on `SPRITE_ATTR_TALK`, after the first version made an unrelated sprite transparent to the pathfinder at the castle passage door. | "The boots", "The castle passage door" | 54| [0007](0007-talk-to-an-npc-until-it-gives.patch) | `ap_plan.c` | A talk lasts until the NPC's text is done and counts only an item actually given, then Link steps off the NPC. | "The boots" | 55| [0008](0008-text-box-gets-a-in-any-state.patch) | `alttp.c` | An open text box always gets A, even while Link is mid-dash. | "The boots" | 56| [0009](0009-pegasus-boots-dash.patch) | `ap_map.c` | A Pegasus Boots dash for `SCRIPT_SEQUENCE`: four new characters (`8`/`2`/`4`/`6`, numpad directions) hold A with a direction, and `ap_follow_targets` no longer clears a dash's A on plain floor. | "The Book of Mudora" | 57| [0010](0010-book-of-mudora-goal.patch) | `ap_map.c`, `ap_plan.c` | A goal for the Library's shelf (room `$0107`), its approach point derived from ROM data, gated on the boots. Proven to attach and gate; not yet proven to land the book. | "The Book of Mudora" | 58| [0011](0011-shopkeeper-blocks-in-room-0123.patch) | `ap_snes.h` | Room `$0123`'s per-room override for sprite `0xBB`/`0x0200` keeps `SPRITE_ATTR_BLKF`, so the pathfinder stops routing through its real hitbox. | "The door D 0x80 stall in room $0123" | 59| [0012](0012-dam-push-block-not-a-hammer-peg.patch) | `ap_map.c` | In the Dam's block-puzzle room (`$010B`), raw tile `0x27` is a push block, not a hammer peg. | "The Dam Chest push block" | 60| [0013](0013-big-chest-needs-the-big-key.patch) | `ap_plan.c` | A big chest's goal is unsatisfiable until its dungeon's big key is held. | "The Eastern Palace big chest" | 61| [0014](0014-door-with-no-vestibule-in-room-0089.patch) | `ap_map.c` | Room `$0089`'s north door has no floor before its transition, so its approach point is the door's own tile. | "A door with no vestibule ($0089)" | 62| [0015](0015-never-push-a-block-into-a-wall.patch) | `ap_map.c` | General: a push that jams (`push_timer` running, Link not moving) marks that cell a wall for the rest of the room visit. | "Never push a block into a wall" | 63| [0016](0016-hc-routines-already-done-in-open-mode.patch) | `ap_plan.c` | Hyrule Castle routines are done in open mode; any routine whose screen's chests are all open is complete. | "A routine already done, or already claimed, is never offered again" | 64| [0030](0030-hammer-peg-indoors-general.patch) | `ap_map.c` | General form of 0012: indoors, raw tile `0x27` is never a hammer peg, by the game's own rule. | "The hammer swings at bare floor" | 65| [0031](0031-dash-as-path-action.patch) | `ap_snes.h`, `ap_map.c` | With the boots, a path may cross bonk rocks (tile `0x57`), and the step onto one is a dash. | not yet written up there | 66| [0032](0032-glove-gating-general.patch) | `ap_plan.c` | The glove a liftable needs comes from its tile's own `LFT1`/`LFT2` bits, not one hard-coded tile id. | not yet written up there | 67 68`CLAUDE.md` beside this has each patch's full account: the run, the frame, 69the measurement, and why no host fix could do it. 70 71| Path | What | 72| --- | --- | 73| `NNNN-*.patch` | The patches, applied in name order by `//third-party/c:patched`. | 74| [README.md](README.md) | This chapter. | 75| [CLAUDE.md](CLAUDE.md) | Every patch's evidence, and the open bugs that are not patches yet. | 76 77← Previous: [Chapter 17, c/](../) · Up: [c](../) · Next: [Chapter 19, rust/](../../rust/) →