Files
bryanthaboi ae6cac89e1 G2 support
2026-08-11 11:53:30 -04:00

38 KiB

Section 17 - Victory Road

Source: ../section-17-victory-road.txt (the FAQ numbers this chapter "23 > Victory Road") Maps covered: MAP_VICTORY_ROAD, MAP_VICTORY_ROAD_GATE (entry gate, badge check) Badges / key milestones in this section: no badge. Milestones are the fifth and final RIVAL1 battle (EVENT_RIVAL_VICTORY_ROAD), TM26 Earthquake, and the north exit onto Route 23 / Indigo Plateau.

Important structural fact the walkthrough hides: Gold/Silver Victory Road is a single 10x36-block map, not three floors. What the FAQ calls "first / second / third floor" are three vertically stacked regions of the same map joined by warp_event rows whose destination map is VICTORY_ROAD itself. Every "ladder" and the "hole" are self-warps inside maps/VictoryRoad.asm.

1. Route order

# Map constant asm file Enter via Leaves via Why (walkthrough beat)
0 MAP_VICTORY_ROAD_GATE maps/VictoryRoadGate.asm gate warps 3/4 at (9,17)/(10,17), arriving from Route 26 (maps/Route26.asm:397 warps to VICTORY_ROAD_GATE, 3) gate warps 5/6 at (9,0)/(10,0) -> VICTORY_ROAD warp 1 8-badge check at coord event (10,11); belongs to the previous section but is the only door in
1 MAP_VICTORY_ROAD (entrance region, y 48..71) maps/VictoryRoad.asm warp 1 at (9,67) warp 2, the ladder at (1,49) "Head up the stairway and up the cliff"; Full Heal (15,48) and Max Revive (12,48) sit here, plus the hidden Full Heal at (3,65)
2 MAP_VICTORY_ROAD (mid region, y 32..43) same warp 3 at (1,35) warp 4, the ladder at (13,31) "second floor" - X Special at (7,38), then "up along the path ... another ladder"
3 MAP_VICTORY_ROAD (top region, y 5..21) same warp 5 at (13,17) warp 7, the ladder at (17,19) "Save when you get to the third floor. Go up the cliff to your left, go down the ladder"
4 MAP_VICTORY_ROAD (Full Restore shelf, y 28..34) same warp 6 at (17,33) one-way HOP_DOWN ledge row y=34, x=16..19, landing on y=36 "grab the Full Restore, and jump down"
5 MAP_VICTORY_ROAD (mid region again) same ledge landing (x,36) warp 4 at (13,31) "Head back up the ladder to the third floor"
6 MAP_VICTORY_ROAD (top region) same warp 5 at (13,17) coord events at (12,8) / (13,8) rival ambush, VictoryRoadRivalLeft / VictoryRoadRivalRight
7 MAP_VICTORY_ROAD (TM pocket, y 26..30) same warp 8, the COLL_PIT at (0,11) warp 8's landing is warp 9 at (0,27); leave by HOP_RIGHT at (8,28)->(10,28) or HOP_DOWN at (2,30)/(3,30)->y=32 "go left instead of out the door, and fall down the hole to get TM26 Earthquake"
8 MAP_VICTORY_ROAD exit same corridor x=12..13 at y=7..8, x=11..14 at y=6 warp 10 at (13,5) -> ROUTE_23 warp 3 leave the dungeon
9 MAP_ROUTE_23 maps/Route23.asm warp 3 at (9,13) - next section (Indigo Plateau / Pokemon League). Route23FlypointCallback sets ENGINE_FLYPOINT_INDIGO_PLATEAU on arrival. Stop here.

2. Maps

MAP_VICTORY_ROAD

  • Script: maps/VictoryRoad.asm (included from data/maps/scripts.asm:24)
  • Blocks: maps/VictoryRoad.blk (360 bytes; data/maps/blocks.asm:962)
  • Header: data/maps/maps.asm:160 map VictoryRoad, TILESET_CAVE, CAVE, LANDMARK_VICTORY_ROAD, MUSIC_VICTORY_ROAD, TRUE, PALETTE_NITE, FISHGROUP_SHORE (per the map macro at the head of data/maps/maps.asm: tileset, environment, location, music, phone-service flag TRUE = phone calls suppressed, time-of-day palette, fishing group.)
  • Attributes: data/maps/attributes.asm:494 map_attributes VictoryRoad, VICTORY_ROAD, $1d - border block $1d, and no connection rows follow, so the map has no overworld connections.
  • Dimensions: constants/map_constants.asm:147 map_const VICTORY_ROAD, 10, 36 -> 10x36 blocks = 20x72 walk cells. Group DUNGEONS (group 3), map id 82.
  • Scene variable: data/maps/scenes.asm:60 scene_var VICTORY_ROAD, wVictoryRoadSceneID (sym 01:d6eb)
  • Callbacks: def_callbacks is empty - no MAPCALLBACK_* for this map.
  • Connections: none.

Warps (def_warp_events, transcribed from maps/VictoryRoad.asm:242-252)

idx x y destination map dest warp
1 9 67 VICTORY_ROAD_GATE 5
2 1 49 VICTORY_ROAD 3
3 1 35 VICTORY_ROAD 2
4 13 31 VICTORY_ROAD 5
5 13 17 VICTORY_ROAD 4
6 17 33 VICTORY_ROAD 7
7 17 19 VICTORY_ROAD 6
8 0 11 VICTORY_ROAD 9
9 0 27 VICTORY_ROAD 8
10 13 5 ROUTE_23 3

