-- Gold route: New Bark Town through the Olivine Gym (asm-walk sections 00-09). -- -- Hand-authored from docs/gold-walkthrough/asm-walk/section-NN-*.md. Every row -- carries the section and checklist step it came from in `id`, so a stall names -- a paragraph a human can go read. -- -- Why this is not generated from the markdown. The plan was a converter over -- each section's "## 4. Bot checklist" table, on the botconv principle that the -- docs stay the source of truth. Seven of these ten sections write that -- checklist as free prose ("walk west along y=11..13", "grind to the -- walkthrough's level 8", "avoid the three trainers") rather than the template's -- six-column table, and the Intent column has no controlled vocabulary anywhere -- -- so a parser would have been a prose-guesser wearing a converter's clothes, -- and normalising 300 rows of prose into tables by hand is strictly more work -- than writing the Lua those tables would have produced. The anti-drift job the -- converter was for is done better by tests/gold_route_validate_test.lua, which -- checks every coordinate below against the extracted cache: a warp that is not -- at (6,3), an object that moved, a map that does not exist and an EVENT_* that -- is not a real flag name all fail in seconds, which is more than a markdown -- parser could ever have caught. -- -- Scope: the REQUIRED spine only. Optional pickups, phone numbers, the Ruins of -- Alph, the Bug Contest and the day-of-week NPCs are left out of this first -- pass; each one is a place the bot can stall for no progression benefit. Rows -- marked `optional = true` may fail without failing the run. -- -- Ops: -- travel be on this map, however the map graph gets there -- walk stand on this cell (trip-wires and coord events) -- warp walk onto this warp cell, expect to arrive on `to` -- edge cross this map connection, expect to arrive on `to` -- talk stand adjacent, face it, press A, answer `answers` in order -- battle as `talk`/`walk`, then fight whatever starts -- grind fight wilds here until the party's lowest level reaches `level` -- heal talk to this map's Pokecenter nurse -- teach teach a move from an HM to an eligible party mon -- field use a field move against this cell -- catch hunt this map's wild encounters until one of `species` is caught -- manual not implemented; log it, record it, carry on return { -- ========================================================================= -- Section 00 : the bedroom through the starter -- ========================================================================= -- NEW GAME, InitClock and NamePlayer have no rows here on purpose. A -- POKEPORT_DRIVER run without POKEPORT_BOOT_CINEMA boots straight into the -- world (src/core/Game2.lua:load), so the bot starts already stood -- in the bedroom with none of the three ever on screen. With the cinema on -- they are driven instead by tests/drivers/gold_boot_smoke.lua. { id = "00.5", map = "PLAYERS_HOUSE_2F", op = "warp", x = 7, y = 0, to = "PLAYERS_HOUSE_1F" }, -- MeetMomScript fires on the scene-0 load and runs ~1300 frames of text with -- a yes/no pair inside it. The section's step 6a is explicit that answering -- the DST question is not enough: the confirm loops back to .SetDayOfWeek on -- "no", so both answers have to be yes. { id = "00.6", map = "PLAYERS_HOUSE_1F", op = "settle", answers = { "yes", "yes" }, budget = 4000 }, { id = "00.7", map = "PLAYERS_HOUSE_1F", op = "warp", x = 6, y = 7, to = "NEW_BARK_TOWN" }, { id = "00.9", map = "NEW_BARK_TOWN", op = "warp", x = 6, y = 3, to = "ELMS_LAB" }, -- Scene 0 auto-walks the player to (4,2) and talks; nothing to drive but the -- text. { id = "00.10", map = "ELMS_LAB", op = "settle", budget = 3000 }, -- Starter. Cyndaquil at (6,3): section 09's own battle notes say to bring a -- Fire or Fighting lead for Jasmine, and Fire also answers Bugsy's Scyther in -- section 04. Answers are yes (take it) then no (skip the nickname screen -- -- the naming keyboard has no cancel, only END, so it is far cheaper never to -- open it: src/ui/gen2/NamingScreen.lua:236). { id = "00.11", map = "ELMS_LAB", op = "talk", x = 6, y = 3, answers = { "yes", "no" }, expect = "EVENT_GOT_A_POKEMON_FROM_ELM" }, { id = "00.12", map = "ELMS_LAB", op = "walk", x = 4, y = 8 }, { id = "00.14", map = "ELMS_LAB", op = "warp", x = 4, y = 11, to = "NEW_BARK_TOWN" }, { id = "00.15", map = "NEW_BARK_TOWN", op = "edge", dir = "west", to = "ROUTE_29" }, -- ========================================================================= -- Section 01 : Cherrygrove, Mr Pokemon, the egg, and north to Violet -- ========================================================================= -- The starter is level 5 and Falkner is four maps away. The walkthrough -- grinds Route 29 to 8 before Cherrygrove; do the same, because every later -- gate in this section is a scripted battle we cannot decline. { id = "01.5", map = "ROUTE_29", op = "grind", level = 8 }, { id = "01.6", map = "ROUTE_29", op = "edge", dir = "west", to = "CHERRYGROVE_CITY" }, -- The guide gent's tour is a long follow/stopfollow cutscene. It is not a -- progression gate, but he walks up and starts it unprompted, so it is -- cheaper to run it deliberately than to be ambushed mid-path later. { id = "01.7", map = "CHERRYGROVE_CITY", op = "talk", x = 32, y = 6, answers = { "yes" }, optional = true, budget = 6000 }, { id = "01.8", map = "CHERRYGROVE_CITY", op = "heal", optional = true }, { id = "01.9", map = "CHERRYGROVE_CITY", op = "edge", dir = "up", to = "ROUTE_30" }, { id = "01.12", map = "ROUTE_30", op = "warp", x = 17, y = 5, to = "MR_POKEMONS_HOUSE" }, -- The scene fires on load: egg, Pokedex, the blackout point moves to -- Cherrygrove, and SPECIALCALL_ROBBED is armed. { id = "01.13", map = "MR_POKEMONS_HOUSE", op = "settle", budget = 5000, expect = "EVENT_GOT_MYSTERY_EGG_FROM_MR_POKEMON" }, { id = "01.14", map = "MR_POKEMONS_HOUSE", op = "warp", x = 2, y = 7, to = "ROUTE_30" }, -- Elm's call lands a few overworld steps after leaving; `settle` after the -- travel below picks it up wherever it fires. { id = "01.15", map = "CHERRYGROVE_CITY", op = "travel" }, { id = "01.15b", map = "CHERRYGROVE_CITY", op = "settle", budget = 2000, optional = true }, { id = "01.16", map = "CHERRYGROVE_CITY", op = "battle", x = 33, y = 6, note = "rival scene trip-wire on row 6/7 at x=33" }, { id = "01.18", map = "ELMS_LAB", op = "travel" }, { id = "01.18b", map = "ELMS_LAB", op = "walk", x = 4, y = 5, note = "SCENE_ELMSLAB_MEET_OFFICER trip-wire; CopScript names the rival" }, { id = "01.18c", map = "ELMS_LAB", op = "settle", budget = 4000 }, { id = "01.19", map = "ELMS_LAB", op = "talk", x = 5, y = 2, answers = { "yes" }, expect = "EVENT_GAVE_MYSTERY_EGG_TO_ELM" }, { id = "01.20", map = "ELMS_LAB", op = "walk", x = 4, y = 8, note = "aide's five POKE BALLs" }, -- Route 30's north blockers come down with the egg handed over, so the run -- north to Violet is only now possible. The trainers on the way (Joey, -- Mikey, Don, Wade) are walked into rather than sought: the route is -- geography and the sight lines do the rest. { id = "01.25", map = "ROUTE_30", op = "travel" }, { id = "01.26", map = "ROUTE_31", op = "travel" }, { id = "01.30", map = "VIOLET_CITY", op = "travel" }, -- ========================================================================= -- Section 02 : Sprout Tower and Falkner -- ========================================================================= -- Sprout Tower is optional for the badge but is where HM05 FLASH lives, and -- the rival fight on 3F is a scene trip-wire that will otherwise ambush a -- later pass through. Kept, but the sages are left to their sight lines. { id = "02.1", map = "SPROUT_TOWER_1F", op = "travel", optional = true }, { id = "02.15", map = "SPROUT_TOWER_3F", op = "travel", optional = true }, { id = "02.15b", map = "SPROUT_TOWER_3F", op = "walk", x = 11, y = 9, optional = true, note = "rival encounter coord event, scene 0" }, { id = "02.16", map = "SPROUT_TOWER_3F", op = "talk", x = 10, y = 2, optional = true, expect = "EVENT_GOT_HM05_FLASH" }, -- Grind before each gym. The route used to carry exactly one grind row (the -- opening Route 29 one) and fought every leader at whatever level the walking -- happened to produce -- which is why runs stalled with a level-10 lead and -- two badges. The badges are load bearing far beyond the badge count: FOG -- gates SURF and PLAIN gates STRENGTH, so losing Morty or Whitney means the -- HMs never work and Cianwood is never reached. { id = "02.g", map = "ROUTE_31", op = "grind", level = 14, lead = true }, { id = "02.19", map = "VIOLET_CITY", op = "travel" }, { id = "02.20", map = "VIOLET_CITY", op = "heal" }, { id = "02.22", map = "VIOLET_GYM", op = "travel" }, -- Falkner at (5,1). Abe and Rod are in the way of the walk up and engage on -- their own; the badge script force-sets their flags either way. { id = "02.26", map = "VIOLET_GYM", op = "battle", x = 5, y = 1, talk = true, expect = "ENGINE_ZEPHYRBADGE", retryFrom = "02.20", retryLimit = 4 }, -- The Togepi Egg, and it is not a side quest: it is what OPENS ROUTE 32. -- -- Route 32's only road south runs through (18,8), which carries a coord -- event at scene 0 -- the Miracle Seed man, who follows you, walks you two -- cells back north and hands you nothing you need (maps/Route32.asm -- Route32CooltrainerMStopsYouScene). Nothing in that script changes the -- scene. The one thing in the game that does is Elm's aide, three maps -- away: giving you the egg runs `setmapscene ROUTE_32, -- SCENE_ROUTE32_OFFER_SLOWPOKETAIL` (maps/VioletPokecenter1F.asm), and only -- then does the road open. The map is a soft gate and the egg is the key. -- -- Without these three rows the bot walked into that scene, was pushed back, -- re-planned the identical path and was pushed back again -- so Azalea, Ilex -- Forest, Goldenrod and everything past them were reachable only by -- teleport, which is most of what the run's shortcut count was. -- -- The aide only appears once Elm has phoned: Falkner's badge script arms -- `specialphonecall SPECIALCALL_ASSISTANT` (maps/VioletGym.asm), the call -- lands outdoors after a few steps, and its script clears -- EVENT_ELMS_AIDE_IN_VIOLET_POKEMON_CENTER, which is what un-hides him. -- -- The wander row waits on a flag being CLEARED rather than set, which is why -- it carries `expectClear` instead of `expect`: an object_event's event flag -- HIDES the object when set (CheckObjectFlag), so the aide appears the moment -- the call clears his. { id = "02.26b", map = "VIOLET_CITY", op = "wander", budget = 40, expectClear = "EVENT_ELMS_AIDE_IN_VIOLET_POKEMON_CENTER", optional = true, note = "walk outdoors until Elm's SPECIALCALL_ASSISTANT lands" }, { id = "02.26c", map = "VIOLET_POKECENTER_1F", op = "travel" }, { id = "02.26d", map = "VIOLET_POKECENTER_1F", op = "talk", x = 4, y = 3, answers = { "yes" }, budget = 6000, expect = "EVENT_GOT_TOGEPI_EGG_FROM_ELMS_AIDE" }, -- ========================================================================= -- Section 03 : Route 32, Union Cave, Route 33 -- ========================================================================= -- The Ruins of Alph detour (steps 4-14) is skipped: the Unown puzzle needs -- `special UnownPuzzle` driven through a sliding-tile UI, and nothing past it -- gates progress to Azalea. { id = "03.16", map = "ROUTE_32", op = "travel" }, { id = "03.28", map = "ROUTE_32_POKECENTER_1F", op = "travel", optional = true }, { id = "03.28b", map = "ROUTE_32_POKECENTER_1F", op = "heal", optional = true }, { id = "03.29", map = "UNION_CAVE_1F", op = "travel" }, { id = "03.36", map = "ROUTE_33", op = "travel" }, { id = "03.39", map = "AZALEA_TOWN", op = "travel" }, -- ========================================================================= -- Section 04 : Slowpoke Well and Bugsy -- ========================================================================= -- Slowpoke Well is a hard gate, not a side quest: clearing it is what sets -- AZALEA_TOWN's scene to SCENE_AZALEATOWN_RIVAL_BATTLE, and Ilex Forest -- -- the only way west -- is behind that scene's coord event. { id = "04.3", map = "KURTS_HOUSE", op = "travel" }, { id = "04.3b", map = "KURTS_HOUSE", op = "talk", x = 3, y = 2, expect = "EVENT_AZALEA_TOWN_SLOWPOKETAIL_ROCKET" }, { id = "04.5", map = "AZALEA_POKECENTER_1F", op = "travel", optional = true }, { id = "04.5b", map = "AZALEA_POKECENTER_1F", op = "heal", optional = true }, -- Balls before the well. Elm's aide gives five in the whole game, and the -- SLOWPOKE below is not optional: it is the only SURF user available before -- FOGBADGE opens water hunting, so five failed throws cost Cianwood, the -- Storm Badge and everything after it. A run that came this far has -- thousands of yen and nothing else to spend it on. Count is sized for this -- catch plus the later POLIWAG and bird hunts (07.g0 / 07.30). { id = "04.5c", map = "AZALEA_MART", op = "buy", item = "POKE_BALL", count = 40 }, -- Potions, for the same reason the balls are bought: the bot has thousands -- of yen and nothing else to spend it on, and until now it walked into every -- gym leader with no way to answer damage except more levels. Bot:fightBattle -- drinks the strongest thing in the bag when the lead drops below a third. { id = "04.5d", map = "AZALEA_MART", op = "buy", item = "SUPER_POTION", count = 10, optional = true }, { id = "04.6", map = "SLOWPOKE_WELL_B1F", op = "travel" }, -- Catch a SLOWPOKE while we are down here. Not in the walkthrough, and the -- run cannot finish without it: SURF is required to reach Cianwood in section -- 08, and the Cyndaquil line cannot learn it (its tmhm list has CUT, -- STRENGTH and ROCK_SMASH but no SURF or FLY). SLOWPOKE is in this map's own -- grass table and learns SURF *and* STRENGTH -- but NOT WHIRLPOOL or -- WATERFALL, which is why 07.30 catches a POLIWAG once the pond opens. { id = "04.6b", map = "SLOWPOKE_WELL_B1F", op = "catch", species = { "SLOWPOKE" }, ball = "POKE_BALL" }, -- The three grunts are sight-line fights on the way north and west; the last -- one at (5,2) runs the whole clear-out cutscene with no endifjustbattled, -- ending in HealParty and a warp to Kurt's house. { id = "04.8", map = "SLOWPOKE_WELL_B1F", op = "battle", x = 15, y = 8 }, { id = "04.9", map = "SLOWPOKE_WELL_B1F", op = "battle", x = 13, y = 3 }, { id = "04.11", map = "SLOWPOKE_WELL_B1F", op = "battle", x = 6, y = 6 }, { id = "04.13", map = "SLOWPOKE_WELL_B1F", op = "battle", x = 5, y = 3, budget = 8000, expect = "EVENT_CLEARED_SLOWPOKE_WELL" }, { id = "04.14", map = "KURTS_HOUSE", op = "talk", x = 3, y = 2, answers = { "no" }, optional = true, note = "LURE_BALL, then decline the apricorn prompt" }, { id = "04.g", map = "UNION_CAVE_1F", op = "grind", level = 19, lead = true }, { id = "04.17", map = "AZALEA_GYM", op = "travel" }, { id = "04.22", map = "AZALEA_GYM", op = "battle", x = 5, y = 7, talk = true, expect = "ENGINE_HIVEBADGE", retryFrom = "04.17", retryLimit = 4 }, -- ========================================================================= -- Section 05 : Ilex Forest, CUT, and Whitney -- ========================================================================= { id = "05.1", map = "AZALEA_TOWN", op = "travel" }, { id = "05.1b", map = "AZALEA_TOWN", op = "battle", x = 5, y = 10, note = "SCENE_AZALEATOWN_RIVAL_BATTLE trip-wire" }, -- Enter the forest from AZALEA, not from Route 34. -- -- Ilex Forest is two regions with no walk between them until the tree at -- (8,25) is cut, and the whole of section 05 -- the Farfetch'd herd, the -- man who hands over HM01, the tree itself -- is in the southern one. A -- plain `travel ILEX_FOREST` is satisfied by either, and the planner -- naturally picked the northern gate: the bot arrived in the forest, on the -- correct map, with every remaining objective behind a tree it needed CUT to -- remove and CUT behind the tree. Naming the gate is what pins the side. { id = "05.2b", map = "ILEX_FOREST_AZALEA_GATE", op = "travel" }, { id = "05.3", map = "ILEX_FOREST", op = "travel" }, -- The Farfetch'd herd. Nine talks, each moving the bird to the next spot. -- -- Every FarfetchdPositionN script (bar the first) scalls -- FarfetchdCryAndCheckFacing, so the direction the PLAYER is facing decides -- whether the bird goes onwards or doubles back round the loop. `facings` -- lists the directions that advance it, taken straight from the section-05 -- branch table; approaching from whichever side happens to be nearest herds -- in circles forever. -- -- Pos2 -> Pos3, except DOWN -> Pos8 -- Pos3 -> Pos4, except LEFT -> Pos2 -- Pos4 -> Pos5, except UP -> Pos3 -- Pos5 -> Pos6, except LEFT -> Pos7, UP/RIGHT -> Pos4 -- Pos6 -> Pos7, except RIGHT -> Pos5 -- Pos7 -> Pos8, except LEFT -> Pos6, DOWN -> Pos5 -- Pos8 -> Pos9, except RIGHT -> Pos7, UP/LEFT -> Pos2 -- Pos9 -> Pos10 (terminal), except RIGHT/DOWN -> Pos8 { id = "05.5", map = "ILEX_FOREST", op = "talk", x = 14, y = 31, note = "Pos1: no facing check, always advances" }, { id = "05.6b", map = "ILEX_FOREST", op = "talk", x = 15, y = 25, facings = { "up", "left", "right" } }, { id = "05.6c", map = "ILEX_FOREST", op = "talk", x = 20, y = 24, facings = { "up", "down", "right" } }, { id = "05.6d", map = "ILEX_FOREST", op = "talk", x = 29, y = 22, facings = { "down", "left", "right" } }, { id = "05.6e", map = "ILEX_FOREST", op = "talk", x = 28, y = 31, facings = { "down" } }, { id = "05.6f", map = "ILEX_FOREST", op = "talk", x = 24, y = 35, facings = { "up", "down", "left" } }, { id = "05.6g", map = "ILEX_FOREST", op = "talk", x = 22, y = 31, facings = { "up", "right" } }, { id = "05.6h", map = "ILEX_FOREST", op = "talk", x = 15, y = 29, facings = { "down" } }, { id = "05.6i", map = "ILEX_FOREST", op = "talk", x = 10, y = 35, facings = { "up", "left" }, expect = "EVENT_HERDED_FARFETCHD" }, { id = "05.8", map = "ILEX_FOREST", op = "talk", x = 5, y = 28, expect = "EVENT_GOT_HM01_CUT" }, { id = "05.9", map = "ILEX_FOREST", op = "teach", move = "CUT" }, -- The tree itself is at (8,25); section 05 step 10 writes (8,24), which is -- the cell you STAND on to face it (verified against the cache: (8,24) is -- plain floor, (8,25) is COLL_CUT_TREE $12). A field move targets the tile, -- so the route names the tree. { id = "05.10", map = "ILEX_FOREST", op = "field", move = "CUT", x = 8, y = 25, note = "opens the path north; block (4,12) becomes $17" }, { id = "05.13", map = "ROUTE_34", op = "travel" }, { id = "05.24", map = "GOLDENROD_CITY", op = "travel" }, { id = "05.25", map = "GOLDENROD_CITY", op = "heal" }, -- Two grinds before Whitney, and both are load bearing. -- -- The lead one is obvious: MILTANK is the wall of the first half of the game -- and the bot fights with no items and a "hit it with the strongest move" -- policy, so it needs the levels the walkthrough's player would have. -- -- The party one is what was missing. The bot fought every gym with one -- Pokemon and a level-7 SLOWPOKE behind it, so the moment the lead fainted -- the run was over -- and the SLOWPOKE is not a spare, it is the only mon -- that can learn SURF before water hunting opens, so it has to survive as -- far as Cianwood either way. `lead = false` grinds the party MINIMUM, -- which is what drags it up. { id = "05.g", map = "ROUTE_34", op = "grind", level = 20, lead = false, wipeBudget = 6 }, { id = "05.g2", map = "ROUTE_34", op = "grind", level = 30, lead = true }, -- Re-enter Goldenrod from ROUTE_34 specifically. Its north edge is a direct -- connection and the flood fill confirms reachable border cells (x=8..11); -- the alternative the planner keeps finding -- Violet -> Route 36 -> Route 35 -- -- ends at Route 35's SOUTH gate, whose warp is not reachable from the -- north border you arrive on, so the bot ping-pongs instead of arriving. { id = "05.24b", map = "ROUTE_34", op = "travel" }, -- Heal between the grind and the leader. Whitney's MILTANK is the wall of -- the first half of the game and the grind that precedes her ends with the -- party wherever the wild encounters left it; a run that walks in at half HP -- wins the fight and then blacks out on the way to the badge talk, which -- costs PLAINBADGE -- and PLAINBADGE gates STRENGTH, the Squirtbottle, -- Sudowoodo and ROCK SMASH behind it. { id = "05.38", map = "GOLDENROD_CITY", op = "heal" }, { id = "05.39", map = "GOLDENROD_GYM", op = "travel" }, { id = "05.44", map = "GOLDENROD_GYM", op = "battle", x = 8, y = 3, talk = true, expect = "EVENT_BEAT_WHITNEY" }, -- Whitney cries afterwards and blocks the door until the trip-wire at (8,5) -- runs WhitneyCriesScript; only then does a second talk hand over the badge. { id = "05.45", map = "GOLDENROD_GYM", op = "walk", x = 8, y = 5 }, { id = "05.46", map = "GOLDENROD_GYM", op = "talk", x = 8, y = 3, expect = "ENGINE_PLAINBADGE", retryFrom = "05.38", retryLimit = 4 }, { id = "05.46b", map = "ROUTE_34", op = "travel", optional = true }, { id = "05.47", map = "GOLDENROD_FLOWER_SHOP", op = "travel" }, { id = "05.47b", map = "GOLDENROD_FLOWER_SHOP", op = "talk", x = 2, y = 4, expect = "EVENT_GOT_SQUIRTBOTTLE" }, -- ========================================================================= -- Section 06 : Sudowoodo and ROCK SMASH -- ========================================================================= -- Sudowoodo is a hard gate: it stands on the Route 36 tile that leads east to -- Violet and north to Ecruteak, and TM08 ROCK SMASH (needed for the Burned -- Tower in section 07) is behind having fought it. { id = "06.15", map = "ROUTE_36", op = "travel" }, { id = "06.20", map = "ROUTE_36", op = "battle", x = 35, y = 9, talk = true, answers = { "yes" }, expect = "EVENT_FOUGHT_SUDOWOODO" }, { id = "06.21", map = "ROUTE_36", op = "talk", x = 44, y = 9, expect = "EVENT_GOT_TM08_ROCK_SMASH" }, -- ROCK SMASH is a TM, not an HM, so nothing teaches it as a side effect of -- picking it up -- and the Burned Tower's north half is behind a rock. The -- route had the TM and no `teach` row, so `07.20 field ROCK_SMASH` skipped -- with "no party mon knows ROCK_SMASH", the beasts were never released and -- Morty was fought without them. { id = "06.21b", map = "ROUTE_36", op = "teach", move = "ROCK_SMASH" }, -- ========================================================================= -- Section 07 : Ecruteak, SURF, the beasts, and Morty -- ========================================================================= { id = "07.6", map = "ECRUTEAK_CITY", op = "travel" }, { id = "07.7", map = "ECRUTEAK_POKECENTER_1F", op = "travel" }, { id = "07.7b", map = "ECRUTEAK_POKECENTER_1F", op = "settle", budget = 5000, note = "Bill / Time Capsule scene fires on load" }, { id = "07.7c", map = "ECRUTEAK_POKECENTER_1F", op = "heal" }, -- The five Kimono Girls all have sight 0 and will not start a fight -- themselves, so each is an explicit talk. { id = "07.12", map = "DANCE_THEATER", op = "travel" }, { id = "07.13a", map = "DANCE_THEATER", op = "battle", x = 0, y = 2, talk = true }, { id = "07.13b", map = "DANCE_THEATER", op = "battle", x = 2, y = 1, talk = true }, { id = "07.13c", map = "DANCE_THEATER", op = "battle", x = 6, y = 2, talk = true }, { id = "07.13d", map = "DANCE_THEATER", op = "battle", x = 9, y = 1, talk = true }, { id = "07.13e", map = "DANCE_THEATER", op = "battle", x = 11, y = 2, talk = true }, { id = "07.14", map = "DANCE_THEATER", op = "talk", x = 7, y = 10, expect = "EVENT_GOT_HM03_SURF" }, { id = "07.14b", map = "DANCE_THEATER", op = "teach", move = "SURF" }, -- ops.teach walks the party for the first mon whose tmhm list contains the -- move, so the SLOWPOKE caught in section 04 is what picks this up. -- Grind and heal BEFORE the tower, not after it. -- -- The Burned Tower is a pit maze whose lower floor has six regions, four of -- them one-way pockets, and the bot can and does get stuck in one. With the -- grind and the heal sitting on the far side of it, a tower that went wrong -- took Morty with it -- the badge fight was reached at whatever level and -- whatever HP the tower left behind, and FOGBADGE gates SURF and everything -- after. Nothing in the tower gates the gym, so it is now a detour that may -- fail on its own. -- Morty is the hardest fight in Johto for this party. His GASTLY line is -- Ghost/Poison: the starter's Normal moves cannot touch it at all and its -- Fire is resisted, so the whole gym is carried by the SLOWPOKE's SURF -- -- which means the SLOWPOKE has to be a real Pokemon by now, not the level-20 -- HM caddy it is when it arrives. Both grinds, and the higher lead target, -- are what the fight costs. -- A FLY user before the party grind. Cyndaquil/SLOWPOKE/TOGEPI none of -- them learn FLY (TOGETIC would, but the egg never sees a Shiny Stone on -- this route). ROUTE_37's grass is PIDGEY / HOOTHOOT / PIDGEOTTO; catching -- here costs no detour and the party-minimum grind that follows levels it. { id = "07.g0", map = "ROUTE_37", op = "catch", species = { "PIDGEY", "PIDGEOTTO", "HOOTHOOT", "NOCTOWL" }, ball = "POKE_BALL" }, { id = "07.g", map = "ROUTE_37", op = "grind", level = 28, lead = false, wipeBudget = 6 }, { id = "07.g2", map = "ROUTE_37", op = "grind", level = 36, lead = true }, { id = "07.18", map = "BURNED_TOWER_1F", op = "travel", optional = true }, -- The rival scene fires on entry, before anything can be driven. { id = "07.19", map = "BURNED_TOWER_1F", op = "settle", budget = 8000, optional = true }, -- A smashable rock is an OBJECT, not a tile. `BURNEDTOWER1F_ROCK1` at (4,3) -- is a SPRITEMOVEDATA_SMASHABLE_ROCK whose script is `jumpstd -- SmashRockScript` -> `AskRockSmashScript`, so it is TALKED to and answered -- YES; World:useFieldMove reads the faced TILE and quite correctly refuses -- ("Can't use that here"), which is what the `field` row used to fail with. -- No badge is required for ROCK SMASH, only a party mon that knows it. { id = "07.20", map = "BURNED_TOWER_1F", op = "talk", x = 4, y = 3, answers = { "yes" }, budget = 4000, optional = true, note = "opens the north half" }, { id = "07.21", map = "BURNED_TOWER_1F", op = "battle", x = 8, y = 1, optional = true }, -- Fall through the CENTRE pit (1F warp 9 -> B1F warp 3, landing (10,8)). -- The beasts' plateau is its own region and only that landing is on it; a -- plain travel used to take the nearest pit, land at (3,3), and leave (9,5) -- unreachable. Getting OUT afterwards is the hop-down ledges to the ladder -- at (7,15), which the planner walks now that ledge hops exist. { id = "07.22", map = "BURNED_TOWER_1F", op = "warp", x = 10, y = 7, to = "BURNED_TOWER_B1F", optional = true }, { id = "07.23", map = "BURNED_TOWER_B1F", op = "walk", x = 9, y = 5, expect = "EVENT_RELEASED_THE_BEASTS", budget = 8000, optional = true }, -- Walk into the gym healed. Morty's GASTLY line is immune to the starter's -- Normal moves and resists its Fire, so the fight is carried by the SLOWPOKE -- and its SURF -- and a SLOWPOKE that arrives at half HP loses to the gym -- trainers before the leader is reached. { id = "07.26", map = "ECRUTEAK_MART", op = "buy", item = "HYPER_POTION", count = 10, optional = true }, { id = "07.27", map = "ECRUTEAK_CITY", op = "heal" }, { id = "07.28", map = "ECRUTEAK_GYM", op = "travel" }, { id = "07.29", map = "ECRUTEAK_GYM", op = "battle", x = 5, y = 1, talk = true, expect = "ENGINE_FOGBADGE", retryFrom = "07.27", retryLimit = 4 }, -- WHIRLPOOL / WATERFALL mule. SLOWPOKE can learn SURF and STRENGTH but its -- tmhm list has neither WHIRLPOOL nor WATERFALL -- that is why 11.34b and -- 13.10b used to report "no party mon can learn …". ECRUTEAK_CITY's water -- table is POLIWAG / POLIWHIRL only (no grass table at all), FOGBADGE just -- opened the pond, and SURF is already taught, so this is a zero-detour -- water hunt. POLIWHIRL also picks up STRENGTH on evolution. { id = "07.30", map = "ECRUTEAK_CITY", op = "catch", species = { "POLIWAG", "POLIWHIRL" }, ball = "POKE_BALL", water = true }, -- ========================================================================= -- Section 08 : Olivine, STRENGTH, the lighthouse, Cianwood, Chuck -- ========================================================================= { id = "08.17", map = "OLIVINE_CITY", op = "travel" }, { id = "08.18", map = "OLIVINE_CITY", op = "walk", x = 13, y = 12, note = "rival scene trip-wire, scene 0" }, { id = "08.20", map = "OLIVINE_CITY", op = "heal" }, { id = "08.21", map = "OLIVINE_CAFE", op = "travel" }, { id = "08.21b", map = "OLIVINE_CAFE", op = "talk", x = 4, y = 3, expect = "EVENT_GOT_HM04_STRENGTH" }, { id = "08.22", map = "OLIVINE_CAFE", op = "teach", move = "STRENGTH" }, -- Up the lighthouse to Jasmine. Her explanation is what unlocks the Cianwood -- pharmacy, so this visit is required even though nothing here is a fight. { id = "08.43", map = "OLIVINE_LIGHTHOUSE_6F", op = "travel" }, { id = "08.43b", map = "OLIVINE_LIGHTHOUSE_6F", op = "talk", x = 8, y = 8, expect = "EVENT_JASMINE_EXPLAINED_AMPHYS_SICKNESS" }, { id = "08.50", map = "ROUTE_40", op = "travel" }, -- Start surfing. The SLOWPOKE caught in section 04 is the SURF user (the -- Cyndaquil line cannot learn it). (8,8) is water with walkable land at -- (8,7), so approachAndFace stands on the beach facing the sea and -- World:useFieldMove does the rest. { id = "08.51", map = "ROUTE_40", op = "field", move = "SURF", x = 8, y = 8 }, { id = "08.57", map = "CIANWOOD_CITY", op = "travel" }, { id = "08.60", map = "CIANWOOD_PHARMACY", op = "travel" }, { id = "08.60b", map = "CIANWOOD_PHARMACY", op = "talk", x = 2, y = 3, expect = "EVENT_GOT_SECRETPOTION_FROM_PHARMACY" }, -- Chuck's POLIWRATH and PRIMEAPE are the second wall of Johto, and the bot -- reaches him having fought four Blackbelts and shoved three boulders on the -- way in. With the lane finally open (rows 08.65a-c) the fight itself became -- the blocker, so it gets the same treatment Morty did: bring the whole party -- up, then top the lead off, then walk in healed. { id = "08.g", map = "ROUTE_41", op = "grind", level = 32, lead = false, wipeBudget = 6 }, { id = "08.g2", map = "ROUTE_41", op = "grind", level = 40, lead = true }, { id = "08.61", map = "CIANWOOD_CITY", op = "heal" }, { id = "08.62", map = "CIANWOOD_GYM", op = "travel" }, { id = "08.63a", map = "CIANWOOD_GYM", op = "battle", x = 2, y = 12 }, { id = "08.63b", map = "CIANWOOD_GYM", op = "battle", x = 7, y = 12 }, { id = "08.64", map = "CIANWOOD_GYM", op = "battle", x = 3, y = 9 }, -- The boulder lane is the only way to the back of the gym. -- The boulder row at y=7 (BOULDER2/3/4 at x=3/4/5) is the only way to the -- back of the gym, and it is what STRENGTH is for -- the walkthrough's "use -- Strength to push your way to the last trainer before the gym leader". -- Shoving the middle one north opens the lane behind it. This was a -- `manual` row that logged and moved on, which meant Chuck was fought from -- the wrong side of a rock and STORMBADGE was never earned. -- The boulder puzzle, solved sideways. -- -- Row 7 (boulders at x=3/4/5) is the only link between the gym's halves: -- rows 6-7 are x=3..5, row 5 narrows to (4,5) and (5,5), Blackbelt Lung -- stands on (5,5) and does not leave it, and (4,3) is solid wall. So -- shoving the middle boulder NORTH can never work -- it stays in the one -- column the player needs, and its furthest cell (4,4) blocks the last step -- into row 4. Every count from 2 to 6 was tried and every end state is -- blocked. -- -- The way through is to empty the row instead of climbing it: push the two -- OUTER boulders north (each frees its own cell in row 7 and parks itself in -- a dead-end pocket of row 6), then stand where the right-hand one was and -- push the middle boulder WEST into the gap the left-hand one left. Row 7's -- middle cell is then clear and the column above it is untouched. -- -- A push does not move the player -- the cart treats a strength boulder like -- a solid NPC -- so each of these costs a pair of presses: one to shove the -- rock, one to step into the cell it left. `ops.push` waits for the rock to -- stop sliding between presses, because World:tryPushBoulder refuses while -- `npc.moving`. { id = "08.65a", map = "CIANWOOD_GYM", op = "push", x = 3, y = 7, dir = "up", count = 2, note = "left boulder to (3,6); frees (3,7)" }, { id = "08.65b", map = "CIANWOOD_GYM", op = "push", x = 5, y = 7, dir = "up", count = 2, note = "right boulder to (5,6); frees (5,7)" }, { id = "08.65c", map = "CIANWOOD_GYM", op = "push", x = 4, y = 7, dir = "left", count = 2, note = "middle boulder west into (3,7); the lane north is now open" }, { id = "08.66", map = "CIANWOOD_GYM", op = "battle", x = 5, y = 5, talk = true, budget = 8000 }, { id = "08.68", map = "CIANWOOD_GYM", op = "battle", x = 4, y = 1, talk = true, expect = "ENGINE_STORMBADGE", retryFrom = "08.61", retryLimit = 4, -- Rewind OUTSIDE the gym, not to 08.66 one row up. -- -- Chuck sits behind a STRENGTH boulder puzzle, and a puzzle left in a bad -- state cannot be retried in place: run 25 pushed the boulders into a -- arrangement that sealed the north half, and both 08.66 and 08.68 then answered -- "approach: nowhere to stand" instantly -- burning all four laps in a -- single frame without ever moving. World:setMap calls restoreBlocks, -- which refills the map from ROM, so LEAVING and re-entering is what puts -- the boulders back. 08.61 is the Cianwood heal, one map outside the door. }, -- FLY is an optimisation, never a gate: section 09 opens by flying back to -- Olivine and travelTo can simply swim the way it came. Optional so a miss -- here cannot cost the badge chain behind it. The bird from 07.g0 is who -- learns it. { id = "08.70", map = "CIANWOOD_CITY", op = "talk", x = 10, y = 46, optional = true, expect = "EVENT_GOT_HM02_FLY" }, { id = "08.70b", map = "CIANWOOD_CITY", op = "teach", move = "FLY", optional = true }, -- ========================================================================= -- Section 09 : back to Olivine, cure Amphy, and Jasmine -- ========================================================================= -- The section opens by flying, which the bot does not need: travelTo can swim -- back the way it came. Flying is strictly an optimisation here. { id = "09.14", map = "OLIVINE_LIGHTHOUSE_6F", op = "travel" }, { id = "09.15", map = "OLIVINE_LIGHTHOUSE_6F", op = "talk", x = 8, y = 8, answers = { "yes" }, budget = 6000, expect = "EVENT_JASMINE_RETURNED_TO_GYM" }, { id = "09.17", map = "OLIVINE_CITY", op = "travel" }, { id = "09.17b", map = "OLIVINE_CITY", op = "heal" }, { id = "09.g", map = "ROUTE_39", op = "grind", level = 38, lead = true }, { id = "09.18", map = "OLIVINE_GYM", op = "travel" }, { id = "09.20", map = "OLIVINE_GYM", op = "battle", x = 5, y = 3, talk = true, budget = 12000, expect = "EVENT_BEAT_JASMINE" }, { id = "09.21", map = "OLIVINE_GYM", op = "check", expect = "ENGINE_MINERALBADGE" }, -- ========================================================================= -- Section 10 : Route 42, Mahogany, Route 43, the Lake of Rage -- ========================================================================= -- No badge here. What the section is FOR is EVENT_DECIDED_TO_HELP_LANCE, -- which arms SCENE_MAHOGANYMART1F_LANCE_UNCOVERS_STAIRS and is the only way -- into the Rocket base -- and therefore the only way to HM06 WHIRLPOOL. { id = "10.1", map = "ECRUTEAK_CITY", op = "travel" }, { id = "10.3", map = "ROUTE_42", op = "travel" }, -- Route 42's two lakes sit across the road east. The bot surfs on its own -- now (Bot:stepDir starts the field move when a planned step enters water), -- so this is a plain travel row. { id = "10.13", map = "MAHOGANY_TOWN", op = "travel" }, { id = "10.14", map = "MAHOGANY_TOWN", op = "heal" }, { id = "10.18", map = "ROUTE_43", op = "travel" }, { id = "10.26", map = "LAKE_OF_RAGE", op = "travel" }, { id = "10.g", map = "ROUTE_43", op = "grind", level = 40, lead = true }, -- The Red Gyarados. Its script is `loadwildmon GYARADOS, 30` with -- BATTLETYPE_FORCESHINY, so this is a wild fight the bot may simply win; the -- RED_SCALE and Lance's appearance are set on a KO as well as a catch. { id = "10.33", map = "LAKE_OF_RAGE", op = "battle", x = 18, y = 22, talk = true, budget = 12000, expect = "EVENT_LAKE_OF_RAGE_RED_GYARADOS" }, { id = "10.34", map = "LAKE_OF_RAGE", op = "talk", x = 21, y = 28, answers = { "yes" }, budget = 8000, expect = "EVENT_DECIDED_TO_HELP_LANCE" }, -- ========================================================================= -- Section 11 : the Rocket hideout and Pryce -- ========================================================================= { id = "11.2", map = "MAHOGANY_MART_1F", op = "travel" }, { id = "11.2b", map = "MAHOGANY_MART_1F", op = "settle", budget = 8000, expect = "EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART", note = "LanceUncoversStaircaseScript runs unattended on arrival" }, { id = "11.3", map = "TEAM_ROCKET_BASE_B1F", op = "travel" }, -- The security cameras are sight-line scripts on the way west; each is the -- same pair of grunts and the bot fights them where it meets them. The -- switch that ends them is a bg event read from (19,12) facing UP. { id = "11.10", map = "TEAM_ROCKET_BASE_B1F", op = "talk", x = 19, y = 11, facings = { "up" }, budget = 6000, expect = "EVENT_TURNED_OFF_SECURITY_CAMERAS" }, { id = "11.12", map = "TEAM_ROCKET_BASE_B2F", op = "travel" }, { id = "11.13", map = "TEAM_ROCKET_BASE_B2F", op = "walk", x = 5, y = 14, note = "Lance heals the party here; scene 0 -> 1" }, { id = "11.15", map = "TEAM_ROCKET_BASE_B3F", op = "travel" }, { id = "11.15b", map = "TEAM_ROCKET_BASE_B3F", op = "settle", budget = 6000, expect = "EVENT_TEAM_ROCKET_BASE_B3F_LANCE_PASSWORDS" }, -- Both passwords are learned by talking: the sight-0 grunt at (21,7) has to -- be spoken to TWICE (the first talk is the battle), and the spinning grunt -- at (5,15) the same. -- Both battle rows carry the trainer's own beat flag: the fight fires on a -- sight line DURING the approach, the trainer then stands wherever it -- happened, and the approach's own opinion of reaching the (now moved) -- object is worthless -- run 3 recorded a FAIL on a fight it had won. { id = "11.18", map = "TEAM_ROCKET_BASE_B3F", op = "battle", x = 21, y = 7, talk = true, budget = 8000, expect = "EVENT_BEAT_ROCKET_GRUNTF_5" }, { id = "11.18b", map = "TEAM_ROCKET_BASE_B3F", op = "talk", x = 21, y = 7, expect = "EVENT_LEARNED_SLOWPOKETAIL" }, { id = "11.20", map = "TEAM_ROCKET_BASE_B3F", op = "battle", x = 5, y = 15, talk = true, budget = 8000, expect = "EVENT_BEAT_ROCKET_GRUNTM_28" }, { id = "11.20b", map = "TEAM_ROCKET_BASE_B3F", op = "talk", x = 5, y = 15, expect = "EVENT_LEARNED_RATICATE_TAIL" }, -- Region 1, and only NOW: the two passwords above are learned from grunts at -- (21,7) and (5,15), which are in region 3. Pinning region 1 before them put -- the bot on the wrong side of a floor it could not cross and both password -- rows failed instantly. -- -- Region 1, not "anywhere on B3F". -- -- The floor is three regions that never touch: region 3 (214 cells, the way -- in from B1F, warps 2 and 4 on the right), region 1 (57 cells, warps 1 and 3 -- on the LEFT), and region 2 (46 cells, the boss chamber, sealed until -- Giovanni's door opens). Every beat this section needs -- the rival at -- (8,10), the locked door at (10,9), Executive 4, HAIL GIOVANNI -- is in -- region 1. Arriving anywhere on B3F satisfied a plain `travel`, so the bot -- stood in region 3 while row after row reported "no path" to cells on the -- same floor. The honest route is a loop: B1F -> B2F r4 -> B3F r3 -> back up -- via B3F warp 2 -> B2F r1 -> down B2F warp 2 -> B3F r1. -- -- Region indices come from `tools/goldwalk/mapgraph.lua map `; they are -- the order in tests/drivers/gold/map_regions.lua and change if the extractor -- output changes, so re-check them when regenerating that file. -- Heal BEFORE the region-1 loop, then noHeal all the way through HAIL -- GIOVANNI. The rival, Giovanni's door, Executive 4 and the Murkrow are -- all in region 1 and the loop into it (11.15r) is a five-hop crossing -- through both floors; a between-rows auto-heal after the Executive fight -- (which arrives with the party beaten in a continuous run) left the base, -- healed at Mahogany, and re-entered in region 3 -- from which (7,2) has no -- path. A wipe on 11.27 still recovers: the whiteout heals, and retryFrom -- 11.15r re-runs the loop. { id = "11.20h", map = "MAHOGANY_TOWN", op = "heal" }, { id = "11.15r", map = "TEAM_ROCKET_BASE_B3F", op = "travel", region = 1, noHeal = true }, { id = "11.25", map = "TEAM_ROCKET_BASE_B3F", op = "walk", x = 8, y = 10, noHeal = true, note = "rival cutscene, no battle; scene 1 -> 2" }, { id = "11.26", map = "TEAM_ROCKET_BASE_B3F", op = "talk", x = 10, y = 9, facings = { "up" }, budget = 6000, noHeal = true, expect = "EVENT_OPENED_DOOR_TO_GIOVANNIS_OFFICE" }, { id = "11.27", map = "TEAM_ROCKET_BASE_B3F", op = "battle", x = 10, y = 8, budget = 12000, noHeal = true, expect = "EVENT_BEAT_ROCKET_EXECUTIVEM_4", -- Losable, so it laps. The rewind goes back to the region-1 travel rather -- than one row up, because a wipe puts the player in a Pokecenter and the -- way back into this half of B3F is the loop through both floors. retryFrom = "11.20h", retryLimit = 5 }, { id = "11.28", map = "TEAM_ROCKET_BASE_B3F", op = "talk", x = 7, y = 2, noHeal = true, expect = "EVENT_LEARNED_HAIL_GIOVANNI" }, -- Back to the B1F side of B2F. Coming out of B3F region 1 lands in B2F -- region 1 (top-left, 66 cells); the transmitter door at (14,12) is in region -- 4, the half the stairs from B1F open into, and the two do not touch. Same -- shape as 11.15r, one floor up. -- Via B1F, deliberately, rather than by naming a region index. -- -- The transmitter door's standing cell (14,13) is in the 103-cell half that -- the B1F stairs open into, and coming out of B3F region 1 lands in the -- 66-cell half instead -- which has no B1F exit at all, only the two back up -- to B3F. Going to B1F therefore forces the whole loop, and the plain travel -- that follows can only arrive on the right side. A `region =` hint was tried -- first and was not reliable here: Bot:currentRegions matches a LIVE flood -- fill against the generated seeds, and on this floor it claimed the far -- region while standing in the near one, so the travel reported success -- without moving. -- Heal BEFORE the transmitter room. Once the Electrode scene arms, the -- room cannot be LEFT: Lance's coord events at (12,3)/(12,10)/(12,11) and -- the (14/15,12) pair walk the player straight back in (cart behaviour -- -- RocketBaseLancesSideScript / RocketBaseCantLeaveScript), so a mid-block -- auto-heal just bounced off them until the walk gave up and 11.33b/c ran -- in whatever state that left. noHeal through HM06. { id = "11.30h", map = "MAHOGANY_TOWN", op = "heal" }, { id = "11.30q", map = "TEAM_ROCKET_BASE_B1F", op = "travel" }, { id = "11.30r", map = "TEAM_ROCKET_BASE_B2F", op = "travel", noHeal = true }, { id = "11.31", map = "TEAM_ROCKET_BASE_B2F", op = "talk", x = 14, y = 12, facings = { "up" }, budget = 6000, noHeal = true, expect = "EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER" }, { id = "11.32", map = "TEAM_ROCKET_BASE_B2F", op = "battle", x = 14, y = 11, budget = 12000, noHeal = true, expect = "EVENT_BEAT_ROCKET_EXECUTIVEF_2", retryFrom = "11.30h", retryLimit = 5 }, -- The three Electrodes are wild L23 battles that may Selfdestruct; the third -- one ends the base and hands over HM06. { id = "11.33a", map = "TEAM_ROCKET_BASE_B2F", op = "battle", x = 7, y = 5, talk = true, budget = 8000, noHeal = true }, { id = "11.33b", map = "TEAM_ROCKET_BASE_B2F", op = "battle", x = 7, y = 7, talk = true, budget = 8000, noHeal = true }, { id = "11.33c", map = "TEAM_ROCKET_BASE_B2F", op = "battle", x = 7, y = 9, talk = true, budget = 12000, noHeal = true }, { id = "11.34", map = "TEAM_ROCKET_BASE_B2F", op = "check", noHeal = true, expect = "EVENT_GOT_HM06_WHIRLPOOL", -- The whole tail re-runs from the heal when the third Electrode's -- handout was missed (a Selfdestruct wipe mid-trio leaves the scene -- armed and the room sealed). retryFrom = "11.30h", retryLimit = 4 }, -- WHIRLPOOL and WATERFALL are both water-route gates rather than optional -- extras: Route 27 has a whirlpool block on the way to Route 26, and Tohjo -- Falls needs the climb. Taught to the POLIWAG/POLIWHIRL from 07.30 -- -- SLOWPOKE cannot learn either, despite carrying SURF. { id = "11.34b", map = "TEAM_ROCKET_BASE_B2F", op = "teach", move = "WHIRLPOOL" }, { id = "11.36", map = "MAHOGANY_TOWN", op = "travel" }, { id = "11.36b", map = "MAHOGANY_TOWN", op = "heal" }, { id = "11.g", map = "ROUTE_43", op = "grind", level = 43, lead = true }, { id = "11.36c", map = "MAHOGANY_GYM", op = "travel" }, -- Mahogany's floor is ice: a press slides until something stops it, so no -- cell here can be aimed at and the asm-walk writes the whole gym as a list -- of directions. These two are transcribed from its slide table -- the -- first reaches (2,14) beside the pillar, the second the cell below Pryce. { id = "11.42", map = "MAHOGANY_GYM", op = "press", dirs = { "up", "left", "left", "up", "up" }, note = "entrance (4,17) -> (2,14); the last three cells are plain floor" }, { id = "11.43", map = "MAHOGANY_GYM", op = "press", dirs = { "up", "up", "right", "down", "left", "up", "right" }, note = "(2,14) -> (5,4), directly below Pryce at (5,3)" }, { id = "11.44", map = "MAHOGANY_GYM", op = "battle", x = 5, y = 3, talk = true, budget = 14000, expect = "ENGINE_GLACIERBADGE", retryFrom = "11.36c", retryLimit = 4 }, -- ========================================================================= -- Section 12 : the Radio Tower and the Goldenrod underground -- ========================================================================= -- Seven badges arm ENGINE_ROCKETS_IN_RADIO_TOWER, which is the precondition -- for the whole section. Two passes at the tower with the underground in -- between: the Basement Key comes off Executive 3 on 5F, the Card Key from -- the Director in the underground warehouse, and only the Card Key opens the -- way to the boss. -- Mahogany -> Goldenrod the WEST way, surfing across Route 42, not the -- eastern loop through the Route 45/46/Dark Cave junction the foot-only graph -- prefers (where the live edge-crosser oscillates and teleports). Route 42 -- is water-split like Route 27: the Mahogany side and the Ecruteak-gate warp -- (0,8) connect only by surf, so name the gate and warp to it -- planPath -- surfs the crossing. From Ecruteak the run to Goldenrod is clean -- (Route 37/36/National Park/35). Same waypoint-the-water-crossing lesson as -- TOHJO_FALLS in section 16. { id = "12.0a", map = "ROUTE_42", op = "travel" }, { id = "12.0b", map = "ROUTE_42", op = "warp", x = 0, y = 8, to = "ROUTE_42_ECRUTEAK_GATE" }, { id = "12.0c", map = "ECRUTEAK_CITY", op = "travel" }, { id = "12.1", map = "RADIO_TOWER_1F", op = "travel" }, -- Heal at Goldenrod BEFORE the boss, and lap from here. Executive 3's four -- self-destructing mons can wipe the party, and the whiteout goes to -- blackoutMap -- which, walking in from Mahogany, was MAHOGANY_TOWN. The -- recovery travel Mahogany -> Goldenrod then has to cross the Route 45/46/ -- Dark Cave junction, where the live edge-crosser oscillates and teleports. -- Healing at Goldenrod's Pokecenter first sets the spawn HERE (World: -- updateWhiteoutSpawn fires on the outdoor->Pokecenter warp), so a wipe lands -- next door to the tower and the lap is a two-hop walk, not a cross-Johto -- one. It also enters the fight at full HP, which is half the point. { id = "12.8h", map = "GOLDENROD_CITY", op = "heal" }, { id = "12.9", map = "RADIO_TOWER_5F", op = "travel" }, { id = "12.9b", map = "RADIO_TOWER_5F", op = "walk", x = 0, y = 3, budget = 14000, expect = "EVENT_BEAT_ROCKET_EXECUTIVEM_3", note = "FakeDirectorScript coord event; six mons, four of them explode", retryFrom = "12.8h", retryLimit = 6 }, { id = "12.11", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "travel" }, -- Region 1 of the underground (157 cells, warps 1/2/3): the salon side that -- holds the Basement Key door at (18,6). The basement side (region 5) is the -- OTHER half of the same-map warp pair, and a plain travel can land there -- via switch-room warp 1 -- after which (18,6) has nowhere to stand. { id = "12.14", map = "GOLDENROD_UNDERGROUND", op = "travel", region = 1 }, { id = "12.14b", map = "GOLDENROD_UNDERGROUND", op = "talk", x = 18, y = 6, expect = "EVENT_USED_BASEMENT_KEY" }, -- Region 1 of the switch room (91 cells, warp 1 only): the north corridor -- with the rival trigger and Switch1/2/3. Ten regions on this map; city -- warps land in 9/10 and underground warp 1 lands in 10, none of which can -- reach (16,1). Only underground warp 6 (basement side) opens into region 1. { id = "12.16", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "walk", x = 19, y = 4, budget = 14000, region = 1, expect = "EVENT_RIVAL_GOLDENROD_UNDERGROUND" }, -- Heal BEFORE the puzzle. noHeal from 12.18a through the Card Key: -- MAPCALLBACK_NEWMAP on the underground / warehouse zeroes -- wUndergroundSwitchPositions, so a heal between Switch3 and Switch2 undoes -- the puzzle. The warehouse grunts are also losable, so arrive full. { id = "12.15h", map = "GOLDENROD_CITY", op = "heal" }, -- Pin region 1 before the switches. 12.16 can be `already satisfied` (the -- rival flag survives a wipe / resume), which skips tryReach and leaves the -- bot in whichever half of the map a plain hop preferred -- then every -- switch reports "nowhere to stand". Same shape as 11.15r. { id = "12.17r", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "travel", region = 1, noHeal = true }, -- The switch puzzle. Each switch is a bg event read with A; the shared byte -- is a plain sum, and intermediate positions leave some doors untouched, so -- order matters. 1-then-2-then-3 opens door 8 (Eddie) but NOT door 5. -- 3-then-2-then-1 from the reset state opens doors 3,5,6,8,9,11 -- door 5 -- at (10,10) is the one that reaches the warehouse warps at (22,10)/(23,10). -- See asm-walk section 12, "Consequences a bot needs". { id = "12.18a", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "talk", x = 2, y = 1, budget = 4000, region = 1, noHeal = true, note = "Switch3 ON (byte 0->3)" }, { id = "12.18b", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "talk", x = 10, y = 1, budget = 4000, region = 1, noHeal = true, note = "Switch2 ON (byte 3->5); leaves door 5 open" }, { id = "12.18c", map = "GOLDENROD_UNDERGROUND_SWITCH_ROOM_ENTRANCES", op = "talk", x = 16, y = 1, budget = 4000, region = 1, noHeal = true, note = "Switch1 ON (byte 5->6); warehouse path open" }, { id = "12.24", map = "GOLDENROD_UNDERGROUND_WAREHOUSE", op = "travel", noHeal = true }, { id = "12.26", map = "GOLDENROD_UNDERGROUND_WAREHOUSE", op = "talk", x = 12, y = 8, budget = 12000, noHeal = true, expect = "EVENT_RECEIVED_CARD_KEY", -- A wipe blacks out to the city and the switch callback has already -- zeroed the puzzle, so the rewind re-enters from the heal + region pin. retryFrom = "12.15h", retryLimit = 5 }, -- Out of the warehouse the intended (and only) road is THROUGH the dept -- store basement: EVENT_RECEIVED_CARD_KEY's MAPCALLBACK_TILES clears the -- box pile at B1F block (8,2) (GoldenrodDeptStoreB1F.asm), joining the -- warehouse-stairs pocket to the elevator. That changeblock is invisible to -- the static region graph -- its B1F region 2 lists only the way back -- so -- travel alone loops the switch-room pocket and falls back to TELEPORT. -- Ride the elevator to 1F and leave by the front door. { id = "12.27", map = "GOLDENROD_DEPT_STORE_B1F", op = "travel", noHeal = true }, { id = "12.27b", map = "GOLDENROD_DEPT_STORE_ELEVATOR", op = "travel", noHeal = true }, { id = "12.27c", map = "GOLDENROD_DEPT_STORE_ELEVATOR", op = "elevator", x = 3, y = 0, floor = "1F", doorX = 1, doorY = 3, to = "GOLDENROD_DEPT_STORE_1F" }, { id = "12.28", map = "RADIO_TOWER_3F", op = "travel" }, { id = "12.29", map = "RADIO_TOWER_3F", op = "talk", x = 14, y = 2, facings = { "up" }, budget = 6000, expect = "EVENT_USED_THE_CARD_KEY_IN_THE_RADIO_TOWER" }, { id = "12.g", map = "ROUTE_35", op = "grind", level = 45, lead = true }, -- 5F is two regions that never touch: region 1 (35 cells, warp 1 from the -- west stairs) and region 2 (44 cells, warp 2 from 4F's east stairs). The -- boss coord at (16,5) is in region 2, and the only way onto that half is -- 3F warp 3 (behind the Card Key shutter) -> 4F region 2 -> 5F warp 2. -- A plain travel lands at 5F (0,0) in region 1, where (16,5) has no path. { id = "12.32", map = "RADIO_TOWER_5F", op = "travel", region = 2 }, { id = "12.33", map = "RADIO_TOWER_5F", op = "walk", x = 16, y = 5, budget = 20000, region = 2, expect = "EVENT_CLEARED_RADIO_TOWER", note = "the script walks the player two cells left, then EXECUTIVEM_1", retryFrom = "12.32", retryLimit = 5 }, -- ========================================================================= -- Section 13 : the Ice Path, Clair and the Rising Badge -- ========================================================================= { id = "13.1", map = "MAHOGANY_TOWN", op = "travel" }, { id = "13.1b", map = "MAHOGANY_TOWN", op = "heal" }, { id = "13.9", map = "ICE_PATH_1F", op = "travel" }, { id = "13.10", map = "ICE_PATH_1F", op = "talk", x = 31, y = 7, expect = "EVENT_GOT_HM07_WATERFALL" }, -- Same mule as 11.34b: the POLIWAG/POLIWHIRL from 07.30. { id = "13.10b", map = "ICE_PATH_1F", op = "teach", move = "WATERFALL" }, { id = "13.11", map = "ICE_PATH_B1F", op = "travel" }, -- Four boulders onto four holes (stonetable warp N+2). Each straight shove -- of N cells uses count = 2*N - 1: the player does not move with the rock, so -- every other press is the step into the cell it vacated (same pairing -- Cianwood's 08.65* rows use). A hole-ending segment stops on the falling -- push so the bot does not walk into the pit afterward. -- -- Order matters: the spawn boulders seal each other's stand cells, and the -- old single-row "push up 5 from spawn" rows could not even stand south of -- boulder 1. Solved against the extracted collision + player reachability. -- B3 (8,9) -> hole (5,12) = EVENT_BOULDER_IN_ICE_PATH_3 { id = "13.12a", map = "ICE_PATH_B1F", op = "push", x = 8, y = 9, dir = "right", count = 1 }, { id = "13.12b", map = "ICE_PATH_B1F", op = "push", x = 9, y = 9, dir = "down", count = 11 }, { id = "13.12c", map = "ICE_PATH_B1F", op = "push", x = 9, y = 15, dir = "left", count = 5 }, { id = "13.12d", map = "ICE_PATH_B1F", op = "push", x = 6, y = 15, dir = "up", count = 1 }, { id = "13.12e", map = "ICE_PATH_B1F", op = "push", x = 6, y = 14, dir = "left", count = 1 }, { id = "13.12", map = "ICE_PATH_B1F", op = "push", x = 5, y = 14, dir = "up", count = 3, expect = "EVENT_BOULDER_IN_ICE_PATH_3" }, -- B4 (17,7) -> hole (12,13) = EVENT_BOULDER_IN_ICE_PATH_4 { id = "13.13a", map = "ICE_PATH_B1F", op = "push", x = 17, y = 7, dir = "left", count = 1 }, { id = "13.13b", map = "ICE_PATH_B1F", op = "push", x = 16, y = 7, dir = "down", count = 7 }, { id = "13.13c", map = "ICE_PATH_B1F", op = "push", x = 16, y = 11, dir = "right", count = 1 }, { id = "13.13d", map = "ICE_PATH_B1F", op = "push", x = 17, y = 11, dir = "down", count = 3 }, { id = "13.13", map = "ICE_PATH_B1F", op = "push", x = 17, y = 13, dir = "left", count = 9, expect = "EVENT_BOULDER_IN_ICE_PATH_4" }, -- B1 (11,7) -> hole (11,2) = EVENT_BOULDER_IN_ICE_PATH_1 -- Approaches the hole from the west: (11,4) is wall, so the last shove is -- right from (10,2) (see tests/drivers/gold_icepath_boulder.lua). { id = "13.14a", map = "ICE_PATH_B1F", op = "push", x = 11, y = 7, dir = "up", count = 3 }, { id = "13.14b", map = "ICE_PATH_B1F", op = "push", x = 11, y = 5, dir = "left", count = 1 }, { id = "13.14c", map = "ICE_PATH_B1F", op = "push", x = 10, y = 5, dir = "up", count = 5 }, { id = "13.14", map = "ICE_PATH_B1F", op = "push", x = 10, y = 2, dir = "right", count = 1, expect = "EVENT_BOULDER_IN_ICE_PATH_1" }, -- B2 (7,8) -> hole (4,7) = EVENT_BOULDER_IN_ICE_PATH_2 { id = "13.15a", map = "ICE_PATH_B1F", op = "push", x = 7, y = 8, dir = "left", count = 1 }, { id = "13.15b", map = "ICE_PATH_B1F", op = "push", x = 6, y = 8, dir = "up", count = 9 }, { id = "13.15c", map = "ICE_PATH_B1F", op = "push", x = 6, y = 3, dir = "left", count = 1 }, { id = "13.15d", map = "ICE_PATH_B1F", op = "push", x = 5, y = 3, dir = "down", count = 7 }, { id = "13.15", map = "ICE_PATH_B1F", op = "push", x = 5, y = 7, dir = "left", count = 1, expect = "EVENT_BOULDER_IN_ICE_PATH_2" }, { id = "13.26", map = "BLACKTHORN_CITY", op = "travel" }, { id = "13.27", map = "BLACKTHORN_CITY", op = "heal" }, -- Two FULL RESTOREs for Clair. Her lead DRAGONAIR opens with THUNDER WAVE, -- and a paralyzed Fire lead loses the KINGDRA war (half speed, quarter of -- its turns skipped, super-effective SURF, plus Clair's own HYPER POTION). -- FULL RESTORE is the only status cure the port implements as a battle item, -- and A.statusCure spends one to un-paralyse -- after which a level-58 -- TYPHLOSION outspeeds and wins. Bought at Blackthorn's mart; the Elite -- Four buys its own later, so this does not raid that budget. { id = "13.26b", map = "BLACKTHORN_MART", op = "buy", item = "FULL_RESTORE", count = 2, optional = true }, -- 52 lead: the fighter usually arrives higher from the switch grinds, and -- 13.g re-checks as satisfied then. The Clair retry loop cannot grow the -- party (same reason), so the real lever is the paralysis cure above. { id = "13.g", map = "ROUTE_45", op = "grind", level = 52, lead = true }, { id = "13.28", map = "BLACKTHORN_GYM_1F", op = "travel" }, -- Clair's island is its own region on 1F. EVENT_BOULDER_IN_BLACKTHORN_GYM_1 -- and _3 (with _2 for the full intended bridge) are painted by the 1F -- MAPCALLBACK_TILES when the matching 2F boulders fall; without them the -- right-stairs landing never reaches (5,3). { id = "13.28b", map = "BLACKTHORN_GYM_2F", op = "travel" }, -- Cody and Fran FIRST, then heal, then run the boulders in one unbroken -- visit. The full run wiped the lead on their sight lines mid-sequence, -- the between-rows auto-heal left the gym, and the map reload respawned -- every unfallen boulder under the remaining rows -- 13.29c/13.29a2 then -- had no stand cell. Beaten trainers stay beaten, so the fights are safe -- to take early; noHeal below keeps the sequence unbroken. { id = "13.28c", map = "BLACKTHORN_GYM_2F", op = "battle", x = 4, y = 1, talk = true, budget = 10000, optional = true, expect = "EVENT_BEAT_COOLTRAINERM_CODY" }, { id = "13.28d", map = "BLACKTHORN_GYM_2F", op = "battle", x = 4, y = 11, talk = true, budget = 10000, optional = true, expect = "EVENT_BEAT_COOLTRAINERF_FRAN" }, { id = "13.28h", map = "BLACKTHORN_CITY", op = "heal" }, { id = "13.28r", map = "BLACKTHORN_GYM_2F", op = "travel" }, -- Cody at (4,1) seals the top row, so the stand cell south of B2 (2,2) is -- unreachable until B4 is parked north out of the (3,2)/(3,3) corridor. { id = "13.29a0", map = "BLACKTHORN_GYM_2F", op = "push", x = 3, y = 3, dir = "up", count = 3, optional = true, noHeal = true, note = "B4 to (3,1); opens the path to (2,2)" }, -- B2 (2,3) -> (2,4), then into hole (2,5) after B1 (order from the solver) { id = "13.29a", map = "BLACKTHORN_GYM_2F", op = "push", x = 2, y = 3, dir = "down", count = 1, optional = true, noHeal = true }, -- B5 (6,1) park. optional so a Clair retry can soft-miss. { id = "13.29b", map = "BLACKTHORN_GYM_2F", op = "push", x = 6, y = 1, dir = "right", count = 5, optional = true, noHeal = true }, -- B6 (8,14) clears the south corridor for B3. { id = "13.29d", map = "BLACKTHORN_GYM_2F", op = "push", x = 8, y = 14, dir = "down", count = 5, optional = true, noHeal = true }, -- B3 (6,16) up to (6,7), then one right to (7,7) while B1/B2 finish. { id = "13.29e", map = "BLACKTHORN_GYM_2F", op = "push", x = 6, y = 16, dir = "up", count = 17, optional = true, noHeal = true }, { id = "13.29e2", map = "BLACKTHORN_GYM_2F", op = "push", x = 6, y = 7, dir = "right", count = 1, optional = true, noHeal = true }, -- B1 (8,2) -> hole (8,3) { id = "13.29c", map = "BLACKTHORN_GYM_2F", op = "push", x = 8, y = 2, dir = "down", count = 1, noHeal = true, expect = "EVENT_BOULDER_IN_BLACKTHORN_GYM_1" }, -- B2 (2,4) -> hole (2,5) { id = "13.29a2", map = "BLACKTHORN_GYM_2F", op = "push", x = 2, y = 4, dir = "down", count = 1, noHeal = true, expect = "EVENT_BOULDER_IN_BLACKTHORN_GYM_2" }, -- B3 (7,7) -> hole (8,7) { id = "13.29f", map = "BLACKTHORN_GYM_2F", op = "push", x = 7, y = 7, dir = "right", count = 1, noHeal = true, expect = "EVENT_BOULDER_IN_BLACKTHORN_GYM_3" }, -- Come down the RIGHT stairs so we land in the bridged region. The door -- from the city is the OTHER region and cannot reach Clair even with every -- bridge painted -- only warp 2 / hole landings 6 and 7 can. { id = "13.29g", map = "BLACKTHORN_GYM_2F", op = "warp", x = 7, y = 9, to = "BLACKTHORN_GYM_1F", noHeal = true }, -- Clair is the hardest single fight in the Johto half for a mono-Fire lead: -- a bulky Water/Dragon KINGDRA that resists Fire and SURFs super-effectively, -- THUNDER WAVE paralysis off her DRAGONAIRs, and her own HYPER POTION. A -- level-58 TYPHLOSION wins it about one lap in five, so the lever is laps. -- retryFrom the FULL RESTORE buy so a paralysis cure is restocked while -- there is money (a lost lap halves it -- Gen 2 -- so the cure mostly lands -- on the first attempt); verified beaten within budget from RESUME=13. -- retryLimit 26, not 12: each lost lap KEEPS the EXP from beating her three -- DRAGONAIRs before KINGDRA (resolveFaints awards it before the loss check), -- so the lead climbs ~1 level every ~3 laps -- but her level-37 mons give a -- level-58 TYPHLOSION so little that 12 laps only bought +3 (to 61), short of -- what out-races KINGDRA + her HYPER POTION under paralysis. ~26 laps buys -- ~+8, which wins reliably; most runs land it in well under a dozen and stop -- early. (This is the same lose-to-grind loop the Elite Four rides, only -- against much weaker mons, hence the higher count.) { id = "13.30", map = "BLACKTHORN_GYM_1F", op = "battle", x = 5, y = 3, talk = true, budget = 16000, expect = "EVENT_BEAT_CLAIR", retryFrom = "13.26b", retryLimit = 26 }, -- The badge is not Clair's to give until the Dragon's Den test: the Dragon -- Fang at the shrine is what sets RISINGBADGE. { id = "13.32", map = "DRAGONS_DEN_B1F", op = "travel" }, { id = "13.33", map = "DRAGONS_DEN_B1F", op = "talk", x = 35, y = 16, budget = 12000, expect = "EVENT_DRAGONS_DEN_B1F_DRAGON_FANG" }, { id = "13.33b", map = "DRAGONS_DEN_B1F", op = "check", expect = "ENGINE_RISINGBADGE" }, -- ========================================================================= -- Section 16 : east to Kanto's door -- ========================================================================= -- Eight badges, SURF, WATERFALL and WHIRLPOOL are all in hand by here, which -- is what makes Route 27 and Tohjo Falls crossable at all. -- Waypointed through Route 46 so the Route 45 descent is two short legs, not -- one Blackthorn -> New Bark plan that flip-flopped at the seam. The -- crossing itself needed the edgeTarget fix: coming onto Route 45's top strip -- (region 3), the west border cells nearest the landing are region 1/2 and -- unreachable, and the old nearest-16 reachability cap never scanned down to -- region 3's own Route 46 cells (Bot:edgeTarget). { id = "16.22a", map = "ROUTE_46", op = "travel" }, { id = "16.22b", map = "ROUTE_29", op = "travel" }, { id = "16.23", map = "NEW_BARK_TOWN", op = "travel" }, { id = "16.24", map = "ELMS_LAB", op = "travel", optional = true }, { id = "16.24b", map = "ELMS_LAB", op = "talk", x = 5, y = 2, optional = true, expect = "EVENT_GOT_MASTER_BALL_FROM_ELM" }, { id = "16.27", map = "ROUTE_27", op = "travel" }, { id = "16.28", map = "ROUTE_27", op = "settle", budget = 8000, note = "FirstStepIntoKantoScene is unskippable" }, -- Route 27 is split by water and by TOHJO FALLS: the west half (where the -- New Bark crossing lands, itself over water -- asm-walk map row 4, "the -- crossing itself is water, so SURF") does not touch the east edge that -- connects to Route 26. The intended path is through the falls -- surf to -- warp 2, climb inside with WATERFALL, exit warp 3 onto the east half -- and -- the static region graph is foot-only, so `travel ROUTE_26` from the west -- tries the unreachable east edge and oscillates into a teleport. Naming -- TOHJO_FALLS forces the surf-and-climb; the east half then reaches Route 26. { id = "16.42", map = "TOHJO_FALLS", op = "travel" }, -- Leave by the EAST warp (25,15 -> Route 27 warp 3), not the west one we came -- in through. Reaching it means climbing the falls inside -- warp 1's pool -- (region 6) and warp 2's ledge (region 7) touch only up the WATERFALL -- so -- this exercises the HM07 climb. A plain `travel ROUTE_27` picked the nearest -- warp, which was the west one straight back into the pocket. { id = "16.42b", map = "TOHJO_FALLS", op = "warp", x = 25, y = 15, to = "ROUTE_27" }, { id = "16.43", map = "ROUTE_26", op = "travel" }, { id = "16.54", map = "VICTORY_ROAD_GATE", op = "travel" }, { id = "16.55", map = "VICTORY_ROAD_GATE", op = "walk", x = 10, y = 11, budget = 6000, note = "the badge check; eight badges walks straight through" }, -- ========================================================================= -- Section 17 : Victory Road -- ========================================================================= { id = "17.2", map = "VICTORY_ROAD", op = "travel" }, { id = "17.11", map = "VICTORY_ROAD", op = "walk", x = 13, y = 8, budget = 16000, expect = "EVENT_RIVAL_VICTORY_ROAD", note = "the rival ambush; there is no way past it" }, { id = "17.15", map = "ROUTE_23", op = "travel" }, -- ========================================================================= -- Section 18 : the Pokemon League -- ========================================================================= -- One-way. Every room seals behind you and the Pokecenter's own -- MAPCALLBACK_NEWMAP wipes every EVENT_BEAT_ELITE_4_*, so a heal after Will -- restarts the gauntlet -- which is why the only heal row is before the door. { id = "18.4", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "travel" }, -- The gauntlet is five fights with no heal between them (the Pokecenter's -- MAPCALLBACK_NEWMAP wipes every EVENT_BEAT_ELITE_4_*), so everything the -- party will ever have has to be bought and earned before the door. Run 13 -- earned all eight badges and then lost Koga and Bruno on level and -- attrition alone. -- Grind on VICTORY_ROAD, not Route 26, and only the lead. -- -- Johto's wilds cap around level 30, so a target of 78 on Route 26's -- low-twenties encounters is a number the bot can never reach -- it spent -- 160k frames gaining nothing and then failed on its wipe budget. Victory -- Road is the highest-level ground actually reachable before the door. -- The party-minimum grind is dropped here on purpose: it rotates the WEAKEST -- mon to the front, and at this point in the game that mon is wiped by the -- wilds faster than it can earn anything. { id = "18.g", map = "VICTORY_ROAD", op = "grind", level = 62, lead = true, wipeBudget = 8 }, -- Cheap heals FIRST, and only then the expensive one. -- -- This bought FULL_RESTORE first at Y3000 each, which with a lap's ~Y9000 -- meant a bag of exactly three items and nothing left for HYPER_POTIONs. The -- bot then spent all three topping up in Will's, Koga's and Bruno's rooms and -- walked into LANCE with an empty bag -- it was killing five of his six and -- losing to the last DRAGONITE with no answer. Five HYPER_POTIONs (Y6000) and -- one FULL_RESTORE (Y3000) is the same money for twice the heals, and it is -- the shape A.bestHeal's rationing wants: something cheap to spend between -- 0.35 and 0.6, and one good thing held back for below it. { id = "18.g3", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "buy", item = "HYPER_POTION", count = 4, optional = true }, { id = "18.g4", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "buy", item = "FULL_RESTORE", count = 4, optional = true }, { id = "18.g5", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "buy", item = "REVIVE", count = 10, optional = true }, { id = "18.4b", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "travel" }, { id = "18.4c", map = "INDIGO_PLATEAU_POKECENTER_1F", op = "heal" }, -- Every fight from here to the Champion carries `retryFrom = "18.g3"`. -- -- Losing costs half the money and nothing else -- the experience earned on -- the way to the wipe is kept -- so a lost gauntlet is not a dead end, it is -- a grind that pays better than any grass in the game. Will's mons are in -- the forties; a lap that dies to Bruno still banks Xatu, Jynx, Exeggutor, -- Slowbro, Ariados, Venomoth, Muk, Forretress and Hitmontop. -- -- The rewind lands on 18.g3 (the shop) rather than on Will's door because -- IndigoPlateauPokecenter1F's MAPCALLBACK_NEWMAP clears all five BEAT flags -- AND all ten room ENTRANCE/EXIT flags, so after a wipe the gauntlet really -- does start over at Will -- and the restock and heal have to happen again -- with it. See maps/IndigoPlateauPokecenter1F.asm. { id = "18.7", map = "WILLS_ROOM", op = "travel" }, { id = "18.8", map = "WILLS_ROOM", op = "settle", budget = 6000, expect = "EVENT_WILLS_ROOM_ENTRANCE_CLOSED", retryFrom = "18.g3" }, { id = "18.9", map = "WILLS_ROOM", op = "battle", x = 5, y = 7, talk = true, budget = 20000, expect = "EVENT_BEAT_ELITE_4_WILL", retryFrom = "18.g3" }, { id = "18.11", map = "KOGAS_ROOM", op = "travel" }, { id = "18.11b", map = "KOGAS_ROOM", op = "settle", budget = 6000 }, { id = "18.11c", map = "KOGAS_ROOM", op = "battle", x = 5, y = 7, talk = true, budget = 20000, expect = "EVENT_BEAT_ELITE_4_KOGA", retryFrom = "18.g3" }, { id = "18.13", map = "BRUNOS_ROOM", op = "travel" }, { id = "18.13b", map = "BRUNOS_ROOM", op = "settle", budget = 6000 }, -- 18 laps, not the default 12: Bruno is the wall when the party arrives -- light, and a lost gauntlet lap is the best-paying grind in the game -- -- the extra laps cost frames, running out of them costs the run. { id = "18.13c", map = "BRUNOS_ROOM", op = "battle", x = 5, y = 7, talk = true, budget = 20000, expect = "EVENT_BEAT_ELITE_4_BRUNO", retryFrom = "18.g3", retryLimit = 18 }, { id = "18.15", map = "KARENS_ROOM", op = "travel" }, { id = "18.15b", map = "KARENS_ROOM", op = "settle", budget = 6000 }, { id = "18.15c", map = "KARENS_ROOM", op = "battle", x = 5, y = 7, talk = true, budget = 20000, expect = "EVENT_BEAT_ELITE_4_KAREN", retryFrom = "18.g3" }, { id = "18.17", map = "LANCES_ROOM", op = "travel" }, { id = "18.17b", map = "LANCES_ROOM", op = "settle", budget = 8000, expect = "EVENT_LANCES_ROOM_ENTRANCE_CLOSED", retryFrom = "18.g3" }, -- The coord event at (4,5) is the Champion fight; the script walks the -- player in, so this is a walk row rather than a talk. -- No `expect` on the walk itself, and this is not laziness. -- -- LancesRoom.asm sets EVENT_BEAT_CHAMPION_LANCE, prints two more pages of -- text, opens the door with `changeblock` and only then lets the player -- north. The bot walks through that door the moment it opens, so the `walk` -- op ends with "left LANCES_ROOM for HALL_OF_FAME" -- and a postcondition -- checked at that instant raced the script. Run 20 beat Lance ("CHAMPION -- LANCE was defeated!", ¥5000 prize) NINE times and the row failed all nine, -- each time rewinding the bot back out of the Hall of Fame to refight the -- whole gauntlet. The win was real every time; the oracle was wrong. -- -- So the walk just triggers the fight, and the finish line is measured where -- it actually happens: standing in the HALL OF FAME with the flag its own -- script sets. { id = "18.18", map = "LANCES_ROOM", op = "walk", x = 4, y = 5, budget = 30000, expect = "EVENT_BEAT_CHAMPION_LANCE", retryFrom = "18.g3" }, -- No row here with `map = "HALL_OF_FAME"` that is allowed to fail softly. -- One was tried and it manufactured a false win: the runner reaches a row's -- map before running it, could not walk to the Hall of Fame from the -- Pokecenter it had just whited out to, and fell back to the harness -- TELEPORT shortcut -- so a run that LOST to Lance still finished with -- "final map: HALL_OF_FAME", and 18.20 then read `already satisfied` off an -- EVENT_BEAT_ELITE_FOUR left over in the checkpoint. 18.18 is the gate. { id = "18.20", map = "HALL_OF_FAME", op = "settle", budget = 20000, expect = "EVENT_BEAT_ELITE_FOUR", note = "Lance's speech, the roster, the credits: the finish line" }, }