07 — Into the Rift

Building a 5-tier endgame dungeon from scratch


The Design

Every loot game needs an endgame. Without it, you hit the credits and the gear system loses its purpose. The Rift Zone is my answer: a post-Champion gauntlet of 5 increasingly difficult dungeon floors, each with corrupted wild Pokémon, a boss trainer, and shard rewards that fuel the crafting loop.

Narratively, it’s the wound the Primal Guardians left behind. Mechanically, it’s where gear matters most.

Building Maps from Nothing

FireRed’s map system is complex. Each map needs:

  1. Layout — dimensions, tileset references, blockdata (the actual tile grid)
  2. Map data — connections, warps, events, NPC positions
  3. Scripts — event logic in a custom assembly-like language
  4. Text — dialogue strings
  5. Encounters — wild Pokémon tables
  6. Registration — entries in layouts.json, map_groups.json, and event_scripts.s

For 5 maps, that’s 35+ files.

Blockdata Generation

Each map tile is a u16 value:

Bits 0-9:   Metatile ID (which 16×16 tile pattern to display)
Bits 10-11: Collision (0=passable, 1=impassable)
Bits 12-15: Elevation (for bridges, stairs, etc.)

A 20×15 map is 600 tiles = 1,200 bytes. Claude wrote a Python script to generate cave rooms using the CeruleanCave tileset:

The Warp Chain

The 5 tiers are connected by warps:

Cinnabar Island → Tier 1 (bottom) → Tier 2 (bottom) → Tier 3 (bottom)
→ Tier 4 (bottom) → Tier 5 (top exits to Cinnabar)

Each tier’s bottom warp leads to the next tier’s entrance. Tier 5’s top warp returns to Cinnabar. A simple linear path — no backtracking, no map selection screen.

Boss Trainers

Five Rift Shades, each embodying a corruption theme:

Tier Name Theme Level Range Party
1 The Dark Caller Darkness 50-52 Houndoom, Murkrow, Sneasel
2 The Rotting One Poison/Decay 55-57 Muk, Weezing, Crobat, Vileplume
3 The Hollow Mind Ghost/Death 60-62 Gengar, Misdreavus, Dusclops, Sableye
4 The Silent Scream Psychic/Madness 65-67 Alakazam, Hypno, Mr. Mime, Gardevoir, Starmie
5 The Rift Itself Pure Corruption 70-75 Tyranitar, Gengar, Dragonite, Salamence, Metagross, Alakazam

The final Shade has 6 Pokémon — the maximum. Its dialogue acknowledges the player:

“You carry the fire of the Guardians… but I AM the wound they left behind!”

Shard Rewards

Defeating a boss triggers shard rewards via a script→C bridge:

// Script:
setvar VAR_0x8000, 15
special SpecialAddGearShards
setvar VAR_0x8000, 5
special SpecialAddRadiantShards
// C:
void SpecialAddGearShards(void) {
    AddGearShards(gSpecialVar_0x8000);
}

Rewards escalate:

The Build Failures

First build attempt: 3 errors.

Error 1: TRAINER_PIC_BOSS undefined

Claude assumed a “BOSS” trainer pic existed. It doesn’t. The fix: TRAINER_PIC_CHAMPION_RIVAL — the closest existing sprite to a mysterious powerful figure.

Lesson: Always check include/constants/trainers.h for valid trainer pic IDs. Intuitive names often don’t exist.

Error 2: OBJ_EVENT_GFX_PSYCHIC_M undefined

Same problem for NPC sprites. OBJ_EVENT_GFX_PSYCHIC_M doesn’t exist in the constants. Fixed to OBJ_EVENT_GFX_GENTLEMAN.

Lesson: Always check include/constants/event_objects.h. Available sprites are a small subset of what you’d expect.

Error 3: Script labels undefined

This was the big one. All 10 script files (5 scripts.inc + 5 text.inc) compiled individually but the linker couldn’t find any of their labels.

Root cause: The map build system auto-generates header.inc, events.inc, and connections.inc from map.json. But scripts.inc and text.inc are NOT auto-included. They must be manually added as .include directives in data/event_scripts.s.

@ In data/event_scripts.s — must be added manually:
	.include "data/maps/RiftZone_Tier1/scripts.inc"
	.include "data/maps/RiftZone_Tier1/text.inc"
	@ ... repeat for all 5 tiers

This is the kind of gotcha that wastes hours if you don’t know about it. The build system handles 90% of map integration automatically. The remaining 10% is manual and undocumented.

Wild Encounters

Each tier has 12 corruption-themed species across land, water, and fishing encounters:

All Dark/Poison/Ghost types. The corruption theme runs deep.

Resource Budget

After the Rift Zone, the remaining resources:

The GBA is nearly full. Every new feature from here needs to be surgically precise about resource usage.

By the Numbers

Metric Value
Commits ~10
Copilot requests ~20
Tool executions ~186
Sub-agents 6

Next: 08 — What’s Next