Self-warp pairs, as a bot should read them: 2<->3, 4<->5, 6<->7, 8->9. Warp 8's tile is COLL_PIT and warp 9's tile is plain COLL_FLOOR, so warp 9 never fires: the hole at (0,11) is one-way down to (0,27). (Tile kinds verified below.)

Coord events (def_coord_events, maps/VictoryRoad.asm:254-256)

scene x y script label effect
SCENE_VICTORYROAD_RIVAL_BATTLE (0) 12 8 VictoryRoadRivalLeft (sym 42:59ba) rival is teleported to (18,11), walks LEFTx6 + UPx2 to (12,9), battle, then leaves DOWNx2 + RIGHTx6
SCENE_VICTORYROAD_RIVAL_BATTLE (0) 13 8 VictoryRoadRivalRight (sym 42:59dd) rival walks from (18,13) UPx2 + LEFTx5 + UPx2 to (13,9), battle, then leaves DOWNx2 + RIGHTx5 + DOWNx2

These two tiles are the entire width of the corridor that leads to the exit (y=8 is walkable only at x=6,7 and x=12,13), so the ambush is unavoidable.

BG events (def_bg_events, maps/VictoryRoad.asm:258-260)

x y type script/item
3 29 BGEVENT_ITEM VictoryRoadHiddenMaxPotion = hiddenitem MAX_POTION, EVENT_VICTORY_ROAD_HIDDEN_MAX_POTION
3 65 BGEVENT_ITEM VictoryRoadHiddenFullHeal = hiddenitem FULL_HEAL, EVENT_VICTORY_ROAD_HIDDEN_FULL_HEAL

Both target tiles are COLL_WALL, i.e. the player stands next to them and presses A into the wall. (3,29) is faced from (2,29), (4,29) or (3,28); (3,65) is faced from (2,65), (4,65), (3,64) or (3,66).

Object events (def_object_events, maps/VictoryRoad.asm:262-268)

Column order follows the object_event macro in macros/scripts/maps.asm:113: x, y, sprite, movement, radius x, radius y, hour1, hour2, palette, type, sight, script, event flag.

const sprite x y movement type script label event flag
VICTORYROAD_RIVAL SPRITE_RIVAL 18 13 SPRITEMOVEDATA_STANDING_UP OBJECTTYPE_SCRIPT ObjectEvent (shared ROM0 stub, sym 00:2812) EVENT_RIVAL_VICTORY_ROAD
VICTORYROAD_POKE_BALL1 SPRITE_POKE_BALL 3 28 SPRITEMOVEDATA_STILL OBJECTTYPE_ITEMBALL VictoryRoadTMEarthquake = itemball TM_EARTHQUAKE EVENT_VICTORY_ROAD_TM_EARTHQUAKE
VICTORYROAD_POKE_BALL2 SPRITE_POKE_BALL 12 48 SPRITEMOVEDATA_STILL OBJECTTYPE_ITEMBALL VictoryRoadMaxRevive = itemball MAX_REVIVE EVENT_VICTORY_ROAD_MAX_REVIVE
VICTORYROAD_POKE_BALL3 SPRITE_POKE_BALL 18 29 SPRITEMOVEDATA_STILL OBJECTTYPE_ITEMBALL VictoryRoadFullRestore = itemball FULL_RESTORE EVENT_VICTORY_ROAD_FULL_RESTORE
VICTORYROAD_POKE_BALL4 SPRITE_POKE_BALL 15 48 SPRITEMOVEDATA_STILL OBJECTTYPE_ITEMBALL VictoryRoadFullHeal = itemball FULL_HEAL EVENT_VICTORY_ROAD_FULL_HEAL
VICTORYROAD_POKE_BALL5 SPRITE_POKE_BALL 7 38 SPRITEMOVEDATA_STILL OBJECTTYPE_ITEMBALL VictoryRoadXSpecial = itemball X_SPECIAL EVENT_VICTORY_ROAD_X_SPECIAL

All rows use radius 0,0, hours -1,-1 (always present), palette 0, sight 0.

Object-flag polarity (this bites bot authors): CheckObjectFlag in engine/overworld/map_objects_2.asm:32 masks an object when its event flag is set, and shows it when the flag is clear or is -1. Script_appear clears the flag, Script_disappear sets it (engine/overworld/scripting.asm:879-897). InitializeEventsScript in engine/events/std_scripts.asm:521 sets EVENT_RIVAL_VICTORY_ROAD at new game, so the rival object starts hidden and is only revealed by the appear inside the ambush script.

Derived collision map (not verbatim asm - built by decoding maps/VictoryRoad.blk through data/tilesets/cave_collision.asm and data/collision/collision_permissions.asm, with the quadrant index (x & 1) + 2 * (y & 1) taken from GetCoordTileCollision in home/map.asm:2065). It is included because Victory Road is the one map in this section where "which tile can I stand on" is the whole problem.

Verification: all ten warp_event tiles land on the expected collision (WARP_CARPET_DOWN, six LADDER, PIT, FLOOR, CAVE) and all six object_event tiles land on walkable tiles, so the decode is aligned.

