Files
gen1recomp/docs/gold-walkthrough/asm-walk/section-11-team-rocket-hideout-and-mahogany-town-gym.md
T
bryanthaboi ae6cac89e1 G2 support
2026-08-11 11:53:30 -04:00

57 KiB

Section 11 - Team Rocket Hideout and Mahogany Town Gym

Source: ../section-11-team-rocket-hideout-and-mahogany-town-gym.txt (the FAQ's own heading is "17 > Team Rocket Hideout and Mahogany Town Gym")

Maps covered: MAP_MAHOGANY_TOWN, MAP_MAHOGANY_POKECENTER_1F, MAP_MAHOGANY_MART_1F, MAP_TEAM_ROCKET_BASE_B1F, MAP_TEAM_ROCKET_BASE_B2F, MAP_TEAM_ROCKET_BASE_B3F, MAP_MAHOGANY_GYM

Badges / key milestones in this section:

  • EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART - the hideout entrance exists
  • EVENT_LEARNED_SLOWPOKETAIL, EVENT_LEARNED_RATICATE_TAIL - Giovanni's-office door
  • EVENT_LEARNED_HAIL_GIOVANNI - transmitter-room door
  • EVENT_GOT_HM06_WHIRLPOOL (HM06 = HM_WHIRLPOOL)
  • EVENT_CLEARED_ROCKET_HIDEOUT + clearflag ENGINE_ROCKET_SIGNAL_ON_CH20
  • ENGINE_GLACIERBADGE (GLACIERBADGE, badge 7) + EVENT_GOT_TM16_ICY_WIND (TM16 = TM_ICY_WIND)

Entry precondition, set in the previous section: maps/LakeOfRage.asm LakeOfRageLanceScript.AgreedToHelp runs clearevent EVENT_MAHOGANY_MART_LANCE_AND_DRAGONITE, setevent EVENT_DECIDED_TO_HELP_LANCE, setmapscene MAHOGANY_MART_1F, SCENE_MAHOGANYMART1F_LANCE_UNCOVERS_STAIRS. Without that scene set, the mart is an ordinary shop and there is no staircase.


1. Route order

# Map constant asm file Enter via Leaves via Why (walkthrough beat)
1 MAP_MAHOGANY_TOWN maps/MahoganyTown.asm from Route 43 gate (warp 5, 9,1) or fly point ENGINE_FLYPOINT_MAHOGANY warp 4 15,13 -> Pokecenter, warp 1 11,7 -> Mart "Heal at the Pokemon Center and withdraw your Gyarados"
2 MAP_MAHOGANY_POKECENTER_1F maps/MahoganyPokecenter1F.asm warp 1/2 3,7 / 4,7 same heal / PC withdraw
3 MAP_MAHOGANY_MART_1F maps/MahoganyMart1F.asm warp 1/2 3,7 / 4,7 warp 3 7,3 Lance's Dragonite Hyper Beams the shop open, uncovers the staircase
4 MAP_TEAM_ROCKET_BASE_B1F maps/TeamRocketBaseB1F.asm warp 1 27,2 warp 2 3,14 security cameras, GruntM16, Scientist Jed, secret switch, 3 item balls
5 MAP_TEAM_ROCKET_BASE_B2F (bottom region) maps/TeamRocketBaseB2F.asm warp 1 3,14 warp 5 27,14 Lance heals you; GruntM19 then GruntM17
6 MAP_TEAM_ROCKET_BASE_B3F (right region) maps/TeamRocketBaseB3F.asm warp 4 27,14 warp 2 27,2 Lance's two-password speech, 4 item balls, Ross / GruntF5 / Mitch / GruntM28, both passwords
7 MAP_TEAM_ROCKET_BASE_B2F (top region) maps/TeamRocketBaseB2F.asm warp 3 27,2 warp 2 3,2 walk left past GruntM18
8 MAP_TEAM_ROCKET_BASE_B3F (left region) maps/TeamRocketBaseB3F.asm warp 1 3,2 warp 3 3,6 rival cutscene, password door, ExecutiveM 4, Murkrow gives HAIL GIOVANNI
9 MAP_TEAM_ROCKET_BASE_B2F (TM room) maps/TeamRocketBaseB2F.asm warp 4 3,6 warp 4 3,6 "the second stairs that you did NOT come out of" - TM46 Thief at 3,10
10 back through 8 -> 7 -> 6 -> 5 "Head back the way you came, past the spinning Team Rocket member"
11 MAP_TEAM_ROCKET_BASE_B2F (transmitter room) maps/TeamRocketBaseB2F.asm password door at 14,12 / 15,12 warp 1 3,14 (then B1F warp panel 5,15) ExecutiveF 2 ambush, 3 Electrode, HM06 Whirlpool from Lance
12 MAP_MAHOGANY_TOWN maps/MahoganyTown.asm Mart warps 1/2 warp 3 6,13 heal, then the gym
13 MAP_MAHOGANY_GYM maps/MahoganyGym.asm warp 1/2 4,17 / 5,17 same five ice-puzzle trainers, then Pryce -> GLACIERBADGE + TM16

Spill into the next section: the last paragraph ("You can now use Whirlpool, once you find that in a dark cavern") points at MAP_ICE_PATH_1F / MAP_ICE_PATH_B2F_MAHOGANY_SIDE. Not covered here.


2. Maps

MAP_MAHOGANY_TOWN

  • Script: maps/MahoganyTown.asm
  • Blocks: maps/MahoganyTown.blk
  • Header: data/maps/maps.asm:74 -> map MahoganyTown, TILESET_JOHTO, TOWN, LANDMARK_MAHOGANY_TOWN, MUSIC_CHERRYGROVE_CITY, FALSE, PALETTE_AUTO, FISHGROUP_SHORE
  • Dimensions: constants/map_constants.asm -> map_const MAHOGANY_TOWN, 10, 9 (group MAHOGANY = 2, map id 7); 10x9 blocks = 20x18 map cells
  • Connections: data/maps/attributes.asm:152-155 -> north Route43, west Route42, east Route44
  • Scene ids (declared inline by scene_script): SCENE_MAHOGANYTOWN_TRY_RAGECANDYBAR = 0, SCENE_MAHOGANYTOWN_NOOP = 1
  • Callback: MAPCALLBACK_NEWMAP, MahoganyTownFlypointCallback -> setflag ENGINE_FLYPOINT_MAHOGANY

Warps (def_warp_events)

idx x y destination map dest warp
1 11 7 MAHOGANY_MART_1F 1
2 17 7 MAHOGANY_RED_GYARADOS_SPEECH_HOUSE 1
3 6 13 MAHOGANY_GYM 1
4 15 13 MAHOGANY_POKECENTER_1F 1
5 9 1 ROUTE_43_MAHOGANY_GATE 3

Coord events (def_coord_events)

scene x y script label effect
SCENE_MAHOGANYTOWN_TRY_RAGECANDYBAR (0) 19 8 MahoganyTownTryARageCandyBarScript merchant steps in front of you and pitches a RAGECANDYBAR
SCENE_MAHOGANYTOWN_TRY_RAGECANDYBAR (0) 19 9 MahoganyTownTryARageCandyBarScript same

The script never calls setscene, so the pitch re-fires every time you cross x=19 until RadioTowerRocketsScript (engine/events/std_scripts.asm:263) runs setmapscene MAHOGANY_TOWN, SCENE_MAHOGANYTOWN_NOOP.

BG events (def_bg_events)

x y type script/item
1 5 BGEVENT_READ MahoganyTownSign
9 7 BGEVENT_READ MahoganyTownRagecandybarSign
3 13 BGEVENT_READ MahoganyGymSign
16 13 BGEVENT_READ MahoganyTownPokecenterSign

Object events (def_object_events)

const sprite x y movement type script label event flag
MAHOGANYTOWN_POKEFAN_M SPRITE_POKEFAN_M 19 8 STANDING_DOWN OBJECTTYPE_SCRIPT MahoganyTownPokefanMScript EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_EAST
MAHOGANYTOWN_GRAMPS SPRITE_GRAMPS 6 9 WALK_LEFT_RIGHT (radius 1,0) OBJECTTYPE_SCRIPT MahoganyTownGrampsScript -1
MAHOGANYTOWN_FISHER SPRITE_FISHER 6 14 STANDING_DOWN OBJECTTYPE_SCRIPT MahoganyTownFisherScript EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM
MAHOGANYTOWN_LASS SPRITE_LASS 12 8 STANDING_DOWN OBJECTTYPE_SCRIPT MahoganyTownLassScript EVENT_MAHOGANY_MART_OWNERS

Object-event flag polarity (verified in engine/overworld/map_objects_2.asm CheckObjectFlag): the flag being set masks (hides) the object; -1 means always visible. So EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM clear = the fisher stands on 6,14, one cell south of the gym warp at 6,13, blocking it. That flag is set by RocketBaseElectrodeScript at the end of the hideout, which is the real gate on the Mahogany gym (see section 3).

MAP_MAHOGANY_POKECENTER_1F

  • Script: maps/MahoganyPokecenter1F.asm
  • Header: data/maps/maps.asm:70 -> TILESET_POKECENTER, INDOOR, LANDMARK_MAHOGANY_TOWN, MUSIC_POKEMON_CENTER, FALSE, PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const MAHOGANY_POKECENTER_1F, 5, 4 (group 2, map id 3)

Warps

idx x y destination map dest warp
1 3 7 MAHOGANY_TOWN 4
2 4 7 MAHOGANY_TOWN 4
3 0 7 POKECENTER_2F 1

No coord events, no bg events. Nurse is MAHOGANYPOKECENTER1F_NURSE SPRITE_NURSE at 3,1, script MahoganyPokecenter1FNurseScript -> jumpstd PokecenterNurseScript.

MAP_MAHOGANY_MART_1F

  • Script: maps/MahoganyMart1F.asm (45:4000 MahoganyMart1F_MapScripts)
  • Blocks: shares maps/GiftShop.blk (data/maps/blocks.asm:700 -> MahoganyMart1F_Blocks: MountMoonGiftShop_Blocks: INCBIN "maps/GiftShop.blk")
  • Header: data/maps/maps.asm:118 -> TILESET_TRADITIONAL_HOUSE, INDOOR, LANDMARK_MAHOGANY_TOWN, MUSIC_MAHOGANY_MART, TRUE (no phone), PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const MAHOGANY_MART_1F, 4, 4 (group DUNGEONS = 3, map id 40)
  • Scene ids: SCENE_MAHOGANYMART1F_NOOP = 0, SCENE_MAHOGANYMART1F_LANCE_UNCOVERS_STAIRS = 1
  • Callback: MAPCALLBACK_TILES, MahoganyMart1FStaircaseCallback - if EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART is set, changeblock 6, 2, $1e ; stairs

Warps

idx x y destination map dest warp
1 3 7 MAHOGANY_TOWN 1
2 4 7 MAHOGANY_TOWN 1
3 7 3 TEAM_ROCKET_BASE_B1F 1

def_coord_events and def_bg_events are both empty.

Object events

const sprite x y movement type script label event flag
MAHOGANYMART1F_PHARMACIST SPRITE_PHARMACIST 4 3 STANDING_DOWN OBJECTTYPE_SCRIPT MahoganyMart1FPharmacistScript EVENT_TEAM_ROCKET_BASE_POPULATION
MAHOGANYMART1F_BLACK_BELT SPRITE_BLACK_BELT 1 6 SPINRANDOM_SLOW OBJECTTYPE_SCRIPT MahoganyMart1FBlackBeltScript EVENT_TEAM_ROCKET_BASE_POPULATION
MAHOGANYMART1F_LANCE SPRITE_LANCE 4 6 STANDING_LEFT OBJECTTYPE_SCRIPT ObjectEvent EVENT_MAHOGANY_MART_LANCE_AND_DRAGONITE
MAHOGANYMART1F_DRAGONITE SPRITE_DRAGON 3 6 STANDING_LEFT OBJECTTYPE_SCRIPT ObjectEvent EVENT_MAHOGANY_MART_LANCE_AND_DRAGONITE
MAHOGANYMART1F_GRANNY SPRITE_GRANNY 1 3 STANDING_RIGHT OBJECTTYPE_SCRIPT MahoganyMart1FGrannyScript EVENT_MAHOGANY_MART_OWNERS

Scripts of interest

MahoganyMart1FLanceUncoversStaircaseScript (45:4046), reached as scene_script ... SCENE_MAHOGANYMART1F_LANCE_UNCOVERS_STAIRS via sdefer, so it fires on map entry without any player input:

  1. Dragonite big_step LEFT / big_step RIGHT into the Black Belt, disappear MAHOGANYMART1F_DRAGONITE
  2. Lance walks over (MahoganyMart1FLanceApproachPlayerMovement), follow MAHOGANYMART1F_LANCE, PLAYER, shoves the pharmacist aside
  3. changeblock 6, 2, $1e + refreshmap + setevent EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART
  4. disappear MAHOGANYMART1F_LANCE, setscene SCENE_MAHOGANYMART1F_NOOP

changeblock's operands are map cell coordinates, not block coordinates (Script_changeblock at engine/overworld/scripting.asm:2031 adds 4 to each and calls GetBlockLocation, which halves them - home/map.asm:2099). 6,2 is therefore block (3,1), covering cells (6..7, 2..3); block $1e in data/tilesets/traditional_house_collision.asm is FLOOR, FLOOR, FLOOR, LADDER, putting the LADDER on cell 7,3 - exactly the warp row above.

Marts: MahoganyMart1FPharmacistScript -> pokemart MARTTYPE_STANDARD, MART_MAHOGANY_1 (closed once EVENT_DECIDED_TO_HELP_LANCE is set), MahoganyMart1FGrannyScript -> pokemart MARTTYPE_STANDARD, MART_MAHOGANY_2.

MAP_TEAM_ROCKET_BASE_B1F

  • Script: maps/TeamRocketBaseB1F.asm (45:430c TeamRocketBaseB1F_MapScripts)
  • Blocks: maps/TeamRocketBaseB1F.blk
  • Header: data/maps/maps.asm:119 -> TILESET_UNDERGROUND, DUNGEON, LANDMARK_MAHOGANY_TOWN, MUSIC_ROCKET_HIDEOUT, TRUE, PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const TEAM_ROCKET_BASE_B1F, 15, 9 (group 3, map id 41) = 30x18 cells
  • Scene ids: SCENE_TEAMROCKETBASEB1F_TRAPS = 0 (the only one)
  • Callback: MAPCALLBACK_OBJECTS, TeamRocketBaseB1FHideSecurityGruntCallback -> disappear TEAMROCKETBASEB1F_ROCKET1 (the camera grunt is parked off-screen at 0,0 and teleported in by moveobject)

The whole floor is one connected walkable region (flood-filled from maps/TeamRocketBaseB1F.blk against data/tilesets/underground_collision.asm).

Warps

idx x y destination map dest warp
1 27 2 MAHOGANY_MART_1F 3
2 3 14 TEAM_ROCKET_BASE_B2F 1
3 5 15 TEAM_ROCKET_BASE_B1F 4
4 25 2 TEAM_ROCKET_BASE_B1F 3

Warps 3 and 4 are the warp panel pair Scientist Jed describes: cell 5,15 has collision WARP_PANEL and dumps you at 25,2, two cells from the exit ladder.

Coord events (def_coord_events) - all on scene SCENE_TEAMROCKETBASEB1F_TRAPS (0)

Security cameras (each triggers GRUNTM_20 then GRUNTM_21):

x y script label guarding statue (bg_event)
24 2 SecurityCamera1a 24,1
24 3 SecurityCamera1b 24,1
6 2 SecurityCamera2a 6,1
6 3 SecurityCamera2b 6,1
24 6 SecurityCamera3a 24,5
24 7 SecurityCamera3b 24,5
22 16 SecurityCamera4 22,15
8 16 SecurityCamera5 8,15

Exploding-trap tiles (each is a one-shot wild battle with loadvar VAR_BATTLETYPE, BATTLETYPE_TRAP):

x y script mon
2 7 ExplodingTrap1 KoffingExplodingTrap - KOFFING L21
3 7 ExplodingTrap2 VoltorbExplodingTrap - VOLTORB L23
4 7 ExplodingTrap3 GeodudeExplodingTrap - GEODUDE L21
1 8 ExplodingTrap4 VOLTORB L23
3 8 ExplodingTrap5 GEODUDE L21
5 8 ExplodingTrap6 KOFFING L21
3 9 ExplodingTrap7 VOLTORB L23
4 9 ExplodingTrap8 KOFFING L21
1 10 ExplodingTrap9 KOFFING L21
2 10 ExplodingTrap10 VOLTORB L23
3 10 ExplodingTrap11 GEODUDE L21
5 10 ExplodingTrap12 GEODUDE L21
2 11 ExplodingTrap13 GEODUDE L21
4 11 ExplodingTrap14 KOFFING L21
1 12 ExplodingTrap15 VOLTORB L23
2 12 ExplodingTrap16 KOFFING L21
4 12 ExplodingTrap17 VOLTORB L23
5 12 ExplodingTrap18 GEODUDE L21
1 13 ExplodingTrap19 GEODUDE L21
3 13 ExplodingTrap20 VOLTORB L23
4 13 ExplodingTrap21 KOFFING L21
5 13 ExplodingTrap22 VOLTORB L23

Safe cells inside the 5x7 trap field (x 1..5, y 7..13) are exactly those with no row above: (1,7), (5,7), (2,8), (4,8), (1,9), (2,9), (5,9), (4,10), (1,11), (3,11), (5,11), (3,12), (2,13). (3,11) is also the hidden REVIVE. That is the "zig-zag" the walkthrough describes.

BG events

x y type script/item
19 11 BGEVENT_READ TeamRocketBaseB1FSecretSwitch
24 1 BGEVENT_UP TeamRocketBaseB1FSecurityCamera
6 1 BGEVENT_UP TeamRocketBaseB1FSecurityCamera
8 15 BGEVENT_UP TeamRocketBaseB1FSecurityCamera
22 15 BGEVENT_UP TeamRocketBaseB1FSecurityCamera
24 5 BGEVENT_UP TeamRocketBaseB1FSecurityCamera
20 11 BGEVENT_READ TeamRocketBaseB1FBookshelf (jumpstd TeamRocketOathScript)
21 11 BGEVENT_READ TeamRocketBaseB1FBookshelf
3 11 BGEVENT_ITEM TeamRocketBaseB1FHiddenRevive -> hiddenitem REVIVE, EVENT_TEAM_ROCKET_BASE_B1F_HIDDEN_REVIVE

Object events

const sprite x y movement type sight script label event flag
TEAMROCKETBASEB1F_ROCKET1 SPRITE_ROCKET 0 0 STANDING_DOWN OBJECTTYPE_SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_SECURITY_GRUNTS
- SPRITE_ROCKET 2 4 STANDING_RIGHT OBJECTTYPE_TRAINER 3 TrainerGruntM16 EVENT_TEAM_ROCKET_BASE_POPULATION
- SPRITE_SCIENTIST 18 12 STANDING_LEFT OBJECTTYPE_TRAINER 3 TrainerScientistJed EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB1F_POKE_BALL1 SPRITE_POKE_BALL 27 6 STILL OBJECTTYPE_ITEMBALL 0 TeamRocketBaseB1FHyperPotion EVENT_TEAM_ROCKET_BASE_B1F_HYPER_POTION
TEAMROCKETBASEB1F_POKE_BALL2 SPRITE_POKE_BALL 14 15 STILL OBJECTTYPE_ITEMBALL 0 TeamRocketBaseB1FNugget EVENT_TEAM_ROCKET_BASE_B1F_NUGGET
TEAMROCKETBASEB1F_POKE_BALL3 SPRITE_POKE_BALL 21 12 STILL OBJECTTYPE_ITEMBALL 0 TeamRocketBaseB1FXAccuracy EVENT_TEAM_ROCKET_BASE_B1F_X_ACCURACY

Scripts of interest

  • SecurityCamera1a .. SecurityCamera5: checkevent EVENT_SECURITY_CAMERA_n -> bail; PlaySecurityCameraSounds (6x SFX_LICK); checkevent EVENT_TEAM_ROCKET_BASE_POPULATION -> bail (never true, see below); showemote EMOTE_SHOCK, PLAYER; playmusic MUSIC_ROCKET_ENCOUNTER; moveobject TEAMROCKETBASEB1F_ROCKET1, <x>, <y>; appear; applymovement SecurityCameraMovement*; scall TrainerCameraGrunt1; repeat for TrainerCameraGrunt2; setevent EVENT_SECURITY_CAMERA_n. Both grunt scripts use loadtrainer + startbattle directly (no trainer macro, so no per-trainer beat flag) - the same two teams are re-fought at every camera.
  • TeamRocketBaseB1FSecretSwitch (45:4757): if EVENT_TURNED_OFF_SECURITY_CAMERAS is already set, prints "the switch is turned off"; otherwise playsound SFX_TALLY and sets EVENT_TURNED_OFF_SECURITY_CAMERAS + EVENT_SECURITY_CAMERA_1..5 in one go. Cell 19,11 is a wall, read from 19,12 facing up.
  • TrainerScientistJed -> .Script after-battle text tells you about the warp panel.
  • TrainerGruntM16 -> after-battle text about the traps.

Flags and events (B1F)

constant defined in read/written by meaning for a bot
EVENT_SECURITY_CAMERA_1 .. _5 constants/event_flags.asm:403-407 set by each camera script and by the switch camera n is spent
EVENT_TURNED_OFF_SECURITY_CAMERAS event_flags.asm:402 TeamRocketBaseB1FSecretSwitch, RocketBaseElectrodeScript switch state only
EVENT_TEAM_ROCKET_BASE_SECURITY_GRUNTS event_flags.asm:1147 disappear/appear of TEAMROCKETBASEB1F_ROCKET1 ambush grunt visibility
EVENT_TEAM_ROCKET_BASE_POPULATION event_flags.asm:1148 read by 8 camera scripts, shared visibility flag of 11 base NPCs never set anywhere in the ROM - grep confirms no setevent/disappear on it, so those checkevent arms are dead and the base NPCs never vanish
EVENT_TEAM_ROCKET_BASE_B1F_HYPER_POTION / _NUGGET / _X_ACCURACY event_flags.asm:1034-1036 itemball item ball taken
EVENT_TEAM_ROCKET_BASE_B1F_HIDDEN_REVIVE event_flags.asm:144 hiddenitem hidden REVIVE at 3,11 taken
EVENT_EXPLODING_TRAP_1..22 constants/event_flags.asm each ExplodingTrapN trap spent

Items (B1F)

item how obtained source one-time flag
HYPER_POTION item ball at 27,6 TeamRocketBaseB1FHyperPotion EVENT_TEAM_ROCKET_BASE_B1F_HYPER_POTION
NUGGET item ball at 14,15 TeamRocketBaseB1FNugget EVENT_TEAM_ROCKET_BASE_B1F_NUGGET
X_ACCURACY item ball at 21,12 TeamRocketBaseB1FXAccuracy EVENT_TEAM_ROCKET_BASE_B1F_X_ACCURACY
REVIVE hidden, face cell 3,11 bg_event 3, 11, BGEVENT_ITEM EVENT_TEAM_ROCKET_BASE_B1F_HIDDEN_REVIVE

Trainers (B1F)

const class id party (data/trainers/parties.asm) script label notes
GRUNTM, GRUNTM_16 GRUNTM ($1f) 16 RATTATA 16, RATTATA 16, RATTATA 16, RATTATA 16 TrainerGruntM16 EVENT_BEAT_ROCKET_GRUNTM_16, sight 3
SCIENTIST, JED SCIENTIST ($0e) 3 MAGNEMITE 20 x3 TrainerScientistJed EVENT_BEAT_SCIENTIST_JED, sight 3
GRUNTM, GRUNTM_20 GRUNTM 20 DROWZEE 17, ZUBAT 19 TrainerCameraGrunt1 no beat flag, repeats per camera
GRUNTM, GRUNTM_21 GRUNTM 21 ZUBAT 16, GRIMER 17, RATTATA 18 TrainerCameraGrunt2 no beat flag, repeats per camera

Wild encounters: none. TEAM_ROCKET_BASE_B1F has no entry in data/wild/johto_grass.asm, johto_water.asm, fish.asm or treemons.asm. The only wild battles are the loadwildmon traps above and the three Electrode on B2F.

MAP_TEAM_ROCKET_BASE_B2F

  • Script: maps/TeamRocketBaseB2F.asm (45:4c2b TeamRocketBaseB2F_MapScripts)
  • Blocks: maps/TeamRocketBaseB2F.blk
  • Header: data/maps/maps.asm:120 -> TILESET_FACILITY, DUNGEON, LANDMARK_MAHOGANY_TOWN, MUSIC_ROCKET_HIDEOUT, TRUE, PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const TEAM_ROCKET_BASE_B2F, 15, 9 (group 3, map id 42) = 30x18 cells
  • Scene ids: SCENE_TEAMROCKETBASEB2F_LANCE_HEALS = 0, ..._ROCKET_BOSS = 1, ..._ELECTRODES = 2, ..._NOOP = 3
  • Callback: MAPCALLBACK_TILES, TeamRocketBaseB2FTransmitterDoorCallback - if EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER, changeblock 14, 12, $07 ; floor

Walkable regions (flood fill of maps/TeamRocketBaseB2F.blk against data/tilesets/facility_collision.asm) - this floor is four disconnected rooms:

region contents
top corridor warp 2 3,2, warp 3 27,2, GruntM18 2,1
transmitter room boss coord 14,11/15,11, Electrodes 7,5/7,7/7,9 and 22,5/22,7/22,9; sealed until the password door opens
TM room warp 4 3,6, TM_THIEF item ball 3,10
bottom corridor warp 1 3,14 (to B1F), warp 5 27,14, Lance heal coords, GruntM19 21,14, GruntM17 25,13

Warps

idx x y destination map dest warp
1 3 14 TEAM_ROCKET_BASE_B1F 2
2 3 2 TEAM_ROCKET_BASE_B3F 1
3 27 2 TEAM_ROCKET_BASE_B3F 2
4 3 6 TEAM_ROCKET_BASE_B3F 3
5 27 14 TEAM_ROCKET_BASE_B3F 4

Coord events

scene x y script label effect
LANCE_HEALS (0) 5 14 LanceHealsScript1 face UP, then LanceHealsCommon
LANCE_HEALS (0) 4 13 LanceHealsScript2 face RIGHT, then LanceHealsCommon
ROCKET_BOSS (1) 14 11 RocketBaseBossFLeft Executive F ambush (Lance spawns at 9,13)
ROCKET_BOSS (1) 15 11 RocketBaseBossFRight same, actors nudged one cell right
ELECTRODES (2) 14 12 RocketBaseCantLeaveScript shoves you back into the room
ELECTRODES (2) 15 12 RocketBaseCantLeaveScript same
ELECTRODES (2) 12 3 RocketBaseLancesSideScript "Leave this side to me", step LEFT
ELECTRODES (2) 12 10 RocketBaseLancesSideScript same
ELECTRODES (2) 12 11 RocketBaseLancesSideScript same

BG events

x y type script/item
14 12 BGEVENT_IFNOTSET conditional_event EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER, TeamRocketBaseB2FLockedDoor.Script
15 12 BGEVENT_IFNOTSET same
12..17, 4 and 9; 12, 5..8; 17, 5..8 (20 cells) BGEVENT_READ TeamRocketBaseB2FTransmitterScript
26 7 BGEVENT_ITEM TeamRocketBaseB2FHiddenFullHeal -> hiddenitem FULL_HEAL, EVENT_TEAM_ROCKET_BASE_B2F_HIDDEN_FULL_HEAL

Object events

const sprite x y movement type sight script label event flag
TEAMROCKETBASEB2F_ROCKET1 SPRITE_ROCKET 20 16 STANDING_UP SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_GRUNT_WITH_EXECUTIVE
TEAMROCKETBASEB2F_ROCKET_GIRL SPRITE_ROCKET_GIRL 20 16 STANDING_UP SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_EXECUTIVE
TEAMROCKETBASEB2F_LANCE SPRITE_LANCE 5 13 STANDING_DOWN SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_LANCE
TEAMROCKETBASEB2F_DRAGON SPRITE_DRAGON 9 13 STANDING_RIGHT SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_DRAGONITE
TEAMROCKETBASEB2F_ELECTRODE1 SPRITE_VOLTORB 7 5 POKEMON SCRIPT 0 RocketElectrode1 EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_1
TEAMROCKETBASEB2F_ELECTRODE2 SPRITE_VOLTORB 7 7 POKEMON SCRIPT 0 RocketElectrode2 EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_2
TEAMROCKETBASEB2F_ELECTRODE3 SPRITE_VOLTORB 7 9 POKEMON SCRIPT 0 RocketElectrode3 EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_3
TEAMROCKETBASEB2F_ELECTRODE4 SPRITE_VOLTORB 22 5 POKEMON SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_1
TEAMROCKETBASEB2F_ELECTRODE5 SPRITE_VOLTORB 22 7 POKEMON SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_2
TEAMROCKETBASEB2F_ELECTRODE6 SPRITE_VOLTORB 22 9 POKEMON SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_3
TEAMROCKETBASEB2F_ROCKET2 SPRITE_ROCKET 25 13 STANDING_DOWN TRAINER 3 TrainerGruntM17 EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB2F_ROCKET3 SPRITE_ROCKET 2 1 STANDING_RIGHT TRAINER 3 TrainerGruntM18 EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB2F_ROCKET4 SPRITE_ROCKET 21 14 STANDING_LEFT TRAINER 4 TrainerGruntM19 EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB2F_POKE_BALL SPRITE_POKE_BALL 3 10 STILL ITEMBALL 0 TeamRocketBaseB2FTMThief EVENT_TEAM_ROCKET_BASE_B2F_TM_THIEF

The Electrodes on the right (22,5/7/9) mirror the left three and share their flags; RocketElectrodeN disappears both of a pair, so Lance's three "count" without ever being battled.

Scripts of interest

  • LanceHealsCommon (45:4d4c): special FadeOutToWhite, playsound SFX_FULL_HEAL, special HealParty, special FadeInFromWhite, setscene SCENE_TEAMROCKETBASEB2F_ROCKET_BOSS, setevent EVENT_LANCE_HEALED_YOU_IN_TEAM_ROCKET_BASE, then readvar VAR_FACING picks one of two exit movements and disappear TEAMROCKETBASEB2F_LANCE. This is a hard ordering dependency: the boss ambush coord events only exist on scene 1, so the transmitter room cannot be entered until Lance has healed you.
  • TeamRocketBaseB2FLockedDoor (45:4e8f): conditional_event on EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER; .Script checks EVENT_LEARNED_HAIL_GIOVANNI. If known: playsound SFX_ENTER_DOOR, changeblock 14, 12, $07, refreshmap, setevent EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER.
  • RocketBaseBossFScript (45:4c67): cutscene, then loadtrainer EXECUTIVEF, EXECUTIVEF_2 + startbattle; sets EVENT_TEAM_ROCKET_BASE_B2F_EXECUTIVE, ..._GRUNT_WITH_EXECUTIVE, ..._LANCE, EVENT_BEAT_ROCKET_EXECUTIVEF_2; then setscene SCENE_TEAMROCKETBASEB2F_ELECTRODES, clearevent EVENT_TEAM_ROCKET_BASE_B2F_LANCE (re-showing Lance), the Electrode briefing, disappear TEAMROCKETBASEB2F_LANCE.
  • RocketElectrode1/2/3: cry ELECTRODE, loadwildmon ELECTRODE, 23, startbattle. iftrue TeamRocketBaseB2FReloadMap covers the "you lost/fled" path. After all three events are set, the player is auto-walked out by RocketBasePlayerLeavesElectrodesMovement1/2/3 into RocketBaseElectrodeScript. No BATTLETYPE_* is armed here, so these are catchable ordinary wild battles.
  • RocketBaseElectrodeScript (45:4e3c) - the section's payoff: verbosegiveitem HM_WHIRLPOOL, setevent EVENT_GOT_HM06_WHIRLPOOL, then setevent EVENT_CLEARED_ROCKET_HIDEOUT, clearflag ENGINE_ROCKET_SIGNAL_ON_CH20, setevent EVENT_ROUTE_43_GATE_ROCKETS, setevent EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM (hides the fisher -> gym opens), setscene SCENE_TEAMROCKETBASEB2F_NOOP, clearevent EVENT_LAKE_OF_RAGE_CIVILIANS, setevent EVENT_TURNED_OFF_SECURITY_CAMERAS + EVENT_SECURITY_CAMERA_1..5.

Items (B2F)

item how obtained source one-time flag
TM_THIEF (TM46) item ball at 3,10 (TM room) TeamRocketBaseB2FTMThief EVENT_TEAM_ROCKET_BASE_B2F_TM_THIEF
FULL_HEAL hidden, face cell 26,7 bg_event 26, 7, BGEVENT_ITEM EVENT_TEAM_ROCKET_BASE_B2F_HIDDEN_FULL_HEAL
HM_WHIRLPOOL (HM06) verbosegiveitem from Lance RocketBaseElectrodeScript EVENT_GOT_HM06_WHIRLPOOL

TM numbering check: constants/item_constants.asm add_tm THIEF ; ee is the 46th add_tm (the const ITEM_C3 / const ITEM_DC holes do not consume TM numbers), so TM46 = Thief, matching the walkthrough. add_tm ICY_WIND ; cf is the 16th = TM16.

Trainers (B2F)

const class id party script label sight
GRUNTM_17 GRUNTM 17 GOLBAT 18 TrainerGruntM17 3
GRUNTM_18 GRUNTM 18 RATTATA 17, ZUBAT 17, RATTATA 17 TrainerGruntM18 3
GRUNTM_19 GRUNTM 19 VENONAT 18, VENONAT 18 TrainerGruntM19 4
EXECUTIVEF_2 EXECUTIVEF ($37) 2 ARBOK 23 (WRAP/LEER/POISON_STING/BITE), GLOOM 23 (ABSORB/SWEET_SCENT/SLEEP_POWDER/ACID), MURKROW 25 (PECK/PURSUIT/HAZE/-) RocketBaseBossFScript cutscene

Wild encounters: none in the tables; only loadwildmon ELECTRODE, 23 x3.

MAP_TEAM_ROCKET_BASE_B3F

  • Script: maps/TeamRocketBaseB3F.asm (45:5c8c TeamRocketBaseB3F_MapScripts)
  • Blocks: maps/TeamRocketBaseB3F.blk
  • Header: data/maps/maps.asm:121 -> TILESET_FACILITY, DUNGEON, LANDMARK_MAHOGANY_TOWN, MUSIC_ROCKET_HIDEOUT, TRUE, PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const TEAM_ROCKET_BASE_B3F, 15, 9 (group 3, map id 43) = 30x18 cells
  • Scene ids: SCENE_TEAMROCKETBASEB3F_LANCE_GETS_PASSWORD = 0, ..._RIVAL_ENCOUNTER = 1, ..._ROCKET_BOSS = 2, ..._NOOP = 3
  • Callback: MAPCALLBACK_TILES, TeamRocketBaseB3FCheckGiovanniDoorCallback - if EVENT_OPENED_DOOR_TO_GIOVANNIS_OFFICE, changeblock 10, 8, $07 ; floor

Walkable regions (same flood-fill method):

region contents
left warp 1 3,2, warp 3 3,6, rival coord 8,10
Giovanni's office boss coords 10,8/11,8, ExecutiveM 8,3, Murkrow 7,2; sealed until both passwords
right / main warp 2 27,2, warp 4 27,14, Lance 25,14, GruntF5 21,7, GruntM28 5,15, Ross 25,12, Mitch 14,15, all four item balls

Warps

idx x y destination map dest warp
1 3 2 TEAM_ROCKET_BASE_B2F 2
2 27 2 TEAM_ROCKET_BASE_B2F 3
3 3 6 TEAM_ROCKET_BASE_B2F 4
4 27 14 TEAM_ROCKET_BASE_B2F 5

Coord events

scene x y script label effect
ROCKET_BOSS (2) 10 8 RocketBaseBossLeft auto-walk UP UP UP LEFT LEFT, then RocketBaseBoss
ROCKET_BOSS (2) 11 8 RocketBaseBossRight auto-walk UP UP LEFT UP LEFT LEFT, then RocketBaseBoss
RIVAL_ENCOUNTER (1) 8 10 RocketBaseRival rival cutscene, no battle

BG events

x y type script/item
10 9 BGEVENT_IFNOTSET conditional_event EVENT_OPENED_DOOR_TO_GIOVANNIS_OFFICE, TeamRocketBaseB3FLockedDoor.Script
11 9 BGEVENT_IFNOTSET same
10..13, 1 BGEVENT_READ TeamRocketBaseB3FOathScript (jumpstd TeamRocketOathScript)
4..7, 13 BGEVENT_READ TeamRocketBaseB3FOathScript

Object events

const sprite x y movement type sight script label event flag
TEAMROCKETBASEB3F_LANCE SPRITE_LANCE 25 14 STANDING_DOWN SCRIPT 0 LanceGetPasswordScript EVENT_TEAM_ROCKET_BASE_B3F_LANCE_PASSWORDS
TEAMROCKETBASEB3F_ROCKET1 SPRITE_ROCKET 8 3 STANDING_UP SCRIPT 0 ObjectEvent EVENT_TEAM_ROCKET_BASE_B3F_EXECUTIVE
TEAMROCKETBASEB3F_MOLTRES SPRITE_MOLTRES 7 2 POKEMON SCRIPT 0 RocketBaseMurkrow EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_ROCKET_GIRL SPRITE_ROCKET_GIRL 21 7 STANDING_UP TRAINER 0 SlowpokeTailGrunt EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_ROCKET2 SPRITE_ROCKET 5 15 SPINRANDOM_FAST TRAINER 3 RaticateTailGrunt EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_SCIENTIST1 SPRITE_SCIENTIST 25 12 STANDING_LEFT TRAINER 4 TrainerScientistRoss EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_SCIENTIST2 SPRITE_SCIENTIST 14 15 STANDING_UP TRAINER 3 TrainerScientistMitch EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_ROCKET3 SPRITE_ROCKET 24 14 STANDING_DOWN SCRIPT 0 TeamRocketBaseB3FRocketScript EVENT_TEAM_ROCKET_BASE_POPULATION
TEAMROCKETBASEB3F_RIVAL SPRITE_RIVAL 4 5 STANDING_DOWN SCRIPT 0 ObjectEvent EVENT_RIVAL_TEAM_ROCKET_BASE
TEAMROCKETBASEB3F_POKE_BALL1 SPRITE_POKE_BALL 1 12 STILL ITEMBALL 0 TeamRocketBaseB3FFullHeal EVENT_TEAM_ROCKET_BASE_B3F_FULL_HEAL
TEAMROCKETBASEB3F_POKE_BALL2 SPRITE_POKE_BALL 3 12 STILL ITEMBALL 0 TeamRocketBaseB3FDireHit EVENT_TEAM_ROCKET_BASE_B3F_DIRE_HIT
TEAMROCKETBASEB3F_POKE_BALL3 SPRITE_POKE_BALL 28 9 STILL ITEMBALL 0 TeamRocketBaseB3FProtein EVENT_TEAM_ROCKET_BASE_B3F_PROTEIN
TEAMROCKETBASEB3F_POKE_BALL4 SPRITE_POKE_BALL 17 2 STILL ITEMBALL 0 TeamRocketBaseB3FIceHeal EVENT_TEAM_ROCKET_BASE_B3F_ICE_HEAL

The Murkrow the walkthrough talks to is the object using SPRITE_MOLTRES at 7,2; its script is RocketBaseMurkrow and its text says MURKROW. The sprite constant is the generic large-bird overworld sprite, not a Moltres encounter.

Scripts of interest

  • LanceGetPasswordScript (45:5cb4): both the sdefer scene script for scene 0 and the Lance object's own script. Runs on entry to the right region, prints LanceGetPasswordText, disappear TEAMROCKETBASEB3F_LANCE (which sets EVENT_TEAM_ROCKET_BASE_B3F_LANCE_PASSWORDS), setscene SCENE_TEAMROCKETBASEB3F_RIVAL_ENCOUNTER.
  • SlowpokeTailGrunt -> trainer GRUNTF, GRUNTF_5, EVENT_BEAT_ROCKET_GRUNTF_5, ...; GruntF5Script (the after-battle arm) does setevent EVENT_LEARNED_SLOWPOKETAIL. Sight range 0 - she never initiates; the bot must walk up and talk, then talk a second time for the password.
  • RaticateTailGrunt -> trainer GRUNTM, GRUNTM_28, EVENT_BEAT_ROCKET_GRUNTM_28, ...; GruntM28Script does setevent EVENT_LEARNED_RATICATE_TAIL. Sight 3, SPINRANDOM_FAST (the "spinning Team Rocket member").
  • TeamRocketBaseB3FLockedDoor (45:5da9): .Script requires EVENT_LEARNED_SLOWPOKETAIL and EVENT_LEARNED_RATICATE_TAIL; on success changeblock 10, 8, $07, refreshmap, setevent EVENT_OPENED_DOOR_TO_GIOVANNIS_OFFICE.
  • RocketBaseRival (45:5cd1): appear TEAMROCKETBASEB3F_RIVAL, walk-in, dialogue, applymovement PLAYER, RocketBaseRivalShovesPlayerMovement (a big_step RIGHT with fix_facing), disappear, setscene SCENE_TEAMROCKETBASEB3F_ROCKET_BOSS. No battle - matches the walkthrough ("He can't battle you though").
  • RocketBaseBoss (45:5d0e): loadtrainer EXECUTIVEM, EXECUTIVEM_4, startbattle, setevent EVENT_BEAT_ROCKET_EXECUTIVEM_4, long exit movement, disappear TEAMROCKETBASEB3F_ROCKET1, setscene SCENE_TEAMROCKETBASEB3F_NOOP.
  • RocketBaseMurkrow (45:5d49): text, then setevent EVENT_LEARNED_HAIL_GIOVANNI.

Items (B3F)

item how obtained source one-time flag
FULL_HEAL item ball 1,12 TeamRocketBaseB3FFullHeal EVENT_TEAM_ROCKET_BASE_B3F_FULL_HEAL
DIRE_HIT item ball 3,12 TeamRocketBaseB3FDireHit EVENT_TEAM_ROCKET_BASE_B3F_DIRE_HIT
PROTEIN item ball 28,9 TeamRocketBaseB3FProtein EVENT_TEAM_ROCKET_BASE_B3F_PROTEIN
ICE_HEAL item ball 17,2 TeamRocketBaseB3FIceHeal EVENT_TEAM_ROCKET_BASE_B3F_ICE_HEAL

Trainers (B3F)

const class id party script label sight
SCIENTIST, ROSS SCIENTIST ($0e) 1 KOFFING 22, KOFFING 22 TrainerScientistRoss 4
SCIENTIST, MITCH SCIENTIST 2 DITTO 24 TrainerScientistMitch 3
GRUNTF, GRUNTF_5 GRUNTF ($42) 5 EKANS 18 (WRAP/LEER/POISON_STING/BITE), GLOOM 18 (ABSORB/SWEET_SCENT/STUN_SPORE/SLEEP_POWDER) SlowpokeTailGrunt 0
GRUNTM, GRUNTM_28 GRUNTM ($1f) 28 RATICATE 19 RaticateTailGrunt 3
EXECUTIVEM, EXECUTIVEM_4 EXECUTIVEM ($33) 4 ZUBAT 22, RATICATE 24, KOFFING 22 RocketBaseBoss cutscene

Wild encounters: none.

MAP_MAHOGANY_GYM

  • Script: maps/MahoganyGym.asm (51:536c MahoganyGym_MapScripts)
  • Blocks: maps/MahoganyGym.blk
  • Header: data/maps/maps.asm:69 -> map MahoganyGym, TILESET_ELITE_FOUR_ROOM, INDOOR, LANDMARK_MAHOGANY_TOWN, MUSIC_GYM, TRUE, PALETTE_DAY, FISHGROUP_SHORE
  • Dimensions: map_const MAHOGANY_GYM, 5, 9 (group 2, map id 2) = 10x18 cells
  • def_scene_scripts and def_callbacks are both empty

Warps

idx x y destination map dest warp
1 4 17 MAHOGANY_TOWN 3
2 5 17 MAHOGANY_TOWN 3

def_coord_events is empty.

BG events

x y type script/item
3 15 BGEVENT_READ MahoganyGymStatue
6 15 BGEVENT_READ MahoganyGymStatue

Object events

const sprite x y movement type sight script label event flag
MAHOGANYGYM_PRYCE SPRITE_PRYCE 5 3 STANDING_DOWN SCRIPT 0 MahoganyGymPryceScript -1
MAHOGANYGYM_BEAUTY1 SPRITE_BEAUTY 4 6 STANDING_DOWN TRAINER 1 TrainerSkierRoxanne -1
MAHOGANYGYM_ROCKER1 SPRITE_ROCKER 0 17 STANDING_UP TRAINER 1 TrainerBoarderRonald -1
MAHOGANYGYM_BEAUTY2 SPRITE_BEAUTY 9 17 STANDING_UP TRAINER 1 TrainerSkierClarissa -1
MAHOGANYGYM_ROCKER2 SPRITE_ROCKER 5 9 STANDING_DOWN TRAINER 1 TrainerBoarderBrad -1
MAHOGANYGYM_ROCKER3 SPRITE_ROCKER 2 4 SPINRANDOM_FAST TRAINER 1 TrainerBoarderDouglas -1
MAHOGANYGYM_GYM_GUIDE SPRITE_GYM_GUIDE 7 15 STANDING_DOWN SCRIPT 0 MahoganyGymGuideScript -1

Ice-floor map, decoded from maps/MahoganyGym.blk against data/tilesets/elite_four_room_collision.asm. I = COLL_ICE ($23), . = walkable floor, # = wall, v = warp carpet:

    x0123456789
 y0 ##########
 y1 ##########
 y2 .IIIII.I#I
 y3 IIIIIIII#I
 y4 I#I.I.IIII
 y5 I#IIII.III
 y6 I#IIIIIIII
 y7 I#II.IIII.
 y8 .IIIIIII#I
 y9 IIIIIIII#I
y10 I#.II.III.
y11 I#IIIII.II
y12 I#IIIIII#I
y13 I#I.II.I#I
y14 I#.#..#.#I
y15 I#.#..#.#I
y16 .I......I.
y17 II..vv..II

Sliding rule (engine/overworld/player_movement.asm): CheckIceTile on the tile you land on -> STEP_ICE; .CheckForced / CheckStandingOnIce re-injects the same d-pad direction, so a single press slides until you land on a non-ice tile, hit a wall, or hit an NPC.

Simulating that rule against the grid above (NPCs treated as blockers) reproduces the walkthrough's directions exactly:

from press lands on who
4,17 (warp) UP 4,16 -
4,16 LEFT, LEFT, LEFT 3,16 -> 2,16 -> 0,16 faces Boarder Ronald 0,17
0,16 UP,UP,RIGHT,DOWN,LEFT 0,8 -> 0,2 -> 6,2 -> 6,5 -> 2,5 faces Boarder Douglas 2,4
2,5 DOWN,RIGHT 2,10 -> 5,10 faces Boarder Brad 5,9
5,10 RIGHT,DOWN 9,10 -> 9,16 faces Skier Clarissa 9,17
9,16 UP,UP,LEFT 9,10 -> 9,7 -> 4,7 faces Skier Roxanne 4,6
4,7 DOWN 4,14 back toward the exit
2,14 ("just left of the left pillar", pillar block at 3,14/3,15) UP,UP,RIGHT,DOWN,LEFT,UP,RIGHT 2,10 -> 2,5 -> 6,5 -> 6,13 -> 3,13 -> 3,4 -> 5,4 standing directly below Pryce 5,3

Reaching 2,14 from the entrance: UP (to 4,16), LEFT (3,16), LEFT (2,16), UP (2,15), UP (2,14) - 2,15/2,16/2,14 are ordinary floor, not ice, so those are single steps.

Scripts of interest

MahoganyGymPryceScript (51:536e):

  1. checkevent EVENT_BEAT_PRYCE -> .FightDone
  2. writetext PryceText_Intro; winlosstext PryceText_Impressed, 0; loadtrainer PRYCE, PRYCE1; startbattle; reloadmapafterbattle
  3. setevent EVENT_BEAT_PRYCE; Text_ReceivedGlacierBadge; playsound SFX_GET_BADGE; setflag ENGINE_GLACIERBADGE
  4. readvar VAR_BADGES; scall MahoganyGymActivateRockets - ifequal 7, .RadioTowerRockets / ifequal 6, .GoldenrodRockets. Badge count is read after GLACIERBADGE is set, so the normal route (Glacier as the 7th badge) takes jumpstd RadioTowerRocketsScript (engine/events/std_scripts.asm:255), which sets ENGINE_ROCKETS_IN_RADIO_TOWER, EVENT_GOLDENROD_CITY_CIVILIANS, EVENT_RADIO_TOWER_BLACKBELT_BLOCKS_STAIRS, EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_EAST, specialphonecall SPECIALCALL_WEIRDBROADCAST, and setmapscene MAHOGANY_TOWN, SCENE_MAHOGANYTOWN_NOOP. Skipping Jasmine first (Glacier as the 6th) takes GoldenrodRocketsScript instead, which only clears EVENT_GOLDENROD_CITY_ROCKET_TAKEOVER.
  5. .FightDone: if EVENT_GOT_TM16_ICY_WIND is set -> farewell text. Otherwise setevent EVENT_BEAT_SKIER_ROXANNE / _CLARISSA / _BOARDER_RONALD / _BRAD / _DOUGLAS (so the five gym trainers never battle again), PryceText_GlacierBadgeSpeech, verbosegiveitem TM_ICY_WIND, setevent EVENT_GOT_TM16_ICY_WIND.

MahoganyGymStatue: checkflag ENGINE_GLACIERBADGE; before the badge jumpstd GymStatue1Script, after it gettrainername STRING_BUFFER_4, PRYCE, PRYCE1

  • jumpstd GymStatue2Script.

Flags and events (gym)

constant defined in read/written by meaning for a bot
EVENT_BEAT_PRYCE constants/event_flags.asm:712 MahoganyGymPryceScript leader beaten
EVENT_GOT_TM16_ICY_WIND event_flags.asm:20 MahoganyGymPryceScript TM handed over
ENGINE_GLACIERBADGE constants/engine_flags.asm:44 set here; read by WhirlpoolFunction and MahoganyGymStatue badge 7
EVENT_BEAT_SKIER_ROXANNE, _CLARISSA, EVENT_BEAT_BOARDER_RONALD, _BRAD, _DOUGLAS constants/event_flags.asm the five trainer macros, force-set by Pryce gym trainer beaten

Trainers (gym)

const class id party (data/trainers/parties.asm) script label
BOARDER, RONALD BOARDER ($3a) 1 SEEL 24, DEWGONG 25, SEEL 24 TrainerBoarderRonald
BOARDER, BRAD BOARDER 2 SWINUB 26, SWINUB 26 TrainerBoarderBrad
BOARDER, DOUGLAS BOARDER 3 SHELLDER 24, CLOYSTER 25, SHELLDER 24 TrainerBoarderDouglas
SKIER, ROXANNE SKIER ($21) 1 JYNX 28 TrainerSkierRoxanne
SKIER, CLARISSA SKIER 2 DEWGONG 28 TrainerSkierClarissa
PRYCE, PRYCE1 PRYCE ($05) 1 SEEL 27 (HEADBUTT/ICY_WIND/AURORA_BEAM/REST), DEWGONG 29 (HEADBUTT/ICY_WIND/AURORA_BEAM/REST), PILOSWINE 31 (ICY_WIND/FURY_ATTACK/MIST/BLIZZARD) MahoganyGymPryceScript

Wild encounters: none.


3. Blockers and gates

Gate Enforced by (file:label) Requirement Unlock condition
Hideout entrance does not exist maps/MahoganyMart1F.asm:MahoganyMart1FStaircaseCallback + MahoganyMart1FLanceUncoversStaircaseScript (45:4046) EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART for the block; the cutscene needs SCENE_MAHOGANYMART1F_LANCE_UNCOVERS_STAIRS maps/LakeOfRage.asm:LakeOfRageLanceScript.AgreedToHelp (previous section)
Camera grunt ambushes maps/TeamRocketBaseB1F.asm:SecurityCamera1a..5 EVENT_SECURITY_CAMERA_n clear beat both grunts at that camera, or press the switch at 19,11 (TeamRocketBaseB1FSecretSwitch, 45:4757)
Exploding floor traps maps/TeamRocketBaseB1F.asm:ExplodingTrap1..22 EVENT_EXPLODING_TRAP_n clear step on the tile once (or route around; safe cells listed above)
B2F transmitter room sealed (block) maps/TeamRocketBaseB2F.asm:TeamRocketBaseB2FLockedDoor (45:4e8f) + TeamRocketBaseB2FTransmitterDoorCallback EVENT_LEARNED_HAIL_GIOVANNI talk to the Murkrow object at B3F 7,2 (RocketBaseMurkrow, 45:5d49) after beating ExecutiveM 4
B2F boss ambush will not fire maps/TeamRocketBaseB2F.asm coord events on SCENE_TEAMROCKETBASEB2F_ROCKET_BOSS map scene must be 1 trip LanceHealsScript1/2 at 5,14 or 4,13 first
B3F Giovanni's office sealed maps/TeamRocketBaseB3F.asm:TeamRocketBaseB3FLockedDoor (45:5da9) + TeamRocketBaseB3FCheckGiovanniDoorCallback EVENT_LEARNED_SLOWPOKETAIL and EVENT_LEARNED_RATICATE_TAIL beat GRUNTF_5 at 21,7 then talk again; beat GRUNTM_28 at 5,15 then talk again
Cannot leave the Electrode room maps/TeamRocketBaseB2F.asm:RocketBaseCantLeaveScript / RocketBaseLancesSideScript scene SCENE_TEAMROCKETBASEB2F_ELECTRODES faint all three left-hand Electrodes
Mahogany Gym door blocked maps/MahoganyTown.asm object SPRITE_FISHER at 6,14 gated on EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM; visibility rule in engine/overworld/map_objects_2.asm:CheckObjectFlag flag set = NPC hidden RocketBaseElectrodeScript (45:4e3c) sets it when the hideout is cleared
Whirlpool unusable in the field engine/events/overworld.asm:WhirlpoolFunction.TryWhirlpool (03:4da0, ld de, ENGINE_GLACIERBADGE / call CheckBadge) and TryWhirlpoolOW (03:4e41, CheckPartyMove WHIRLPOOL then CheckEngineFlag ENGINE_GLACIERBADGE) GLACIERBADGE + a party member that knows WHIRLPOOL beat Pryce
Rage Candy Bar merchant trip-wire maps/MahoganyTown.asm coord events 19,8/19,9 on scene 0 scene SCENE_MAHOGANYTOWN_TRY_RAGECANDYBAR only cleared later, by RadioTowerRocketsScript setmapscene MAHOGANY_TOWN, SCENE_MAHOGANYTOWN_NOOP

4. Bot checklist

Coordinates are (x, y) map cells as written in the asm. "talk" = face the target and press A.

  1. MAHOGANY_TOWN: warp 4 at (15,13) -> MAHOGANY_POKECENTER_1F; talk to nurse at (3,1). Pre: none. Post: party healed.
  2. MAHOGANY_TOWN: warp 1 at (11,7) -> MAHOGANY_MART_1F. Pre: EVENT_DECIDED_TO_HELP_LANCE set and map scene = 1. Post: MahoganyMart1FLanceUncoversStaircaseScript runs unattended; wait for EVENT_UNCOVERED_STAIRCASE_IN_MAHOGANY_MART.
  3. MAHOGANY_MART_1F: walk to (7,3) -> TEAM_ROCKET_BASE_B1F warp 1, arriving at (27,2).
  4. B1F: walk west along y=2. Crossing (24,2) or (24,3) fires SecurityCamera1a/1b -> battle GRUNTM_20 then GRUNTM_21. Post: EVENT_SECURITY_CAMERA_1.
  5. B1F: item ball at (27,6) = HYPER_POTION. Post: EVENT_TEAM_ROCKET_BASE_B1F_HYPER_POTION.
  6. B1F: continue west; (6,2)/(6,3) fires camera 2, (24,6)/(24,7) camera 3, (22,16) camera 4, (8,16) camera 5. Each is the same two grunts.
  7. B1F: talk to GRUNTM_16 at (2,4) (sight 3, faces RIGHT - approaching from the east triggers him). Post: EVENT_BEAT_ROCKET_GRUNTM_16.
  8. B1F: cross the trap field x1..5 / y7..13 using only the safe cells listed in section 2, or accept the one-shot BATTLETYPE_TRAP battles. Optional: hidden REVIVE by facing (3,11).
  9. B1F: battle SCIENTIST JED at (18,12) (sight 3, faces LEFT). Post: EVENT_BEAT_SCIENTIST_JED. Talk again for the warp-panel hint.
  10. B1F: stand at (19,12), face UP, press A on the bg event at (19,11). Post: EVENT_TURNED_OFF_SECURITY_CAMERAS + EVENT_SECURITY_CAMERA_1..5.
  11. B1F: item balls (21,12) = X_ACCURACY, (14,15) = NUGGET.
  12. B1F: walk to (3,14) -> TEAM_ROCKET_BASE_B2F arriving at (3,14).
  13. B2F: step on (5,14) or (4,13). Pre: map scene 0. Post: party healed, EVENT_LANCE_HEALED_YOU_IN_TEAM_ROCKET_BASE, scene -> 1.
  14. B2F: battle GRUNTM_19 at (21,14) (sight 4, faces LEFT), then GRUNTM_17 at (25,13) (sight 3, faces DOWN).
  15. B2F: walk to (27,14) -> TEAM_ROCKET_BASE_B3F arriving at (27,14). Pre: none. Post: LanceGetPasswordScript auto-runs, scene -> 1, EVENT_TEAM_ROCKET_BASE_B3F_LANCE_PASSWORDS.
  16. B3F: item balls (28,9) = PROTEIN, (17,2) = ICE_HEAL.
  17. B3F: battle SCIENTIST ROSS at (25,12) (sight 4, faces LEFT).
  18. B3F: walk to (21,8) and talk UP to GRUNTF_5 at (21,7) - sight 0, she will not initiate. Post: EVENT_BEAT_ROCKET_GRUNTF_5; talk again -> EVENT_LEARNED_SLOWPOKETAIL.
  19. B3F: battle SCIENTIST MITCH at (14,15) (sight 3, faces UP).
  20. B3F: battle GRUNTM_28 at (5,15) (sight 3, spinning). Post: EVENT_BEAT_ROCKET_GRUNTM_28; talk again -> EVENT_LEARNED_RATICATE_TAIL.
  21. B3F: item balls (3,12) = DIRE_HIT, (1,12) = FULL_HEAL.
  22. B3F: walk to (27,2) -> TEAM_ROCKET_BASE_B2F arriving at (27,2).
  23. B2F top corridor: walk west along y=1..2; battle GRUNTM_18 at (2,1) (sight 3, faces RIGHT).
  24. B2F: walk to (3,2) -> TEAM_ROCKET_BASE_B3F arriving at (3,2).
  25. B3F left region: walk to (8,10). Pre: scene 1. Post: rival cutscene, no battle, scene -> 2, EVENT_RIVAL_TEAM_ROCKET_BASE set by disappear.
  26. B3F: stand at (10,10) or (11,10), face UP, press A on the bg event at (10,9)/(11,9). Pre: both password events. Post: EVENT_OPENED_DOOR_TO_GIOVANNIS_OFFICE, block at (10,8) becomes floor.
  27. B3F: step onto (10,8) or (11,8). Pre: scene 2. Post: auto-walk, battle EXECUTIVEM_4, EVENT_BEAT_ROCKET_EXECUTIVEM_4, scene -> 3.
  28. B3F: talk to the bird object at (7,2). Post: EVENT_LEARNED_HAIL_GIOVANNI.
  29. B3F: walk to (3,6) -> TEAM_ROCKET_BASE_B2F arriving at (3,6); item ball (3,10) = TM_THIEF (TM46). Return via (3,6).
  30. Back-track: B3F (3,2) -> B2F (3,2); B2F top corridor east to (27,2) -> B3F (27,2); B3F right region south to (27,14) -> B2F (27,14); walk west to the door.
  31. B2F: stand at (14,13)/(15,13), face UP, press A on (14,12)/(15,12). Pre: EVENT_LEARNED_HAIL_GIOVANNI. Post: EVENT_OPENED_DOOR_TO_ROCKET_HIDEOUT_TRANSMITTER, block becomes floor.
  32. B2F: step onto (14,11) or (15,11). Pre: scene 1. Post: EXECUTIVEF_2 battle, EVENT_BEAT_ROCKET_EXECUTIVEF_2, scene -> 2, Lance briefing.
  33. B2F: talk to the three left Electrodes at (7,5), (7,7), (7,9). Each is a wild ELECTRODE L23 that may Selfdestruct. Do not walk east past x=12 (RocketBaseLancesSideScript bounces you back). Post: three EVENT_TEAM_ROCKET_BASE_B2F_ELECTRODE_n.
  34. After the third, RocketBaseElectrodeScript auto-runs: accept HM_WHIRLPOOL. Post: EVENT_GOT_HM06_WHIRLPOOL, EVENT_CLEARED_ROCKET_HIDEOUT, EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM, clearflag ENGINE_ROCKET_SIGNAL_ON_CH20, scene -> 3.
  35. Exit: B2F (3,14) -> B1F (3,14); B1F warp panel (5,15) -> (25,2); (27,2) -> mart; mart (3,7)/(4,7) -> town.
  36. MAHOGANY_TOWN: heal at the Pokecenter, then warp 3 at (6,13) -> MAHOGANY_GYM, arriving at (4,17)/(5,17). Pre: EVENT_MAHOGANY_TOWN_POKEFAN_M_BLOCKS_GYM set (otherwise the fisher stands on (6,14)).
  37. Gym: UP, LEFT, LEFT, LEFT -> (0,16), Boarder Ronald spots you from (0,17).
  38. Gym: UP,UP,RIGHT,DOWN,LEFT -> (2,5), Boarder Douglas at (2,4). Talk again for the Pryce-waterfall line.
  39. Gym: DOWN,RIGHT -> (5,10), Boarder Brad at (5,9).
  40. Gym: RIGHT,DOWN -> (9,16), Skier Clarissa at (9,17).
  41. Gym: UP,UP,LEFT -> (4,7), Skier Roxanne at (4,6).
  42. Gym: DOWN -> (4,14), then walk to (2,14).
  43. Gym: from (2,14): UP,UP,RIGHT,DOWN,LEFT,UP,RIGHT -> (5,4). Talk UP to Pryce at (5,3).
  44. Battle PRYCE1. Post: EVENT_BEAT_PRYCE, ENGINE_GLACIERBADGE, the five gym-trainer beat flags, EVENT_GOT_TM16_ICY_WIND, and (at 7 badges) RadioTowerRocketsScript.
  45. Gym: leave via (4,17)/(5,17).

5. Port coverage

Beat Port file Status
Map headers / warps / coord events / bg events / objects for all six maps src/import/RomExtractorGen2.lua, src/world/gen2/Map.lua implemented (generic extraction, nothing map-specific needed)
Map scenes + sdefer scene scripts src/world/gen2/World.lua (World:scene, mapScenes), src/script/gen2/Vm.lua (sdefer, setscene, setmapscene) implemented
Coord-event trip-wires src/world/gen2/World.lua (coord event dispatch) implemented
changeblock (mart staircase, both password doors) src/script/gen2/Vm.lua:1006 - the comment cites MahoganyMart1F's changeblock 6, 2, $1e and cell (7,3) by name implemented
BGEVENT_IFNOTSET / conditional_event (both password doors) src/world/gen2/World.lua:5147 World:bgEventAt only matches (ev.kind or 0) == 0; src/world/gen2/HiddenItems.lua handles kind 7 missing - pressing A on the transmitter door or Giovanni's door does nothing in the port
Ice sliding (STEP_ICE, CheckStandingOnIce forced d-pad) src/world/gen2/Permissions.lua:128 ICE exists but is only consumed by FieldMoves.canEncounterWildMon; World:movePlayer picks step frames from Bike.stepFrames only missing - Mahogany Gym floor behaves as ordinary floor, so the puzzle and the trainer sight lines are wrong
Trainer sight range / approach src/world/gen2/Trainers.lua (Trainers.sees, Trainers.approach) implemented (sight 0 on GruntF5 falls out naturally)
itemball / hiddenitem src/script/gen2/CallAsm.lua, src/world/gen2/HiddenItems.lua implemented
verbosegiveitem HM_WHIRLPOOL src/script/gen2/Vm.lua, src/script/gen2/Opcodes.lua implemented
Whirlpool field move + GLACIERBADGE gate src/world/gen2/FieldMoves.lua:109 (WHIRLPOOL = "GLACIER"), .somethingToWhirlpool, .whirlpoolFromMenu, .tryWhirlpoolOW, WHIRLPOOL_BLOCKS implemented
loadwildmon + BATTLETYPE_TRAP src/world/gen2/World.lua:4587 (names "TRAP 9 (the Rocket base)"), src/script/gen2/Vm.lua:699 implemented
special HealParty / FadeOutToWhite / FadeInFromWhite / PlayMapMusic / ReloadSpritesNoPalettes / FadeOutToBlack / FadeInFromBlack / RestartMapMusic / FadeOutMusic src/script/gen2/Specials.lua:450, 992-1066 implemented
moveobject / appear / disappear / applymovement / follow / showemote src/script/gen2/Vm.lua, src/script/gen2/Movement.lua, src/world/gen2/World.lua implemented
jumpstd (TeamRocketOathScript, GymStatue1/2Script, PokecenterSignScript, RadioTowerRocketsScript) src/script/gen2/Vm.lua:742, data/generated/std_scripts.lua via World.lua:635 implemented (generic)
readvar VAR_BADGES for MahoganyGymActivateRockets src/world/gen2/World.lua:117,1240 implemented
specialphonecall SPECIALCALL_WEIRDBROADCAST src/script/gen2/Vm.lua:1364 stores the id; src/core/gen2/Phone.lua delivers implemented
ENGINE_ROCKET_SIGNAL_ON_CH20 radio behaviour src/ui/gen2/Pokegear.lua:816-821, 1097 implemented
Driver coverage for this stretch tests/drivers/gold_*.lua - none touches Mahogany, the hideout or Pryce (gold_icepath_boulder.lua is the only Mahogany-adjacent one, and it is Ice Path boulders) missing

The two "missing" rows are the blocking ones: without BGEVENT_IFNOTSET the hideout cannot be completed, and without ice sliding the gym cannot be crossed.


6. Unresolved / verify by hand

  • Floor labels in the walkthrough are wrong past the first password. It says "go up the stairs at the upper-right part of the floor, then head left on Negative Floor 2 ... Head up the stairs to Negative Floor 1. Head right and then before you reach the locked door, your rival will come." The rival coord event (8,10) and Giovanni's office are both on B3F, not B1F. The route is B3F(right) -> B2F(top) -> B3F(left). Verified by flood-filling maps/TeamRocketBaseB2F.blk / maps/TeamRocketBaseB3F.blk: the four B2F warps and four B3F warps sit in disconnected rooms, and B2F warp 2 (3,2) reaches B3F (3,2) which is the region containing 8,10.
  • Boarder Ronald's party order. Walkthrough lists Seel 24 / Seel 24 / Dewgong 25; data/trainers/parties.asm BOARDER (1) is SEEL 24, DEWGONG 25, SEEL 24. Same three mon, different lead order. Same class of discrepancy for GRUNTM_18 (walkthrough Rattata/Rattata/Zubat, asm Rattata/Zubat/Rattata).
  • Item list is incomplete. The walkthrough's "Items in the Team Rocket Hideout" block lists six; the asm has ten: the six named plus FULL_HEAL and DIRE_HIT item balls on B3F (mentioned later in the prose) and two hidden items the walkthrough never mentions - REVIVE at B1F (3,11) and FULL_HEAL at B2F (26,7).
  • "Every time you pass one of those statues, two Team Rocket grunts will fight you" is right, but the walkthrough implies only two statues on the first floor. There are five (bg_event at 24,1, 6,1, 24,5, 8,15, 22,15) with eight trigger cells, i.e. up to ten grunt battles if none are skipped.
  • EVENT_TEAM_ROCKET_BASE_POPULATION is dead. It is the shared visibility flag of eleven base NPCs and is read by all eight SecurityCamera* scripts, but a full-tree grep finds no setevent, clearevent or disappear that writes it. Those checkevent ... iftrue NoSecurityCamera arms therefore never take, and the Rocket NPCs stay on the maps forever - including after the hideout is cleared. Flagged in case a bot author expects the base to empty out.
  • Lance's three right-hand Electrodes are never battled. RocketElectrodeN disappears both members of a mirrored pair, and the objects at 22,5/22,7/22,9 point at the no-op ObjectEvent script. The walkthrough's "Lance runs to the right to take the Electrodes on the right" is flavour; the game just hides them.
  • Exact reachability of 19,11 (the secret switch) was checked by collision (19,11 is a WALL, 19,12 is FLOOR and in the single B1F region), but the in-game facing direction for the BGEVENT_READ was not observed running - the bg event type is BGEVENT_READ, not BGEVENT_UP, so any adjacent facing should work; worth confirming on hardware if a driver misses it.
  • The gym slide table in section 2 was produced by simulating engine/overworld/player_movement.asm's ice rule against the decoded maps/MahoganyGym.blk, treating NPCs as blockers. It reproduces every direction string in the walkthrough, but it has not been executed in an emulator.