46 KiB
Section 15 - Mount Mortar and Dark Cave
Source: ../section-15-mount-mortar-and-dark-cave.txt
Maps covered: MAP_MOUNT_MORTAR_1F_OUTSIDE, MAP_MOUNT_MORTAR_1F_INSIDE,
MAP_MOUNT_MORTAR_2F_INSIDE, MAP_MOUNT_MORTAR_B1F,
MAP_DARK_CAVE_BLACKTHORN_ENTRANCE, MAP_DARK_CAVE_VIOLET_ENTRANCE.
Touched in passing (owned by neighbouring sections): MAP_MAHOGANY_TOWN,
MAP_ROUTE_42, MAP_BLACKTHORN_CITY, MAP_ROUTE_45, MAP_ROUTE_31,
MAP_ROUTE_46.
Badges / key milestones in this section: no badge. The milestones are
EVENT_BEAT_BLACKBELT_KIYO + EVENT_GOT_TYROGUE_FROM_KIYO (a free level 10
TYROGUE, the only one in the game) and EVENT_GOT_BLACKGLASSES_IN_DARK_CAVE.
Everything else here is optional loot. Nothing in this section gates any later
section.
A note on coordinates: every table below is transcribed verbatim from the map's
_MapEvents block in the named maps/*.asm file. warp_event, coord_event,
bg_event and object_event all share one coordinate space (the
object_event macro in macros/scripts/maps.asm applies the +4 border offset
itself), so the numbers are directly comparable. A map declared
map_const NAME, W, H spans x in 0 .. 2W-1 and y in 0 .. 2H-1.
A note on the event flag column of object_event:
engine/overworld/map_objects_2.asm CheckObjectFlag hides the object when
the flag is set, and -1 means always visible. So for a Poke Ball, "flag set =
already taken = gone".
A note on darkness: all six maps in this section are PALETTE_DARK in
data/maps/maps.asm. engine/tilesets/timeofday_pals.asm
ReplaceTimeOfDayPals (23:43e9) sends PALETTE_DARK down .NeedsFlash,
which writes DARKNESS_PALSET unless STATUSFLAGS_FLASH_F is set in
wStatusFlags. That bit is set by BlindingFlash (engine/events/field_moves.asm)
and cleared by ResetFlashIfOutOfCave (home/flag.asm, 00:2f1d) on any map
whose wEnvironment is ROUTE or TOWN. A bot must re-cast Flash every time
it re-enters, including after every Fly.
1. Route order
| # | Map constant | asm file | Enter via | Leaves via | Why (walkthrough beat) |
|---|---|---|---|---|---|
| 1 | MAP_MAHOGANY_TOWN |
data/maps/maps.asm:74, data/maps/spawn_points.asm spawn MAHOGANY_TOWN, 15, 14 |
Fly (ENGINE_FLYPOINT_MAHOGANY) |
west map connection -> ROUTE_42 |
heal, buy Max Repels / Escape Ropes, drop to 5 party members so Tyrogue fits |
| 2 | MAP_ROUTE_42 |
maps/Route42.asm |
east connection from Mahogany, or warps 1/2 at (0,8)/(0,9) from the Ecruteak gate | warp 3 (10,5) west entrance, warp 4 (28,9) middle entrance, warp 5 (46,7) east entrance -> MOUNT_MORTAR_1F_OUTSIDE warps 1/2/3 |
"three cave entrances to Mt. Mortar" |
| 3 | MAP_MOUNT_MORTAR_1F_OUTSIDE |
maps/MountMortar1FOutside.asm |
warps 1/2/3 at (3,33)/(17,33)/(37,33) | warp 4 (17,5) -> 2F after Waterfall; warp 7 (17,29) -> B1F | all three Route 42 doors land on this one map; the Surf lake and the waterfall live here |
| 4 | MAP_MOUNT_MORTAR_1F_INSIDE |
maps/MountMortar1FInside.asm |
1F Outside warps 5/6 (11,21)/(29,21) or 8/9 (7,13)/(33,13) | warp 5 (3,19) -> B1F; warp 6 (9,9) -> 2F | the "giant room" with the Strength boulder, Escape Rope and Hyper Potion |
| 5 | MAP_MOUNT_MORTAR_2F_INSIDE |
maps/MountMortar2FInside.asm |
warp 1 (17,33) from 1F Outside warp 4 (top of the waterfall) | warp 2 (3,5) -> MOUNT_MORTAR_1F_INSIDE warp 6 |
Rare Candy, Max Potion, TM40, Dragon Scale, Elixer, Escape Rope, hidden Full Restore |
| 6 | MAP_MOUNT_MORTAR_B1F |
maps/MountMortarB1F.asm |
warp 1 (3,3) from 1F Inside warp 5 | Escape Rope, or Strength the boulder at (9,10) and take warp 2 (19,29) -> 1F Outside warp 7 | Blackbelt Kiyo, then the free Tyrogue |
| 7 | MAP_BLACKTHORN_CITY |
data/maps/maps.asm:187, data/maps/spawn_points.asm spawn BLACKTHORN_CITY, 21, 30 |
Fly (ENGINE_FLYPOINT_BLACKTHORN) |
south map connection (data/maps/attributes.asm:161 connection south, Route45, ROUTE_45, 0) |
heal, then head south |
| 8 | MAP_ROUTE_45 |
maps/Route45.asm |
north connection from Blackthorn | warp 1 (2,5) -> DARK_CAVE_BLACKTHORN_ENTRANCE warp 1 |
"enter the Dark Cave to the left before there are even any jumps" |
| 9 | MAP_DARK_CAVE_BLACKTHORN_ENTRANCE |
maps/DarkCaveBlackthornEntrance.asm |
warp 1 (23,3) | warp 2 (3,25) -> DARK_CAVE_VIOLET_ENTRANCE warp 2 |
Blackglasses NPC, Revive, TM13 Snore, Wobbuffet |
| 10 | MAP_DARK_CAVE_VIOLET_ENTRANCE |
maps/DarkCaveVioletEntrance.asm |
warp 2 (17,1) | warp 1 (3,15) -> ROUTE_31 warp 3 |
"surf down, rock smash the rock, grab the Potion, head out onto Route 31" |
| 11 | MAP_ROUTE_31 |
maps/Route31.asm |
warp 3 (34,5) | Fly back to Blackthorn | walkthrough exit |
Spill into the next section: the walkthrough's video links name Blackthorn Gym,
Route 45/46, Tohjo Falls, Routes 26/27, Victory Road and the Elite Four, but its
prose stops at "head back south to actually take Route 45". MAP_ROUTE_45
proper, MAP_ROUTE_46, MAP_BLACKTHORN_GYM and everything past them belong to
the next section; only the Route 45 warp that reaches Dark Cave is documented
here.
MAP_DARK_CAVE_VIOLET_ENTRANCE is also reachable from ROUTE_46 warp 3 at
(14,5) (-> Dark Cave warp 3 at (35,33)) and from ROUTE_31 warp 3; the earlier
sections that visit Route 31 already touch the north end of this map. This
section only walks it top-to-bottom-left, from the Blackthorn side out to
Route 31.
2. Maps
MAP_MOUNT_MORTAR_1F_OUTSIDE
- Script:
maps/MountMortar1FOutside.asm - Blocks:
maps/MountMortar1FOutside.blk - Header:
data/maps/maps.asm:127->TILESET_DARK_CAVE,CAVE,LANDMARK_MT_MORTAR,MUSIC_UNION_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:114map_const MOUNT_MORTAR_1F_OUTSIDE, 20, 18(x 0..39, y 0..35), map id 49, group 3 - Attributes:
data/maps/attributes.asm:446, border block$09, no connections - Map events block:
MountMortar1FOutside_MapEvents=46:5db9
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 3 | 33 | ROUTE_42 |
3 |
| 2 | 17 | 33 | ROUTE_42 |
4 |
| 3 | 37 | 33 | ROUTE_42 |
5 |
| 4 | 17 | 5 | MOUNT_MORTAR_2F_INSIDE |
1 |
| 5 | 11 | 21 | MOUNT_MORTAR_1F_INSIDE |
1 |
| 6 | 29 | 21 | MOUNT_MORTAR_1F_INSIDE |
2 |
| 7 | 17 | 29 | MOUNT_MORTAR_B1F |
2 |
| 8 | 7 | 13 | MOUNT_MORTAR_1F_INSIDE |
3 |
| 9 | 33 | 13 | MOUNT_MORTAR_1F_INSIDE |
4 |
Coord events (def_coord_events)
def_coord_events is empty. No scripted trip-wires anywhere in Mt. Mortar.
BG events (def_bg_events)
| x | y | type | script/item |
|---|---|---|---|
| 25 | 22 | BGEVENT_ITEM |
MountMortar1FOutsideHiddenHyperPotion -> hiddenitem HYPER_POTION, EVENT_MOUNT_MORTAR_1F_OUTSIDE_HIDDEN_HYPER_POTION |
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
MOUNTMORTAR1FOUTSIDE_POKE_BALL1 |
SPRITE_POKE_BALL |
13 | 15 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar1FOutsideEther (itemball ETHER) |
EVENT_MOUNT_MORTAR_1F_OUTSIDE_ETHER |
MOUNTMORTAR1FOUTSIDE_POKE_BALL2 |
SPRITE_POKE_BALL |
31 | 18 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar1FOutsideGuardSpec (itemball GUARD_SPEC) |
EVENT_MOUNT_MORTAR_1F_OUTSIDE_REVIVE |
Note the flag/item mismatch on the second ball: the item is GUARD_SPEC but the
flag is named ..._REVIVE. That is verbatim from the disassembly - the label
name is cosmetic, the flag bit is what matters.
Scripts of interest
MountMortar1FOutsideEther/MountMortar1FOutsideGuardSpec- bareitemball ITEMrows (two bytes, no bytecode). Picked up by the sharedFindItemInBallScriptpath, not by a per-map script.MountMortar1FOutsideHiddenHyperPotion-hiddenitemdata behind aBGEVENT_ITEMrow; A-pressed on (25,22) or found by the ITEMFINDER.
Wild encounters
data/wild/johto_grass.asm:686 def_grass_wildmons MOUNT_MORTAR_1F_OUTSIDE,
encounter rate 6 percent for all three of morn/day/nite, and all three
slot lists are identical:
| slot | lvl | species |
|---|---|---|
| 1 | 13 | ZUBAT |
| 2 | 15 | ZUBAT |
| 3 | 14 | MACHOP |
| 4 | 14 | RATTATA |
| 5 | 14 | GEODUDE |
| 6 | 16 | RATTATA |
| 7 | 15 | MARILL |
data/wild/johto_water.asm:58 def_water_wildmons MOUNT_MORTAR_1F_OUTSIDE,
rate 4 percent: 20 GOLDEEN / 15 GOLDEEN / 20 SEAKING.
Fishing: FISHGROUP_LAKE, data/wild/fish.asm:57 - Old rod MAGIKARP 10 /
GOLDEEN 10; Good rod MAGIKARP 20 / GOLDEEN 20 / time_group 4; Super rod
GOLDEEN 40 / time_group 5 / MAGIKARP 40 / SEAKING 40.
No headbutt or rock-smash table (data/wild/treemon_maps.asm does not list this
map).
MAP_MOUNT_MORTAR_1F_INSIDE
- Script:
maps/MountMortar1FInside.asm - Blocks:
maps/MountMortar1FInside.blk - Header:
data/maps/maps.asm:128->TILESET_DARK_CAVE,CAVE,LANDMARK_MT_MORTAR,MUSIC_UNION_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:115map_const MOUNT_MORTAR_1F_INSIDE, 20, 27(x 0..39, y 0..53), map id 50, group 3 - Attributes:
data/maps/attributes.asm:447, border block$09, no connections - Map events block:
MountMortar1FInside_MapEvents=46:5e19
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 11 | 47 | MOUNT_MORTAR_1F_OUTSIDE |
5 |
| 2 | 29 | 47 | MOUNT_MORTAR_1F_OUTSIDE |
6 |
| 3 | 5 | 39 | MOUNT_MORTAR_1F_OUTSIDE |
8 |
| 4 | 33 | 41 | MOUNT_MORTAR_1F_OUTSIDE |
9 |
| 5 | 3 | 19 | MOUNT_MORTAR_B1F |
1 |
| 6 | 9 | 9 | MOUNT_MORTAR_2F_INSIDE |
2 |
Coord events - empty.
BG events (def_bg_events)
| x | y | type | script/item |
|---|---|---|---|
| 31 | 9 | BGEVENT_ITEM |
MountMortar1FInsideHiddenMaxRepel -> hiddenitem MAX_REPEL, EVENT_MOUNT_MORTAR_1F_INSIDE_HIDDEN_MAX_REPEL |
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
MOUNTMORTAR1FINSIDE_BOULDER |
SPRITE_BOULDER |
21 | 43 | SPRITEMOVEDATA_STRENGTH_BOULDER |
OBJECTTYPE_SCRIPT |
MountMortar1FBoulder (jumpstd StrengthBoulderScript) |
-1 |
MOUNTMORTAR1FINSIDE_POKE_BALL1 |
SPRITE_POKE_BALL |
33 | 22 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar1FInsideEscapeRope (itemball ESCAPE_ROPE) |
EVENT_MOUNT_MORTAR_1F_INSIDE_ESCAPE_ROPE |
MOUNTMORTAR1FINSIDE_POKE_BALL2 |
SPRITE_POKE_BALL |
16 | 10 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar1FInsideMaxRevive (itemball MAX_REVIVE) |
EVENT_MOUNT_MORTAR_1F_INSIDE_MAX_REVIVE |
MOUNTMORTAR1FINSIDE_POKE_BALL3 |
SPRITE_POKE_BALL |
12 | 21 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar1FInsideHyperPotion (itemball HYPER_POTION) |
EVENT_MOUNT_MORTAR_1F_INSIDE_HYPER_POTION |
Scripts of interest
MountMortar1FBoulder- one line:jumpstd StrengthBoulderScript.engine/events/std_scripts.asm:196StrengthBoulderScript: farsjump AskStrengthScript(03:4d4e). See section 3 for the gate.
Wild encounters
data/wild/johto_grass.asm:714 def_grass_wildmons MOUNT_MORTAR_1F_INSIDE,
rate 6 percent morn/day/nite, all three lists identical:
| slot | lvl | species |
|---|---|---|
| 1 | 13 | GEODUDE |
| 2 | 13 | MACHOP |
| 3 | 15 | GEODUDE |
| 4 | 14 | RATTATA |
| 5 | 15 | MACHOP |
| 6 | 14 | ZUBAT |
| 7 | 14 | ZUBAT |
There is no def_water_wildmons MOUNT_MORTAR_1F_INSIDE in
data/wild/johto_water.asm - only 1F Outside, 2F Inside and B1F have water
tables. Fishing group is still FISHGROUP_LAKE.
MAP_MOUNT_MORTAR_2F_INSIDE
- Script:
maps/MountMortar2FInside.asm - Blocks:
maps/MountMortar2FInside.blk - Header:
data/maps/maps.asm:129->TILESET_DARK_CAVE,CAVE,LANDMARK_MT_MORTAR,MUSIC_UNION_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:116map_const MOUNT_MORTAR_2F_INSIDE, 20, 18(x 0..39, y 0..35), map id 51, group 3 - Attributes:
data/maps/attributes.asm:448, border block$09, no connections - Map events block:
MountMortar2FInside_MapEvents=46:5e87
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 17 | 33 | MOUNT_MORTAR_1F_OUTSIDE |
4 |
| 2 | 3 | 5 | MOUNT_MORTAR_1F_INSIDE |
6 |
Coord events - empty.
BG events (def_bg_events)
| x | y | type | script/item |
|---|---|---|---|
| 19 | 6 | BGEVENT_ITEM |
MountMortar2FInsideHiddenFullRestore -> hiddenitem FULL_RESTORE, EVENT_MOUNT_MORTAR_2F_INSIDE_HIDDEN_FULL_RESTORE |
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
MOUNTMORTAR2FINSIDE_POKE_BALL1 |
SPRITE_POKE_BALL |
31 | 23 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideMaxPotion (itemball MAX_POTION) |
EVENT_MOUNT_MORTAR_2F_INSIDE_MAX_POTION |
MOUNTMORTAR2FINSIDE_POKE_BALL2 |
SPRITE_POKE_BALL |
2 | 24 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideRareCandy (itemball RARE_CANDY) |
EVENT_MOUNT_MORTAR_2F_INSIDE_RARE_CANDY |
MOUNTMORTAR2FINSIDE_POKE_BALL3 |
SPRITE_POKE_BALL |
19 | 17 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideTMDefenseCurl (itemball TM_DEFENSE_CURL) |
EVENT_MOUNT_MORTAR_2F_INSIDE_TM_DEFENSE_CURL |
MOUNTMORTAR2FINSIDE_POKE_BALL4 |
SPRITE_POKE_BALL |
14 | 5 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideDragonScale (itemball DRAGON_SCALE) |
EVENT_MOUNT_MORTAR_2F_INSIDE_DRAGON_SCALE |
MOUNTMORTAR2FINSIDE_POKE_BALL5 |
SPRITE_POKE_BALL |
8 | 9 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideElixer (itemball ELIXER) |
EVENT_MOUNT_MORTAR_2F_INSIDE_ELIXER |
MOUNTMORTAR2FINSIDE_POKE_BALL6 |
SPRITE_POKE_BALL |
28 | 5 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortar2FInsideEscapeRope (itemball ESCAPE_ROPE) |
EVENT_MOUNT_MORTAR_2F_INSIDE_ESCAPE_ROPE |
TM_DEFENSE_CURL is TM40 by the add_tm ordering in
constants/item_constants.asm:261. The walkthrough calls it "TM40 Aerial Ace",
which is the HGSS remake's TM40 - see section 6.
Wild encounters
data/wild/johto_grass.asm:742 def_grass_wildmons MOUNT_MORTAR_2F_INSIDE,
rate 6 percent morn/day/nite, all three lists identical - this is the floor
the walkthrough's "Raticate / Machoke / Graveler" list is drawn from:
| slot | lvl | species |
|---|---|---|
| 1 | 31 | GRAVELER |
| 2 | 32 | MACHOKE |
| 3 | 31 | GEODUDE |
| 4 | 30 | RATICATE |
| 5 | 28 | MACHOP |
| 6 | 30 | GOLBAT |
| 7 | 30 | GOLBAT |
data/wild/johto_water.asm:65 def_water_wildmons MOUNT_MORTAR_2F_INSIDE,
rate 2 percent: 20 GOLDEEN / 25 GOLDEEN / 25 SEAKING.
MAP_MOUNT_MORTAR_B1F
- Script:
maps/MountMortarB1F.asm - Blocks:
maps/MountMortarB1F.blk - Header:
data/maps/maps.asm:130->TILESET_DARK_CAVE,CAVE,LANDMARK_MT_MORTAR,MUSIC_UNION_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:117map_const MOUNT_MORTAR_B1F, 20, 18(x 0..39, y 0..35), map id 52, group 3 - Attributes:
data/maps/attributes.asm:449, border block$09, no connections - Map events block:
MountMortarB1F_MapEvents=46:60f0
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 3 | 3 | MOUNT_MORTAR_1F_INSIDE |
5 |
| 2 | 19 | 29 | MOUNT_MORTAR_1F_OUTSIDE |
7 |
Coord events - empty. Kiyo is a talk-to trigger, not a trip-wire.
BG events (def_bg_events)
| x | y | type | script/item |
|---|---|---|---|
| 4 | 6 | BGEVENT_ITEM |
MountMortarB1FHiddenMaxRevive -> hiddenitem MAX_REVIVE, EVENT_MOUNT_MORTAR_B1F_HIDDEN_MAX_REVIVE |
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
MOUNTMORTARB1F_POKE_BALL1 |
SPRITE_POKE_BALL |
31 | 17 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortarB1FHyperPotion (itemball HYPER_POTION) |
EVENT_MOUNT_MORTAR_B1F_HYPER_POTION |
MOUNTMORTARB1F_POKE_BALL2 |
SPRITE_POKE_BALL |
4 | 16 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
MountMortarB1FFullHeal (itemball FULL_HEAL) |
EVENT_MOUNT_MORTAR_B1F_FULL_HEAL |
MOUNTMORTARB1F_BOULDER |
SPRITE_BOULDER |
9 | 10 | SPRITEMOVEDATA_STRENGTH_BOULDER |
OBJECTTYPE_SCRIPT |
MountMortarB1FBoulder (jumpstd StrengthBoulderScript) |
-1 |
MOUNTMORTARB1F_KIYO |
SPRITE_BLACK_BELT |
13 | 4 | SPRITEMOVEDATA_STANDING_DOWN |
OBJECTTYPE_SCRIPT, palette PAL_NPC_BROWN |
MountMortarB1FKiyoScript |
-1 |
Scripts of interest
MountMortarB1FKiyoScript (46:5eec) - the whole point of this section. Note
it is OBJECTTYPE_SCRIPT, not OBJECTTYPE_TRAINER: Kiyo has no trainer
header, no sight range, and never walks up to you. He must be talked to.
faceplayer
opentext
checkevent EVENT_GOT_TYROGUE_FROM_KIYO ; iftrue -> .GotTyrogue (46:5f27)
checkevent EVENT_BEAT_BLACKBELT_KIYO ; iftrue -> .BeatKiyo (46:5f0d)
writetext MountMortarB1FKiyoIntroText
waitbutton
closetext
winlosstext MountMortarB1FKiyoWinText, 0
loadtrainer BLACKBELT_T, KIYO
startbattle
reloadmapafterbattle
setevent EVENT_BEAT_BLACKBELT_KIYO
opentext
.BeatKiyo:
writetext MountMortarB1FTyrogueRewardText
promptbutton
waitsfx
readvar VAR_PARTYCOUNT
ifequal PARTY_LENGTH, .NoRoom ; 46:5f2d
writetext MountMortarB1FReceiveMonText
playsound SFX_CAUGHT_MON
waitsfx
givepoke TYROGUE, 10
setevent EVENT_GOT_TYROGUE_FROM_KIYO
.GotTyrogue:
writetext MountMortarB1FKiyoGotTyrogueText
waitbutton
closetext
end
Bot-relevant control flow:
- The battle is unconditional on first talk (no
checkeventguard beforeloadtrainer), and the win-flag write is afterstartbattle, so a blackout means the whole script re-runs from the top. readvar VAR_PARTYCOUNT/ifequal PARTY_LENGTHis the "you have no room" branch.PARTY_LENGTHis 6. If the party is full,EVENT_BEAT_BLACKBELT_KIYOis already set butEVENT_GOT_TYROGUE_FROM_KIYOis not, so re-talking re-enters at.BeatKiyoand offers the Tyrogue again. This is why the walkthrough tells you to free a slot in advance - but it is recoverable, not missable.givepoke TYROGUE, 10- level 10, no held item, no nickname prompt in this form of the opcode.
MountMortarB1FBoulder - jumpstd StrengthBoulderScript, same as 1F Inside.
Flags and events
| constant | defined in | read/written by | meaning for a bot |
|---|---|---|---|
EVENT_BEAT_BLACKBELT_KIYO |
constants/event_flags.asm:684 |
set by MountMortarB1FKiyoScript after startbattle |
Kiyo will not fight again |
EVENT_GOT_TYROGUE_FROM_KIYO |
constants/event_flags.asm:106 |
set by MountMortarB1FKiyoScript after givepoke |
the Tyrogue is banked; the script becomes pure flavour |
Trainers
| const | class | id | party (data/trainers/parties.asm label) |
script label | rematch/phone |
|---|---|---|---|---|---|
KIYO (constants/trainer_constants.asm:500) |
BLACKBELT_T |
6th entry of BlackbeltGroup |
data/trainers/parties.asm:2455 ; BLACKBELT_T (6) db "KIYO@", TRAINERTYPE_NORMAL / db 34, HITMONLEE / db 34, HITMONCHAN |
MountMortarB1FKiyoScript |
none - no trainer header, so no phone number, no rematch |
TRAINERTYPE_NORMAL means no custom moves and no held items: both mons use
their level-34 learnset defaults. The walkthrough's "816G" prize and the
1012/1020 EXP figures were not verified against data/trainers/attributes.asm -
see section 6.
Wild encounters
data/wild/johto_grass.asm:770 def_grass_wildmons MOUNT_MORTAR_B1F, rate
6 percent morn/day/nite, all three lists identical:
| slot | lvl | species |
|---|---|---|
| 1 | 15 | ZUBAT |
| 2 | 17 | ZUBAT |
| 3 | 16 | RATTATA |
| 4 | 16 | MACHOP |
| 5 | 16 | GEODUDE |
| 6 | 16 | RATICATE |
| 7 | 16 | RATICATE |
data/wild/johto_water.asm:72 def_water_wildmons MOUNT_MORTAR_B1F, rate
2 percent: 20 GOLDEEN / 15 GOLDEEN / 20 SEAKING.
MAP_DARK_CAVE_BLACKTHORN_ENTRANCE
- Script:
maps/DarkCaveBlackthornEntrance.asm - Blocks:
maps/DarkCaveBlackthornEntrance.blk - Header:
data/maps/maps.asm:149->TILESET_DARK_CAVE,CAVE,LANDMARK_DARK_CAVE,MUSIC_DARK_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:136map_const DARK_CAVE_BLACKTHORN_ENTRANCE, 15, 18(x 0..29, y 0..35), map id 71, group 3 - Attributes:
data/maps/attributes.asm:468, border block$09, no connections - Map events block:
DarkCaveBlackthornEntrance_MapEvents=47:4489
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 23 | 3 | ROUTE_45 |
1 |
| 2 | 3 | 25 | DARK_CAVE_VIOLET_ENTRANCE |
2 |
Coord events - empty.
BG events - def_bg_events is empty. No signs, no hidden items.
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
DARKCAVEBLACKTHORNENTRANCE_PHARMACIST |
SPRITE_PHARMACIST |
7 | 3 | SPRITEMOVEDATA_SPINRANDOM_SLOW |
OBJECTTYPE_SCRIPT |
DarkCaveBlackthornEntrancePharmacistScript |
-1 |
DARKCAVEBLACKTHORNENTRANCE_POKE_BALL1 |
SPRITE_POKE_BALL |
21 | 24 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
DarkCaveBlackthornEntranceRevive (itemball REVIVE) |
EVENT_DARK_CAVE_BLACKTHORN_ENTRANCE_REVIVE |
DARKCAVEBLACKTHORNENTRANCE_POKE_BALL2 |
SPRITE_POKE_BALL |
7 | 22 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
DarkCaveBlackthornEntranceTMSnore (itemball TM_SNORE) |
EVENT_DARK_CAVE_BLACKTHORN_ENTRANCE_TM_SNORE |
TM_SNORE is TM13 by the add_tm ordering in
constants/item_constants.asm:233, which matches the walkthrough's "TM 13".
Scripts of interest
DarkCaveBlackthornEntrancePharmacistScript (47:436c):
faceplayer
opentext
checkevent EVENT_GOT_BLACKGLASSES_IN_DARK_CAVE ; iftrue -> .GotBlackglasses (47:4381)
writetext DarkCaveBlackthornEntrancePharmacistText1
promptbutton
verbosegiveitem BLACKGLASSES
iffalse .PackFull ; 47:4385
setevent EVENT_GOT_BLACKGLASSES_IN_DARK_CAVE
.GotBlackglasses:
writetext DarkCaveBlackthornEntrancePharmacistText2
waitbutton
.PackFull:
closetext
end
Bot-relevant: verbosegiveitem returns 0 when the pack is full, and the
setevent is after the give, so a full item pocket leaves the flag clear
and the NPC re-offers. Not missable. The NPC spins
(SPRITEMOVEDATA_SPINRANDOM_SLOW), so the bot must stand adjacent and press A;
faceplayer handles the turn.
Flags and events
| constant | defined in | read/written by | meaning for a bot |
|---|---|---|---|
EVENT_GOT_BLACKGLASSES_IN_DARK_CAVE |
constants/event_flags.asm:123 |
DarkCaveBlackthornEntrancePharmacistScript |
BLACKGLASSES banked; NPC becomes flavour text |
EVENT_DARK_CAVE_BLACKTHORN_ENTRANCE_REVIVE |
constants/event_flags.asm:1090 |
object visibility mask | set = ball already taken |
EVENT_DARK_CAVE_BLACKTHORN_ENTRANCE_TM_SNORE |
constants/event_flags.asm:1091 |
object visibility mask | set = TM13 already taken |
Wild encounters
data/wild/johto_grass.asm:1545 def_grass_wildmons DARK_CAVE_BLACKTHORN_ENTRANCE,
rate 4 percent morn/day/nite, all three lists identical - this is the
walkthrough's Wobbuffet spot:
| slot | lvl | species |
|---|---|---|
| 1 | 23 | GEODUDE |
| 2 | 23 | ZUBAT |
| 3 | 25 | GRAVELER |
| 4 | 20 | WOBBUFFET |
| 5 | 25 | WOBBUFFET |
| 6 | 23 | GOLBAT |
| 7 | 23 | GOLBAT |
data/wild/johto_water.asm:114 def_water_wildmons DARK_CAVE_BLACKTHORN_ENTRANCE,
rate 2 percent: 15 MAGIKARP / 10 MAGIKARP / 5 MAGIKARP.
No treemon_map row for this map - rock smash here yields nothing, and
there are no smashable rock objects on it either.
MAP_DARK_CAVE_VIOLET_ENTRANCE
- Script:
maps/DarkCaveVioletEntrance.asm - Blocks:
maps/DarkCaveVioletEntrance.blk - Header:
data/maps/maps.asm:148->TILESET_DARK_CAVE,CAVE,LANDMARK_DARK_CAVE,MUSIC_DARK_CAVE, phoneTRUE,PALETTE_DARK,FISHGROUP_LAKE - Dimensions:
constants/map_constants.asm:135map_const DARK_CAVE_VIOLET_ENTRANCE, 20, 18(x 0..39, y 0..35), map id 70, group 3 - Attributes:
data/maps/attributes.asm:467, border block$09, no connections - Map events block:
DarkCaveVioletEntrance_MapEvents=47:42f5
Warps (def_warp_events)
| idx | x | y | destination map | dest warp |
|---|---|---|---|---|
| 1 | 3 | 15 | ROUTE_31 |
3 |
| 2 | 17 | 1 | DARK_CAVE_BLACKTHORN_ENTRANCE |
2 |
| 3 | 35 | 33 | ROUTE_46 |
3 |
Coord events - empty.
BG events (def_bg_events)
| x | y | type | script/item |
|---|---|---|---|
| 26 | 3 | BGEVENT_ITEM |
DarkCaveVioletEntranceHiddenElixer -> hiddenitem ELIXER, EVENT_DARK_CAVE_VIOLET_ENTRANCE_HIDDEN_ELIXER |
Object events (def_object_events)
| const | sprite | x | y | movement | type | script label | event flag |
|---|---|---|---|---|---|---|---|
DARKCAVEVIOLETENTRANCE_POKE_BALL1 |
SPRITE_POKE_BALL |
6 | 8 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
DarkCaveVioletEntrancePotion (itemball POTION) |
EVENT_DARK_CAVE_VIOLET_ENTRANCE_POTION |
DARKCAVEVIOLETENTRANCE_ROCK1 |
SPRITE_ROCK |
16 | 14 | SPRITEMOVEDATA_SMASHABLE_ROCK |
OBJECTTYPE_SCRIPT |
DarkCaveVioletEntranceRock (jumpstd SmashRockScript) |
-1 |
DARKCAVEVIOLETENTRANCE_ROCK2 |
SPRITE_ROCK |
27 | 6 | SPRITEMOVEDATA_SMASHABLE_ROCK |
OBJECTTYPE_SCRIPT |
DarkCaveVioletEntranceRock |
-1 |
DARKCAVEVIOLETENTRANCE_ROCK3 |
SPRITE_ROCK |
7 | 14 | SPRITEMOVEDATA_SMASHABLE_ROCK |
OBJECTTYPE_SCRIPT |
DarkCaveVioletEntranceRock |
-1 |
DARKCAVEVIOLETENTRANCE_ROCK4 |
SPRITE_ROCK |
36 | 31 | SPRITEMOVEDATA_SMASHABLE_ROCK |
OBJECTTYPE_SCRIPT |
DarkCaveVioletEntranceRock |
-1 |
DARKCAVEVIOLETENTRANCE_POKE_BALL2 |
SPRITE_POKE_BALL |
36 | 22 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
DarkCaveVioletEntranceFullHeal (itemball FULL_HEAL) |
EVENT_DARK_CAVE_VIOLET_ENTRANCE_FULL_HEAL |
DARKCAVEVIOLETENTRANCE_POKE_BALL3 |
SPRITE_POKE_BALL |
35 | 9 | SPRITEMOVEDATA_STILL |
OBJECTTYPE_ITEMBALL |
DarkCaveVioletEntranceHyperPotion (itemball HYPER_POTION) |
EVENT_DARK_CAVE_VIOLET_ENTRANCE_HYPER_POTION |
Note the four rocks all share one script label; the smash disappear LAST_TALKED
in RockSmashScript acts on hLastTalked, so they are independent objects
despite the shared pointer. Rocks have no event flag (-1) - they come back
on every map reload.
Scripts of interest
DarkCaveVioletEntranceRock - jumpstd SmashRockScript
(engine/events/std_scripts.asm:199 -> farsjump AskRockSmashScript, 03:4f60).
AskRockSmashScript calls HasRockSmash (03:4f7f), which is inverted
(wScriptVar = 1 when the party does NOT know ROCK SMASH); on 0 it prompts
yes/no and falls into RockSmashScript (03:4f35):
playsound SFX_STRENGTH / earthquake 84 / applymovementlasttalked MovementData_RockSmash
/ disappear LAST_TALKED / callasm RockMonEncounter / randomwildmon /
startbattle.
Wild encounters
data/wild/johto_grass.asm:1517 def_grass_wildmons DARK_CAVE_VIOLET_ENTRANCE,
rate 4 percent morn/day/nite, all three lists identical:
| slot | lvl | species |
|---|---|---|
| 1 | 3 | GEODUDE |
| 2 | 2 | ZUBAT |
| 3 | 2 | GEODUDE |
| 4 | 4 | GEODUDE |
| 5 | 3 | ZUBAT |
| 6 | 4 | ZUBAT |
| 7 | 4 | DUNSPARCE |
data/wild/johto_water.asm:107 def_water_wildmons DARK_CAVE_VIOLET_ENTRANCE,
rate 2 percent: 15 MAGIKARP / 10 MAGIKARP / 5 MAGIKARP.
Rock smash encounters - this map IS in data/wild/treemon_maps.asm:46
RockMonMaps: treemon_map DARK_CAVE_VIOLET_ENTRANCE, TREEMON_SET_ROCK.
RockMonEncounter (2e:63a1) rolls RandomRange 10 < 4 (a 40% chance) and then
SelectTreeMon over data/wild/treemons.asm:91 TreeMonSet_Rock:
90% KRABBY lvl 15, 10% SHUCKLE lvl 15. This is the only Shuckle source in
Johto reachable in this section, and the walkthrough does not mention it.
3. Blockers and gates
| Gate | Enforced by (file:label) | Requirement | Unlock condition |
|---|---|---|---|
| Darkness on all six maps | engine/tilesets/timeofday_pals.asm ReplaceTimeOfDayPals (23:43e9) .NeedsFlash -> DARKNESS_PALSET, because data/maps/maps.asm lines 127-130 / 148-149 all say PALETTE_DARK |
FLASH cast, i.e. STATUSFLAGS_FLASH_F set in wStatusFlags |
engine/events/overworld.asm FlashFunction.CheckUseFlash (03:48f1): ENGINE_ZEPHYRBADGE and wTimeOfDayPalset == DARKNESS_PALSET. The bit is cleared by home/flag.asm ResetFlashIfOutOfCave (00:2f1d) on any ROUTE/TOWN map, so re-cast after every exit and every Fly |
Mt. Mortar middle entrance (ROUTE_42 warp 4 at (28,9)) |
terrain: the tile is across water on Route 42 | SURF | engine/events/overworld.asm SurfFunction (03:493b), .TrySurf arm / TrySurfOW (03:4a06): ENGINE_FOGBADGE + a party member knowing SURF |
| The lake and the waterfall between 1F Outside and 2F | terrain on MountMortar1FOutside.blk; the only route to warp 4 at (17,5) |
SURF, then WATERFALL | WaterfallFunction.TryWaterfall (03:4af6) / TryWaterfallOW (03:4b5f): ENGINE_RISINGBADGE, then CheckMapCanWaterfall - player must be facing UP and the tile ABOVE (wTileUp) must be a waterfall tile |
MOUNTMORTAR1FINSIDE_BOULDER at (21,43) |
MountMortar1FBoulder -> jumpstd StrengthBoulderScript -> AskStrengthScript (03:4d4e) |
STRENGTH toggled on | TryStrengthOW (03:4d7b): party knows STRENGTH and ENGINE_PLAINBADGE and BIKEFLAGS_STRENGTH_ACTIVE_F set. StrengthFunction.TryStrength (03:4cf1) only checks the badge. Note ResetBikeFlags clears the active bit on every map load - Strength must be re-activated per floor |
MOUNTMORTARB1F_BOULDER at (9,10) |
MountMortarB1FBoulder, same std script |
STRENGTH | as above. This is the walkthrough's "move the rock with HM Strength to get out"; the alternative is an Escape Rope |
| Kiyo's Tyrogue | MountMortarB1FKiyoScript readvar VAR_PARTYCOUNT / ifequal PARTY_LENGTH, .NoRoom |
5 or fewer party members | free a slot and re-talk; EVENT_BEAT_BLACKBELT_KIYO stays set so the battle is not repeated |
| Dark Cave water crossings (both entrances) | terrain | SURF | ENGINE_FOGBADGE as above |
DARKCAVEVIOLETENTRANCE_ROCK1..4 |
DarkCaveVioletEntranceRock -> jumpstd SmashRockScript -> AskRockSmashScript (03:4f60) |
a party member knowing ROCK SMASH (TM08) | HasRockSmash (03:4f7f) - no badge check at all for Rock Smash |
| Fly between Mahogany and Blackthorn | engine/events/overworld.asm:545 (the .TryFly arm of the Fly jumptable) ld de, ENGINE_STORMBADGE |
ENGINE_STORMBADGE + the destination's ENGINE_FLYPOINT_* (constants/engine_flags.asm:87, :89) |
both flypoints are set by visiting the towns in earlier sections |
Badge constants used above: ENGINE_ZEPHYRBADGE (constants/engine_flags.asm:38),
ENGINE_PLAINBADGE (:40), ENGINE_FOGBADGE (:41), ENGINE_STORMBADGE
(:43), ENGINE_RISINGBADGE (:45). All are checked through
engine/events/overworld.asm CheckBadge (line 50), which prints
"Badge required" and returns carry.
Nothing in this section gates anything else. Both Mt. Mortar and Dark Cave are entirely optional; a bot that skips them loses only items, the Tyrogue and the Blackglasses.
4. Bot checklist
Preconditions for the whole section: ENGINE_ZEPHYRBADGE, ENGINE_FOGBADGE,
ENGINE_PLAINBADGE, ENGINE_RISINGBADGE, ENGINE_STORMBADGE; party members
knowing FLASH, SURF, STRENGTH, WATERFALL (and ROCK SMASH for step 26); party
count <= 5 before step 20.
| # | Map | Target | Intent | Precondition | Postcondition |
|---|---|---|---|---|---|
| 1 | MAHOGANY_TOWN |
spawn (15,14) | Fly in, heal, buy MAX_REPEL / ESCAPE_ROPE | ENGINE_FLYPOINT_MAHOGANY |
party healthy, bag stocked |
| 2 | MAHOGANY_TOWN |
west map connection | walk west | - | on ROUTE_42 |
| 3 | ROUTE_42 |
warp 3 at (10,5) | step onto warp (west entrance) | - | on MOUNT_MORTAR_1F_OUTSIDE at (3,33) |
| 4 | MOUNT_MORTAR_1F_OUTSIDE |
- | use FLASH from the PACK/party menu | ENGINE_ZEPHYRBADGE, map palset is DARKNESS_PALSET |
STATUSFLAGS_FLASH_F set |
| 5 | MOUNT_MORTAR_1F_OUTSIDE |
- | use MAX_REPEL | bag has one | encounters suppressed |
| 6 | MOUNT_MORTAR_1F_OUTSIDE |
object at (13,15) | walk onto / A-press the Poke Ball | EVENT_MOUNT_MORTAR_1F_OUTSIDE_ETHER clear |
ETHER in bag, flag set |
| 7 | MOUNT_MORTAR_1F_OUTSIDE |
object at (31,18) | pick up Poke Ball | EVENT_MOUNT_MORTAR_1F_OUTSIDE_REVIVE clear |
GUARD_SPEC in bag, flag set |
| 8 | MOUNT_MORTAR_1F_OUTSIDE |
bg event (25,22) | face the tile, press A | EVENT_MOUNT_MORTAR_1F_OUTSIDE_HIDDEN_HYPER_POTION clear |
HYPER_POTION in bag, flag set |
| 9 | MOUNT_MORTAR_1F_OUTSIDE |
warp 5 at (11,21) | step on warp | - | on MOUNT_MORTAR_1F_INSIDE at (11,47) |
| 10 | MOUNT_MORTAR_1F_INSIDE |
- | re-cast FLASH only if it was lost (it is not - cave to cave keeps the bit) | - | - |
| 11 | MOUNT_MORTAR_1F_INSIDE |
object at (33,22) | pick up Poke Ball | EVENT_MOUNT_MORTAR_1F_INSIDE_ESCAPE_ROPE clear |
ESCAPE_ROPE in bag |
| 12 | MOUNT_MORTAR_1F_INSIDE |
object at (12,21) | pick up Poke Ball | EVENT_MOUNT_MORTAR_1F_INSIDE_HYPER_POTION clear |
HYPER_POTION in bag |
| 13 | MOUNT_MORTAR_1F_INSIDE |
boulder at (21,43) | activate STRENGTH from the party menu, then push | ENGINE_PLAINBADGE, party knows STRENGTH |
BIKEFLAGS_STRENGTH_ACTIVE_F set, boulder movable |
| 14 | MOUNT_MORTAR_1F_INSIDE |
warp 1 at (11,47) | back out | - | on MOUNT_MORTAR_1F_OUTSIDE at (11,21) |
| 15 | MOUNT_MORTAR_1F_OUTSIDE |
the lake | walk into water / A-press facing water -> SURF | ENGINE_FOGBADGE |
wPlayerState = PLAYER_SURF |
| 16 | MOUNT_MORTAR_1F_OUTSIDE |
the waterfall tile | face UP at the waterfall, press A -> WATERFALL | ENGINE_RISINGBADGE, CheckMapCanWaterfall passes |
climbed |
| 17 | MOUNT_MORTAR_1F_OUTSIDE |
warp 4 at (17,5) | step on warp | - | on MOUNT_MORTAR_2F_INSIDE at (17,33) |
| 18 | MOUNT_MORTAR_2F_INSIDE |
objects at (31,23), (2,24), (19,17), (14,5), (8,9), (28,5) | pick up all six Poke Balls | matching EVENT_MOUNT_MORTAR_2F_INSIDE_* clear |
MAX_POTION, RARE_CANDY, TM_DEFENSE_CURL (TM40), DRAGON_SCALE, ELIXER, ESCAPE_ROPE |
| 19 | MOUNT_MORTAR_2F_INSIDE |
bg event (19,6) | face, press A | EVENT_MOUNT_MORTAR_2F_INSIDE_HIDDEN_FULL_RESTORE clear |
FULL_RESTORE in bag |
| 20 | MOUNT_MORTAR_2F_INSIDE |
warp 2 at (3,5) | step on warp | - | on MOUNT_MORTAR_1F_INSIDE at (9,9) |
| 21 | MOUNT_MORTAR_1F_INSIDE |
object at (16,10) | pick up Poke Ball | EVENT_MOUNT_MORTAR_1F_INSIDE_MAX_REVIVE clear |
MAX_REVIVE in bag |
| 22 | MOUNT_MORTAR_1F_INSIDE |
bg event (31,9) | face, press A | EVENT_MOUNT_MORTAR_1F_INSIDE_HIDDEN_MAX_REPEL clear |
MAX_REPEL in bag |
| 23 | MOUNT_MORTAR_1F_INSIDE |
warp 5 at (3,19) | step on warp | - | on MOUNT_MORTAR_B1F at (3,3) |
| 24 | MOUNT_MORTAR_B1F |
bg (4,6), objects (4,16) and (31,17) | pick up hidden MAX_REVIVE, FULL_HEAL, HYPER_POTION | matching EVENT_MOUNT_MORTAR_B1F_* clear |
three items |
| 25 | MOUNT_MORTAR_B1F |
MOUNTMORTARB1F_KIYO at (13,4) |
stand adjacent, press A | party count <= 5, EVENT_GOT_TYROGUE_FROM_KIYO clear |
battle BLACKBELT_T/KIYO (L34 HITMONLEE, L34 HITMONCHAN) -> EVENT_BEAT_BLACKBELT_KIYO |
| 26 | MOUNT_MORTAR_B1F |
Kiyo (same object, script continues) | press A through the reward text | party count <= 5 | givepoke TYROGUE, 10, EVENT_GOT_TYROGUE_FROM_KIYO set |
| 27 | MOUNT_MORTAR_B1F |
- | use ESCAPE_ROPE (or STRENGTH the boulder at (9,10) then warp 2 at (19,29)) | ESCAPE_ROPE in bag | out of the cave |
| 28 | anywhere outdoors | SPAWN_BLACKTHORN |
Fly to Blackthorn, heal | ENGINE_STORMBADGE, ENGINE_FLYPOINT_BLACKTHORN |
at Blackthorn spawn (21,30); STATUSFLAGS_FLASH_F is now cleared |
| 29 | BLACKTHORN_CITY |
south map connection | walk south | - | on ROUTE_45 |
| 30 | ROUTE_45 |
warp 1 at (2,5) | step on warp | - | on DARK_CAVE_BLACKTHORN_ENTRANCE at (23,3) |
| 31 | DARK_CAVE_BLACKTHORN_ENTRANCE |
- | use FLASH again | ENGINE_ZEPHYRBADGE |
STATUSFLAGS_FLASH_F set |
| 32 | DARK_CAVE_BLACKTHORN_ENTRANCE |
water in the middle of the map | SURF | ENGINE_FOGBADGE |
crossing possible |
| 33 | DARK_CAVE_BLACKTHORN_ENTRANCE |
DARKCAVEBLACKTHORNENTRANCE_PHARMACIST at (7,3) |
stand adjacent, press A | EVENT_GOT_BLACKGLASSES_IN_DARK_CAVE clear, item pocket has room |
BLACKGLASSES, flag set |
| 34 | DARK_CAVE_BLACKTHORN_ENTRANCE |
objects at (7,22) and (21,24) | pick up both Poke Balls | matching events clear | TM_SNORE (TM13), REVIVE |
| 35 | DARK_CAVE_BLACKTHORN_ENTRANCE |
warp 2 at (3,25) | step on warp | - | on DARK_CAVE_VIOLET_ENTRANCE at (17,1) |
| 36 | DARK_CAVE_VIOLET_ENTRANCE |
water below (17,1) | SURF down | ENGINE_FOGBADGE |
- |
| 37 | DARK_CAVE_VIOLET_ENTRANCE |
rock at (16,14) or (7,14) | face rock, press A, answer yes | party knows ROCK_SMASH | rock gone; 40% chance of a KRABBY/SHUCKLE L15 battle |
| 38 | DARK_CAVE_VIOLET_ENTRANCE |
object at (6,8) | pick up Poke Ball | EVENT_DARK_CAVE_VIOLET_ENTRANCE_POTION clear |
POTION in bag |
| 39 | DARK_CAVE_VIOLET_ENTRANCE |
warp 1 at (3,15) | step on warp | - | on ROUTE_31 at (34,5); FLASH bit cleared |
| 40 | ROUTE_31 |
- | Fly back to Blackthorn, heal | - | section complete |
Optional extras this route skips, with their coordinates if a completionist bot
wants them: DARK_CAVE_VIOLET_ENTRANCE objects at (36,22) FULL_HEAL and (35,9)
HYPER_POTION plus the hidden ELIXER bg at (26,3) - all three sit on the
north-east lobe of the map that the earlier Route 31 section already reaches.
5. Port coverage
| Beat | Port file | Status |
|---|---|---|
| Map headers / dimensions for all six maps | tools/rom_manifest_gold.json (e.g. MOUNT_MORTAR_1F_OUTSIDE 20x18 group 3 map 49, DARK_CAVE_BLACKTHORN_ENTRANCE 15x18 group 3 map 71), read by src/import/RomExtractorGen2.lua |
implemented (extracted from ROM, no hand-ported map file needed) |
| Warp / coord / bg / object event tables | src/import/RomExtractorGen2.lua (warps, coordEvents, bgEvents, objects around lines 787-862) -> src/world/gen2/Map.lua |
implemented |
PALETTE_DARK -> DARKNESS_PALSET and the FLASH override |
src/world/gen2/Palettes.lua, asserted by tests/gen2_palettes_test.lua:118-129 (dark cave / dark cave with flash) |
implemented |
ResetFlashIfOutOfCave (FLASH dies on ROUTE/TOWN) |
src/world/gen2/World.lua:5622-5625 |
implemented |
| FLASH / SURF / WATERFALL / STRENGTH badge gates | src/world/gen2/FieldMoves.lua:105-110 (FLASH=ZEPHYR, SURF=FOG, STRENGTH=PLAIN, WATERFALL=RISING), FieldMoves.flashFromMenu / surfFromMenu / waterfallFromMenu / strengthFromMenu |
implemented |
CheckMapCanWaterfall (facing UP, wTileUp) and the climb loop |
src/world/gen2/FieldMoves.lua:253-266, src/world/gen2/World.lua:4030-4046 runWaterfall / waterfallStep, World:tryWaterfallOW (4217) |
implemented |
Strength boulder push (StrengthBoulderScript -> AskStrengthScript) |
src/world/gen2/World.lua:5268-5274 (the boulder arm of World:interact), World:tryStrengthOW, driver tests/drivers/gold_icepath_boulder.lua |
implemented |
BIKEFLAGS_STRENGTH_ACTIVE_F cleared on map load |
src/world/gen2/World.lua:5611-5613 |
implemented |
Hidden items (BGEVENT_ITEM / hiddenitem) |
src/world/gen2/HiddenItems.lua, wired at src/world/gen2/World.lua:5290-5296 |
implemented |
verbosegiveitem BLACKGLASSES (the Dark Cave pharmacist) |
src/script/gen2/Vm.lua:490-510, hook World.lua:831 giveItem |
implemented |
givepoke TYROGUE, 10 (Kiyo's reward) |
src/script/gen2/Vm.lua:439-445, hook World.lua:812 givePoke |
implemented |
readvar VAR_PARTYCOUNT (Kiyo's "no room" branch) |
src/world/gen2/World.lua:112 VAR_PARTYCOUNT = 0x01, read at World.lua:1225 |
implemented |
loadtrainer / startbattle / winlosstext / reloadmapafterbattle |
src/script/gen2/Vm.lua:806, :817, :886, :918; src/world/gen2/Trainers.lua; driver tests/drivers/gold_trainer_smoke.lua |
implemented |
| Tyrogue's three-way stat evolution (what the reward mon becomes) | src/core/gen2/Evolution.lua:71, asserted by tests/gen2_evolution_test.lua:347-357 |
implemented |
| Repel / Max Repel step counter | src/world/gen2/World.lua:3382 World:useRepel, src/ui/gen2/PackMenu.lua:199-206 |
implemented |
Picking up a Poke Ball (OBJECTTYPE_ITEMBALL) |
extracted into obj.itemball by src/import/RomExtractorGen2.lua:2968-2969, but World:interact (src/world/gen2/World.lua:5256-5310) has arms for trainer, boulder, scriptKey, BGEVENT_READ and BGEVENT_ITEM and no itemball arm; CallAsm.lua:551 stubs TryReceiveItem out |
missing - all 15 Poke Balls in this section are unobtainable in the port today |
| ROCK SMASH as a field move | src/script/gen2/CallAsm.lua:346-350 implements HasRockSmash, but line 526 stubs RockMonEncounter with the note "ROCK SMASH has no field-move path yet; RockMonMaps is unported"; World:interact's tile-event chain (World.lua:5301-5308) lists cut / whirlpool / waterfall / headbutt / surf and not rock smash, and nothing in src/ references SPRITEMOVEDATA_SMASHABLE_ROCK |
missing - the four Dark Cave Violet rocks cannot be broken, and the Krabby/Shuckle table is unreachable |
| ESCAPE_ROPE / DIG as a field item | src/world/gen2/World.lua:3293-3302 World:useFieldItem handles ITEMFINDER, BICYCLE, SACRED_ASH, repels, trophy boxes and rods only. (Gen 1's path exists at src/ui/BagMenu.lua:231-240, but that is the Red/Blue engine, not the Gen 2 one.) |
missing - the walkthrough's "use one of the Escape Ropes to get out" has no port path; the Strength-boulder exit at B1F (9,10) does work |
| Fly to Mahogany / Blackthorn | src/world/gen2/FieldMoves.lua:394-440 hasVisitedSpawn / flyPoints, flyFromMenu (504) |
implemented |
| Wild encounter tables (grass + water + fishing) for these maps | extracted; src/world/gen2/FieldMoves.lua:162-177 canEncounterWildMon / encounterTable |
implemented (not separately verified against these six maps) |
No driver in tests/drivers/gold_*.lua visits Mt. Mortar or Dark Cave.
6. Unresolved / verify by hand
- The walkthrough's Mt. Mortar item list is the HGSS list, not the GS list.
It names Carbos, Escape Rope x2, Full Restore, Hyper Potion x2, Max Ether,
Max Potion, Max Revive, PP Up, Rare Candy, Dragon Scale and "TM40 Aerial
Ace". What is actually in
maps/MountMortar*.asmis: ETHER, GUARD_SPEC, hidden HYPER_POTION (1F Outside); ESCAPE_ROPE, MAX_REVIVE, HYPER_POTION, hidden MAX_REPEL (1F Inside); MAX_POTION, RARE_CANDY, TM_DEFENSE_CURL, DRAGON_SCALE, ELIXER, ESCAPE_ROPE, hidden FULL_RESTORE (2F Inside); HYPER_POTION, FULL_HEAL, hidden MAX_REVIVE (B1F). No CARBOS, no PP_UP, no MAX_ETHER, no IRON anywhere in Mt. Mortar. TM40 is the right number but the move is DEFENSE_CURL (constants/item_constants.asm:261); Aerial Ace is a Gen 3 move that does not exist in this disassembly. - "grab the free Iron on the cliff" (1F Inside, after coming down from 2F). There is no IRON object on any Mt. Mortar map. The nearest items to warp 6 at (9,9) are the MAX_REVIVE ball at (16,10) and the hidden MAX_REPEL bg event at (31,9). Treat "Iron" as an HGSS-only pickup.
- "surf clockwise around and reach a Hyper Potion and a Max Ether." There is no MAX_ETHER in Mt. Mortar. If the intended floor is B1F (the ladder from the central entrance) the pair is HYPER_POTION (31,17) + FULL_HEAL (4,16); if 2F, the closest analogue is ELIXER (8,9). Which one the author meant could not be determined from the asm.
- Kiyo's prize money and EXP yields. The walkthrough gives 816G and
1012/1020 EXP.
data/trainers/parties.asmonly carries the class, name, type byte and party; the money formula lives in the battle engine'sdata/trainers/attributes.asmbase-money table times level, which was not opened for this document. The party itself is verified: L34 HITMONLEE, L34 HITMONCHAN,TRAINERTYPE_NORMAL(default moves, no held items). - "a giant room where you can zig zag around ... and get two items, to include
a Hyper Potion and Escape Rope."
MOUNT_MORTAR_1F_INSIDEactually holds three balls (ESCAPE_ROPE (33,22), MAX_REVIVE (16,10), HYPER_POTION (12,21)) plus a hidden MAX_REPEL - but MAX_REVIVE and the hidden item sit on the section of the map only reachable from 2F, which is presumably why the walkthrough counts two. - "The west entrance and east entrance lead to each other." All three Route
42 doors land on the same map,
MOUNT_MORTAR_1F_OUTSIDE; the west/east link runs throughMOUNT_MORTAR_1F_INSIDEvia warp pairs 5/6 (at y=21) and 8/9 (at y=13). The blk files were not decoded, so the exact walkable path between any two of these warps is not verified here - only the warp graph is. - Dark Cave Pokemon list. The walkthrough lists Zubat, Golbat, Geodude,
Graveler, Magikarp and Wobbuffet - that is the
DARK_CAVE_BLACKTHORN_ENTRANCEtable exactly. It omits DUNSPARCE, which is slot 7 ofDARK_CAVE_VIOLET_ENTRANCEand is on the map the route exits through. - Dark Cave item list. The walkthrough lists Blackglasses, Full Heal, Hyper
Potion, Revive and TM13. The Full Heal (36,22) and Hyper Potion (35,9) are on
DARK_CAVE_VIOLET_ENTRANCE's north-east lobe, which this route does not pass through; the hidden ELIXER at (26,3) is not mentioned at all. The POTION at (6,8) is named in the prose but missing from the list. - The Shuckle/Krabby rock-smash table (
data/wild/treemon_maps.asm:46,data/wild/treemons.asm:91) is real and reachable atDARK_CAVE_VIOLET_ENTRANCE, but the walkthrough never mentions it. Worth flagging to a bot author as a cheap Shuckle source. MOUNT_MORTAR_1F_OUTSIDEobject 2 flag naming. The item isGUARD_SPECbut the event flag isEVENT_MOUNT_MORTAR_1F_OUTSIDE_REVIVE(constants/event_flags.asm:1053). Verbatim from the disassembly; not a transcription error here, but it will look like one to anyone grepping by item name.- Mahogany Town and Blackthorn City interiors (Poke Center, Mart, gym) were
not opened for this document - only their
data/maps/maps.asmheader rows anddata/maps/spawn_points.asmentries. Those maps belong to neighbouring sections.