Legend: . floor, # wall (impassable), ^ COLL_UP_WALL (walkable, but you cannot step down into it and cannot step up off it), L ladder, P pit, C cave exit, W warp carpet (needs a DOWN press), < HOP_LEFT, > HOP_RIGHT, v HOP_DOWN (all three are walkable land; pressing the matching direction while standing on one jumps two tiles - see .TryJump and .ledge_table in engine/overworld/player_movement.asm:354-391, which reads the tile the player is standing on, not the tile ahead).

    01234567890123456789
  0 ....................
  1 ....................
  2 ....................
  3 ....................
  4 ....................
  5 #############C######
  6 ###########....#####
  7 ############..######
  8 ######..####..######
  9 #####....##....#####
 10 ......##...........#
 11 P....####...........
 12 ...######^^^^^^^^#..
 13 #########........#..
 14 #^^^^^^##........#..
 15 #......##..#####.#..
 16 #......##..#........
 17 ###.#..##..#.L..####
 18 #...#......#####..##
 19 #...##########...L##
 20 ##......>#.......###
 21 ###.....>#.....#####
 22 ####################
 23 ####################
 24 ####################
 25 ####################
 26 #...################
 27 .......#############
 28 ........>#...#######
 29 ...#....>#....####.#
 30 ##vv..#####...####..
 31 ###########..L###...
 32 ##..########..##....
 33 ....########..##.L..
 34 ..#^^^^^^^^#...#vvvv
 35 .L#........#...#####
 36 ..#........#........
 37 ..###.###..##.......
 38 ......#<#...^^^^^#..
 39 #..#..#<#........#..
 40 ##....#<#........#..
 41 ####..#<#####.####..
 42 #######.............
 43 ##########........##
 44 ####################
 45 ####################
 46 ####################
 47 ####################
 48 ....########.##..###
 49 .L..########.###..##
 50 #.....####........##
 51 #......#####..#....#
 52 #...#^^^^^^^^^^^^#..
 53 #...#............#..
 54 ##..#............#..
 55 ##..###.###..##.##..
 56 ##........#..##.....
 57 ##........#..##....#
 58 ##.##^^####..#######
 59 ##..#..####..#######
 60 ##vv#...^^...#######
 61 #####........#######
 62 ##..#........######^
 63 ##..###.###########.
 64 #....#..##.....####.
 65 #..#....#......####.
 66 ##............###^..
 67 ######...W##.####...
 68 #######^^#^^^^^^....
 69 #######.............
 70 ^^^^^^..............
 71 ....................

One-way transitions a bot must respect (all derived from the grid above):

  • (0,11) PIT -> (0,27). No route back up from (0,27); the return is a ledge.
  • (8,28) or (8,29) HOP_RIGHT + RIGHT -> (10,28) / (10,29), which reaches the (13,31) ladder. This is the short way out of the TM pocket.
  • (2,30) or (3,30) HOP_DOWN + DOWN -> (2,32) / (3,32), which drops into the pocket that holds the (1,35) ladder. This is the long way out of the TM pocket.
  • (16..19, 34) HOP_DOWN + DOWN -> (16..19, 36). This is the only exit from the Full Restore shelf, and it is why the FAQ says "jump down".
  • (8,20) or (8,21) HOP_RIGHT + RIGHT -> (10,20) / (10,21) in the top region.
  • Rows of ^ (COLL_UP_WALL) are walkable dead strips: you may enter them from the side or from below and leave sideways or downward, never upward, and you can never step down onto one.

Scripts of interest

  • VictoryRoadRivalLeft (maps/VictoryRoad.asm:22, sym 42:59ba) moveobject VICTORYROAD_RIVAL, 18, 11 / turnobject PLAYER, DOWN / showemote EMOTE_SHOCK, PLAYER, 15 / special FadeOutMusic / pause 15 / appear VICTORYROAD_RIVAL / applymovement VictoryRoadRivalBattleApproachMovement1 (LEFT x6, UP x2) / scall VictoryRoadRivalNext / applymovement VictoryRoadRivalBattleExitMovement1 (DOWN x2, RIGHT x6) / disappear VICTORYROAD_RIVAL / setscene SCENE_VICTORYROAD_NOOP / playmapmusic / end.

  • VictoryRoadRivalRight (maps/VictoryRoad.asm:37, sym 42:59dd) - identical except there is no moveobject (he starts at his object_event position 18,13), the approach is VictoryRoadRivalBattleApproachMovement2 (UP x2, LEFT x5, UP x2) and the exit is VictoryRoadRivalBattleExitMovement2 (DOWN x2, RIGHT x5, DOWN x2).

  • VictoryRoadRivalNext (maps/VictoryRoad.asm:51, sym 42:59fc) - the shared body. turnobject PLAYER, DOWN, playmusic MUSIC_RIVAL_ENCOUNTER, text VictoryRoadRivalBeforeText, then setevent EVENT_RIVAL_VICTORY_ROAD (before the battle, so a reset or blackout mid-battle still leaves the object hidden), then a three-way starter branch:

    • checkevent EVENT_GOT_TOTODILE_FROM_ELM -> .GotTotodile -> loadtrainer RIVAL1, RIVAL1_5_CHIKORITA
    • checkevent EVENT_GOT_CHIKORITA_FROM_ELM -> .GotChikorita -> loadtrainer RIVAL1, RIVAL1_5_CYNDAQUIL
    • fall-through (player picked Cyndaquil) -> loadtrainer RIVAL1, RIVAL1_5_TOTODILE

    Each arm runs winlosstext VictoryRoadRivalDefeatText, VictoryRoadRivalVictoryText, setlasttalked VICTORYROAD_RIVAL, startbattle, dontrestartmapmusic, reloadmapafterbattle, then .AfterBattle: playmusic MUSIC_RIVAL_AFTER and VictoryRoadRivalAfterText.

  • VictoryRoadTMEarthquake / MaxRevive / FullRestore / FullHeal / XSpecial (maps/VictoryRoad.asm:97-110) - each is a bare itemball <ITEM> (two bytes: item, quantity 1; macros/scripts/maps.asm:155), not bytecode. Do not try to disassemble them.

  • VictoryRoadHiddenMaxPotion / VictoryRoadHiddenFullHeal (maps/VictoryRoad.asm:112-116) - hiddenitem item, flag, three bytes laid down as dwb flag, item (macros/scripts/maps.asm:165).

Flags and events

constant defined in read/written by meaning for a bot
EVENT_RIVAL_VICTORY_ROAD constants/event_flags.asm:1124 set by InitializeEventsScript (engine/events/std_scripts.asm:521) and again by VictoryRoadRivalNext; cleared by the appear in the ambush scripts set = rival object masked. Postcondition of the ambush.
EVENT_VICTORY_ROAD_TM_EARTHQUAKE constants/event_flags.asm:1092 itemball object flag set once TM26 is taken
EVENT_VICTORY_ROAD_MAX_REVIVE constants/event_flags.asm:1093 itemball object flag set once Max Revive is taken
EVENT_VICTORY_ROAD_FULL_RESTORE constants/event_flags.asm:1094 itemball object flag set once Full Restore is taken
EVENT_VICTORY_ROAD_FULL_HEAL constants/event_flags.asm:1095 itemball object flag set once Full Heal is taken
EVENT_VICTORY_ROAD_X_SPECIAL constants/event_flags.asm:1096 itemball object flag set once X Special is taken
EVENT_VICTORY_ROAD_HIDDEN_MAX_POTION constants/event_flags.asm:168 hiddenitem operand at bg (3,29) set once dug up
EVENT_VICTORY_ROAD_HIDDEN_FULL_HEAL constants/event_flags.asm:169 hiddenitem operand at bg (3,65) set once dug up
EVENT_GOT_TOTODILE_FROM_ELM (:37), EVENT_GOT_CHIKORITA_FROM_ELM (:38) constants/event_flags.asm read by VictoryRoadRivalNext selects which of the three rival parties loads. EVENT_GOT_CYNDAQUIL_FROM_ELM (:36) is never read here; Cyndaquil is the fall-through case
SCENE_VICTORYROAD_RIVAL_BATTLE = 0 defined inline by the scene_script macro (macros/scripts/maps.asm:25, const_def starting at 0) via maps/VictoryRoad.asm:11 compared by both coord events the scene the map starts a new game on
SCENE_VICTORYROAD_NOOP = 1 same, maps/VictoryRoad.asm:12 written by setscene at the end of both ambush scripts rival ambush disarmed

Both scene scripts (VictoryRoadNoop1Scene, VictoryRoadNoop2Scene) are a bare end; the scene id only gates the coord events.

Items

item how obtained source (label / bg_event / hidden) one-time flag
TM_EARTHQUAKE (TM26 - counted off the add_tm list in constants/item_constants.asm:218-246) Poke Ball at (3,28), only reachable through the pit at (0,11) VictoryRoadTMEarthquake EVENT_VICTORY_ROAD_TM_EARTHQUAKE
MAX_REVIVE Poke Ball at (12,48) VictoryRoadMaxRevive EVENT_VICTORY_ROAD_MAX_REVIVE
FULL_RESTORE Poke Ball at (18,29), reached by ladder warp 7 -> (17,33) then north VictoryRoadFullRestore EVENT_VICTORY_ROAD_FULL_RESTORE
FULL_HEAL Poke Ball at (15,48) VictoryRoadFullHeal EVENT_VICTORY_ROAD_FULL_HEAL
X_SPECIAL Poke Ball at (7,38), standing on the HOP_LEFT column; walk north from (7,42) VictoryRoadXSpecial EVENT_VICTORY_ROAD_X_SPECIAL
MAX_POTION hidden, face the wall at (3,29) bg_event 3, 29, BGEVENT_ITEM EVENT_VICTORY_ROAD_HIDDEN_MAX_POTION
FULL_HEAL (second one) hidden, face the wall at (3,65) bg_event 3, 65, BGEVENT_ITEM EVENT_VICTORY_ROAD_HIDDEN_FULL_HEAL

Trainers

There are no OBJECTTYPE_TRAINER objects on this map. The single battle is a scripted loadtrainer with no EVENT_BEAT_* flag of its own.

const class id party (data/trainers/parties.asm label) script label rematch/phone
RIVAL1_5_CHIKORITA RIVAL1 (trainer class 9, constants/trainer_constants.asm:51) 13th member of the class Rival1Group "RIVAL1 (13)" (data/trainers/parties.asm:164, sym 0e:5a92 for the group) VictoryRoadRivalNext.GotTotodile (sym 42:5a27) none
RIVAL1_5_CYNDAQUIL RIVAL1 14th Rival1Group "RIVAL1 (14)" (data/trainers/parties.asm:174) VictoryRoadRivalNext.GotChikorita (sym 42:5a37) none
RIVAL1_5_TOTODILE RIVAL1 15th Rival1Group "RIVAL1 (15)" (data/trainers/parties.asm:184) fall-through arm of VictoryRoadRivalNext none

Parties, verbatim (TRAINERTYPE_MOVES, name string "?@"):

RIVAL1 (13) - loaded when the player chose Totodile:

db 34, SNEASEL,    QUICK_ATTACK, SCREECH, FAINT_ATTACK, FURY_CUTTER
db 36, GOLBAT,     LEECH_LIFE, BITE, CONFUSE_RAY, WING_ATTACK
db 35, MAGNETON,   THUNDERSHOCK, SONICBOOM, THUNDER_WAVE, SWIFT
db 35, HAUNTER,    MEAN_LOOK, CURSE, SHADOW_BALL, CONFUSE_RAY
db 35, KADABRA,    DISABLE, PSYBEAM, RECOVER, FUTURE_SIGHT
db 38, MEGANIUM,   REFLECT, RAZOR_LEAF, POISONPOWDER, BODY_SLAM

RIVAL1 (14) - loaded when the player chose Chikorita:

db 34, SNEASEL,    QUICK_ATTACK, SCREECH, FAINT_ATTACK, FURY_CUTTER
db 36, GOLBAT,     LEECH_LIFE, BITE, CONFUSE_RAY, WING_ATTACK
db 35, MAGNETON,   THUNDERSHOCK, SONICBOOM, THUNDER_WAVE, SWIFT
db 35, HAUNTER,    MEAN_LOOK, CURSE, SHADOW_BALL, CONFUSE_RAY
db 35, KADABRA,    DISABLE, PSYBEAM, RECOVER, FUTURE_SIGHT
db 38, TYPHLOSION, SMOKESCREEN, EMBER, QUICK_ATTACK, FLAME_WHEEL

RIVAL1 (15) - loaded when the player chose Cyndaquil:

db 34, SNEASEL,    QUICK_ATTACK, SCREECH, FAINT_ATTACK, FURY_CUTTER
db 36, GOLBAT,     LEECH_LIFE, BITE, CONFUSE_RAY, WING_ATTACK
db 34, MAGNETON,   THUNDERSHOCK, SONICBOOM, THUNDER_WAVE, SWIFT
db 35, HAUNTER,    MEAN_LOOK, CURSE, SHADOW_BALL, CONFUSE_RAY
db 35, KADABRA,    DISABLE, PSYBEAM, RECOVER, FUTURE_SIGHT
db 38, FERALIGATR, RAGE, WATER_GUN, SCARY_FACE, SLASH

Note the send-out order: Sneasel, Golbat, Magneton, Haunter, Kadabra, starter. The FAQ lists the starter fourth; the asm puts it last.

Wild encounters

data/wild/kanto_grass.asm:144 def_grass_wildmons VICTORY_ROAD (Victory Road lives in the Kanto grass table even though it is Johto-side).

Encounter rates: db 6 percent, 6 percent, 6 percent (morn / day / nite - all equal). Slot weights come from GrassMonProbTable (data/wild/probabilities.asm:6): 30 / 30 / 20 / 10 / 5 / 4 / 1 percent.

Gold (IF DEF(_GOLD)), identical for morn, day and nite:

slot % level species
1 30 32 GRAVELER
2 30 32 GOLBAT
3 20 33 URSARING
4 10 34 ONIX
5 5 36 ONIX
6 4 35 RHYHORN
7 1 35 RHYHORN

Silver (ELIF DEF(_SILVER)) is the same table with slot 3 replaced by db 33, DONPHAN.

No water, fishing, headbutt or rock-smash data: there is no VICTORY_ROAD row in data/wild/kanto_water.asm, data/wild/johto_water.asm, data/wild/fish.asm or data/wild/treemons.asm, and the decoded collision map contains no water tiles. The FISHGROUP_SHORE in the header is therefore unreachable. No roamer either (VICTORY_ROAD is absent from data/wild/roammon_maps.asm).

MAP_VICTORY_ROAD_GATE

Included here because it is the only entrance and it carries the badge gate. The NPC beats themselves belong to the previous / later sections.

  • Script: maps/VictoryRoadGate.asm (data/maps/scripts.asm:452)
  • Blocks: maps/VictoryRoadGate.blk (data/maps/blocks.asm:943)
  • Header: data/maps/maps.asm:467 map VictoryRoadGate, TILESET_GATE, GATE, LANDMARK_ROUTE_26, MUSIC_INDIGO_PLATEAU, FALSE, PALETTE_DAY, FISHGROUP_SHORE
  • Attributes: data/maps/attributes.asm:666, border block $00, no connections.
  • Dimensions: constants/map_constants.asm:433 map_const VICTORY_ROAD_GATE, 10, 9 -> 20x18 cells. Group VIRIDIAN (group 23), map id 13.
  • Scene variable: data/maps/scenes.asm:16 scene_var VICTORY_ROAD_GATE, wVictoryRoadGateSceneID (sym 01:d6bf)

Warps (maps/VictoryRoadGate.asm:101-109)

idx x y destination map dest warp
1 17 7 ROUTE_22 1
2 18 7 ROUTE_22 1
3 9 17 ROUTE_26 1
4 10 17 ROUTE_26 1
5 9 0 VICTORY_ROAD 1
6 10 0 VICTORY_ROAD 1
7 1 7 ROUTE_28 2
8 2 7 ROUTE_28 2

Cross-checked from the other side: maps/Route22.asm:20 warps to VICTORY_ROAD_GATE, 1, maps/Route26.asm:397 warps to VICTORY_ROAD_GATE, 3, maps/Route28.asm:21 warps to VICTORY_ROAD_GATE, 7.

Coord events

scene x y script label effect
SCENE_VICTORYROADGATE_BADGE_CHECK (0) 10 11 VictoryRoadGateBadgeCheckScript (sym 5f:4fdc) turns the player LEFT and falls into _VictoryRoadGateBadgeCheckScript

BG events: none.

Object events (maps/VictoryRoadGate.asm:116-119)

const sprite x y movement type script label event flag
VICTORYROADGATE_OFFICER SPRITE_OFFICER 8 11 SPRITEMOVEDATA_STANDING_RIGHT OBJECTTYPE_SCRIPT VictoryRoadGateOfficerScript -1 (always present)
VICTORYROADGATE_BLACK_BELT1 SPRITE_BLACK_BELT 7 5 SPRITEMOVEDATA_STANDING_RIGHT OBJECTTYPE_SCRIPT VictoryRoadGateLeftBlackBeltScript EVENT_OPENED_MT_SILVER
VICTORYROADGATE_BLACK_BELT2 SPRITE_BLACK_BELT 12 5 SPRITEMOVEDATA_STANDING_LEFT OBJECTTYPE_SCRIPT VictoryRoadGateRightBlackBeltScript EVENT_FOUGHT_SNORLAX

Derived collision map (same method, data/tilesets/gate_collision.asm; c = COLL_COUNTER, a wall):

    01234567890123456789
  0 #########DD#########
  1 ########....########
  2 ########....########
  3 ########....########
  4 ########....########
  5 ....................
  6 ....####....####....
  7 .WW.####....####.WW.
  8 ########....########
  9 ########....########
 10 ########cc..########
 11 ########.c.c########
 12 ########.c..########
 13 ########cc..########
 14 ########....########
 15 ########....########
 16 ########....########
 17 ########.WW.########

Row 11 is walkable only at x=8 (where the officer stands) and x=10, so (10,11) is a mandatory chokepoint: the badge check cannot be walked around.

Scripts of interest

  • _VictoryRoadGateBadgeCheckScript (maps/VictoryRoadGate.asm:25, sym 5f:4fe3): writetext VictoryRoadGateOfficerText, promptbutton, readvar VAR_BADGES, ifgreater NUM_JOHTO_BADGES - 1, .AllEightBadges. On failure it prints VictoryRoadGateNotEnoughBadgesText and applymovement PLAYER, VictoryRoadGateStepDownMovement (one step DOWN, pushing the player back south). On success it prints VictoryRoadGateEightBadgesText and setscene SCENE_VICTORYROADGATE_NOOP, permanently disarming the coord event.
  • VictoryRoadGateOfficerScript (maps/VictoryRoadGate.asm:23) - faceplayer then the same body, so talking to the officer also opens the gate.

3. Blockers and gates

Gate Enforced by (file:label) Requirement Unlock condition
Entry to Victory Road maps/VictoryRoadGate.asm:19 VictoryRoadGateBadgeCheckScript / _VictoryRoadGateBadgeCheckScript readvar VAR_BADGES then ifgreater NUM_JOHTO_BADGES - 1 (that is, badge count must be >= 8). NUM_JOHTO_BADGES = 8 (constants/ram_constants.asm:260). VAR_BADGES resolves to .CountBadges in engine/overworld/variables.asm:80, which is CountSetBits over two bytes (wBadges, b = 2), i.e. Johto and Kanto badges together own all eight Johto badges. The script then sets SCENE_VICTORYROADGATE_NOOP, so the check runs at most once
Physical block west to Route 28 maps/VictoryRoadGate.asm:118 object VICTORYROADGATE_BLACK_BELT1 at (7,5), masked when EVENT_OPENED_MT_SILVER is set row 5 is the only east-west corridor in the gate and he stands in it out of scope here (Mt. Silver, later section)
Physical block east to Route 22 maps/VictoryRoadGate.asm:119 object VICTORYROADGATE_BLACK_BELT2 at (12,5), masked when EVENT_FOUGHT_SNORLAX is set same corridor out of scope here (Kanto, later section)
Rival ambush before the exit maps/VictoryRoad.asm:255-256 coord events at (12,8) and (13,8), gated on SCENE_VICTORYROAD_RIVAL_BATTLE those two tiles are the whole corridor to the exit at (13,5) win the battle; the script then runs setscene SCENE_VICTORYROAD_NOOP
TM26 Earthquake geometry only, no flag: (3,28) is inside the y=26..30 pocket whose only entrance is the COLL_PIT at (0,11) reach the top region first (so: beat the ladders, not the rival) none
Full Restore geometry only: (18,29) is on a shelf whose only entrance is warp 7 (17,19) -> (17,33) reach the top region none

Field moves: none required. There is no COLL_CUT_TREE, no water, no strength boulder and no whirlpool anywhere in the decoded map, and the header palette is PALETTE_NITE, not PALETTE_DARK, so Flash is not needed either. The FAQ's "no puzzles to solve now" is accurate.

4. Bot checklist

Coordinates are map cells (x, y) on the named map. "step" means walk onto the tile; ladders and the pit fire on arrival (Permissions.isImmediateWarp equivalent: COLL_LADDER = $72 and COLL_PIT = $60 are warp collisions), while the entrance carpet at (9,67) fires on a DOWN press.

  1. MAP_VICTORY_ROAD_GATE: from the Route 26 door at (9,17)/(10,17) walk north along x=10. Precondition: 8 Johto badges. Step (10,11) -> VictoryRoadGateBadgeCheckScript fires. Postcondition: wVictoryRoadGateSceneID = SCENE_VICTORYROADGATE_NOOP. If badges < 8 the script pushes you one step DOWN and you cannot pass.
  2. MAP_VICTORY_ROAD_GATE: step (9,0) or (10,0) -> warp to MAP_VICTORY_ROAD (9,67).
  3. MAP_VICTORY_ROAD entrance region. Waypoints that were checked against the collision map: (9,66) -> west along y=66 to (7,66) -> north x=7 through y=65,64 to (7,63) -> (7,62) -> east along y=62 to (11,62)/(12,62) -> north x=11/12 through y=61..55 -> (11,54) -> the long y=53/54 corridor (x=5..16).
  4. Max Revive and Full Heal: from the y=53/54 corridor go east to (15,54) -> (15,55) -> (15,56) -> east along y=56 to (18,56) -> north along x=18 through y=55,54,53,52 to (18,51) -> west along y=51 to (15,51) -> (15,50) -> (16,50) -> (16,49) -> (16,48), press A facing LEFT into (15,48) -> Full Heal (EVENT_VICTORY_ROAD_FULL_HEAL). Then west along y=50 to (12,50) -> (12,49) -> press A facing UP into (12,48) -> Max Revive (EVENT_VICTORY_ROAD_MAX_REVIVE).
  5. Optional hidden Full Heal: face the wall at (3,65) from (2,65), (4,65), (3,64) or (3,66) and press A. Postcondition EVENT_VICTORY_ROAD_HIDDEN_FULL_HEAL.
  6. Back along the y=53/54 corridor to its west end, (3,53) -> (2,52) -> (2,51) -> (2,50) -> (1,49); the ladder fires on arrival -> warp 2 -> (1,35).
  7. X Special. Verified chain from the ladder landing: (1,35) -> (1,36) -> (1,37) -> (1,38) -> east along y=38 to (5,38) -> (5,37) -> (5,36) -> east along y=36 to (9,36)/(10,36) -> (9,37)/(10,37) -> (9,38)/(10,38) -> south through y=39,40 (x=9..16 is open) -> (13,41) -> (13,42) -> west along y=42 to (7,42) -> north along x=7 (the HOP_LEFT column is walkable) through y=41,40,39 to (7,38). Press A -> X Special. Postcondition EVENT_VICTORY_ROAD_X_SPECIAL. Do not press LEFT while on that column (it triggers a two-tile jump into a wall column).
  8. To the (13,31) ladder: back to (7,42) -> east along y=42 to (18,42) -> north along x=18 through y=41,40,39,38 to (18,37) -> west along y=37 then y=36 to (13,36) -> north (13,35), (13,34), (13,33), (13,32) -> step (13,31) -> warp 4 -> arrive (13,17). Note you cannot climb x=13 straight up from y=41: (13,38) is COLL_UP_WALL and blocks the step up out of it, and the x=11 column walls off the y=34..36 strip on its west side.
  9. Optional Full Restore detour. The verified chain from the ladder to (17,19) is: (13,17) -> (13,16) -> east along y=16 to (16,16) -> (16,15) -> (16,14) -> west along y=14 to (9,14)/(10,14) -> south x=9/10 through y=15,16,17 to (9,18)/(10,18) -> west along y=18 to (5,18) -> (5,17) -> (5,16) -> west along y=16 to (3,16) -> (3,17) -> (3,18) -> (3,19) -> (3,20) -> east along y=20 to (8,20) -> press RIGHT to hop the ledge, landing (10,20) -> east/north to (16,19) -> (17,19). On the cart that HOP_RIGHT is the only way into the (17,19) pocket. Step (17,19) -> warp 7 -> arrive (17,33). Walk north along x=17..19 to (18,29), press A -> Full Restore. Postcondition EVENT_VICTORY_ROAD_FULL_RESTORE. Return to y=34 (x=16..19) and press DOWN to hop the ledge, landing on y=36 - which is already the y=36 corridor, so go west to (13,36) and north to (13,31), warp 4, back to (13,17).
  10. From (13,17): (13,16) -> east along y=16 to (18,16) -> north along x=18 through (18,15), (18,14), (18,13) (the rival's masked object tile), (18,12) to (18,11) -> west along y=11 to (13,11) -> north (13,10), (13,9) to (13,8).
  11. Step (12,8) or (13,8) -> rival ambush. Precondition wVictoryRoadSceneID = 0. Battle RIVAL1 member 13/14/15 depending on the starter events. Postconditions: EVENT_RIVAL_VICTORY_ROAD set, wVictoryRoadSceneID = SCENE_VICTORYROAD_NOOP.
  12. TM26 detour. The x=6,7 wall pair on y=10 and the x=5..8 wall run on y=11 mean you cannot walk straight west; the verified chain is (9,11) -> (9,10) -> (8,10) -> (8,9) -> west along y=9 to (5,9) -> (5,10) -> west along y=10 to (0,10) -> (0,11), the COLL_PIT, which fires on arrival -> land at (0,27). Then (0,28) -> east along y=28 to (2,28), press A facing RIGHT into the ball object at (3,28) -> TM26 Earthquake (EVENT_VICTORY_ROAD_TM_EARTHQUAKE). Optionally step to (2,29) and press A facing RIGHT into the wall at (3,29) -> hidden Max Potion (EVENT_VICTORY_ROAD_HIDDEN_MAX_POTION).
  13. Leave the pocket: east along y=28 to (7,28) -> step onto (8,28), the HOP_RIGHT tile -> press RIGHT to hop to (10,28) -> (10,29) -> east to (12,29) -> (12,30) -> (12,31) -> step (13,31) -> warp 4 -> (13,17). (Alternative, longer: stand on (2,30) or (3,30) and press DOWN, landing at y=32, which drops you back in the (1,35) ladder pocket and forces a full re-cross of the middle region via steps 7 and 8.)
  14. Repeat step 10 to return to the exit corridor. The coord events no longer fire.
  15. Walk (13,7) -> (13,6) -> step (13,5) (COLL_CAVE) -> warp 10 -> MAP_ROUTE_23 (9,13). End of section.

5. Port coverage

Beat Port file Status
Map header, dimensions, warps, coord events, bg events, object events for any Gold map src/import/RomExtractorGen2.lua (map event reader at lines 785-865, extractMaps from 866) implemented - data driven off the ROM, so VICTORY_ROAD needs no hand port
OBJECTTYPE_ITEMBALL item data extraction src/import/RomExtractorGen2.lua:2968 (obj.itemball = readItemBall(...)) implemented (extraction only)
Picking up a Poke Ball object (all five Victory Road items) src/world/gen2/World.lua:5257 World:interact missing - the A-press path handles trainers, strength boulders, scriptKey NPCs, BGEVENT_READ signs, BGEVENT_ITEM hidden items and the tile-collision field moves. Nothing consumes obj.itemball, and an itemball object has no scriptKey, so the press falls through
Hidden items (BGEVENT_ITEM, the two here) src/world/gen2/HiddenItems.lua, used at src/world/gen2/World.lua:5290 implemented
Ladder / cave / pit warps src/world/gen2/Permissions.lua:162 isWarpCollision (covers $60 PIT and the $7x block) and isImmediateWarp implemented - the (0,11) hole and all six ladders work
Warp carpet needing a direction press (the (9,67) entrance) src/world/gen2/Permissions.lua:170 CARPET_DIR implemented
Walkability from CollisionPermissionTable src/world/gen2/Permissions.lua:11 (256-entry table), src/world/gen2/Map.lua:59 implemented
Ledge hops (COLL_HOP_LEFT/RIGHT/DOWN, five of them in this map) - missing - no $a0..$a7 handling anywhere under src/world/gen2/. The tiles are LAND in the port's permission table, so a bot can walk over them freely. Net effect: the one-way ledges become two-way, and the Full Restore shelf / TM pocket exits behave differently from the cart
Directional side walls (COLL_UP_WALL, heavily used here) src/world/gen2/FieldMoves.lua:313 BLOCKED_BY partial - the $b0..$b7 table exists but is only consulted by FieldMoves.directionBlocked for surf/field-move refusals. There is no port equivalent of GetMovementPermissions (home/map.asm:1868), so UP_WALL does not restrict ordinary walking
Coord events gated on the map scene src/world/gen2/World.lua:5007 World:tryCoordScript, scene storage at World.lua:740 / World:scene at 1161 implemented
Scene scripts / setscene persistence across save src/world/gen2/World.lua:558-584, src/core/gen2/Save.lua implemented
Rival ambush opcodes (moveobject, turnobject, showemote, appear, disappear, applymovement, scall, setscene, playmapmusic, playmusic, winlosstext, setlasttalked, loadtrainer, startbattle, dontrestartmapmusic, reloadmapafterbattle) src/script/gen2/Opcodes.lua (table), src/script/gen2/Vm.lua (moveobject 337, showemote 961, loadtrainer 806, winlosstext 918, reloadmapafterbattle 886) implemented
special FadeOutMusic src/script/gen2/Specials.lua:1066 implemented
VAR_BADGES (the gate check) src/world/gen2/World.lua:1240 - counts player.badges + player.kantoBadges, matching CountSetBits over two bytes implemented
Object masking by event flag src/import/RomExtractorGen2.lua object eventFlag field; src/world/gen2/Npc.lua partial - the flag is extracted, but confirm the mask polarity (hidden when set) matches CheckObjectFlag; not verified in this pass
Wild encounters for this map src/import/RomExtractorGen2.lua:3720 (JohtoGrassWildMons / KantoGrassWildMons), src/battle/gen2/Encounter.lua implemented
Battle music landmark split src/battle/gen2/BattleMusic.lua:45-56 explicitly names the Victory Road landmark boundary implemented
A driver that walks Victory Road - missing - no tests/drivers/gold_*.lua mentions Victory Road

6. Unresolved / verify by hand

  • Rival Magneton level. The FAQ says "Level 34 Magneton". The asm has 35 in RIVAL1 (13) and RIVAL1 (14) and 34 only in RIVAL1 (15), the Feraligatr set loaded when the player picked Cyndaquil. The FAQ appears to have been written from one playthrough.
  • Rival party order. The FAQ lists the starter evolution fourth. The asm order is Sneasel, Golbat, Magneton, Haunter, Kadabra, starter (starter last).
  • "You get: 2280G" and the per-mon EXP figures were not verified; base money for the RIVAL1 class lives in the trainer class attribute table, which was not opened for this pass.
  • Wild list. The FAQ lists only Golbat, Graveler, Rhyhorn and "Donphan (Silver only)". The asm table also carries Onix (two slots, L34 and L36) and, in Gold, Ursaring at L33 in the slot Silver gives to Donphan.
  • Item list. The FAQ's item list omits the hidden Max Potion at (3,29) and does not distinguish the itemball Full Heal at (15,48) from the hidden Full Heal at (3,65).
  • "Head up the stairway" - there is no COLL_STAIRCASE in the decoded Victory Road map. What the FAQ calls stairways and cliffs are ordinary floor plus the COLL_UP_WALL strips; the only vertical transitions are the six ladders, the pit and the five ledges.
  • "Head back up the ladder to get back to the third floor" (after TM26). There is no ladder inside the TM pocket. The two ways out are the HOP_RIGHT at (8,28)/(8,29) into the x=10..13 corridor that reaches the (13,31) ladder, and the HOP_DOWN at (2,30)/(3,30) into the (1,35) pocket. The checklist above prefers the first; which one the FAQ author meant is not recoverable from the text.
  • X Special tile. The Poke Ball at (7,38) sits on a COLL_HOP_LEFT tile with COLL_WALL on both sides and above. Ledge tiles are LAND_TILE in CollisionPermissionTable, so the column x=7, y=38..41 is walkable from (7,42) upward and the ball is reachable; but this should be confirmed on hardware or in an emulator, because it is the one placement in this map that looks like a mistake rather than a design.
  • The gate's black belts as physical blockers. The claim that VICTORYROADGATE_BLACK_BELT1 at (7,5) and BLACK_BELT2 at (12,5) block the only east-west corridor is inferred from the decoded gate collision (row 5 is the sole corridor and rows 4/6 are walls beside it) plus the fact that NPCs are solid. It is not stated in any script, and it belongs to later sections (Route 28 / Route 22) rather than this one.
  • Object flag polarity in the port was not tested; see the Port coverage row.