Pixel-Art Routes: Map Connections and Districts on iPhone

Pokémon’s first three generations all walk one 16-pixel cell in 16 frames, about 3.73 cells a second, and Kiradex’s collector walks 4 tiles a second, so a road measured in the old games converts to our town at a quarter-second a tile.1234 The first route of each game spans two to six console screens and has no trainers; the first leg, from the player’s front door to the next town’s Center, is 58 cells and 15.5 seconds of walking in Emerald and 94 cells and 25.2 seconds in FireRed, and the walk back is shorter in both, 42 and 76 cells, over routes whose ledges all face home.567 Where the art changes, Kanto puts a building in the road: 76 of Red’s 78 map connections join one tileset, and every Red gatehouse between two different places joins two.8 Hoenn’s engine copies seven cells of the neighboring map into a margin around the current one on three sides and eight on the east, draws them with the current map’s tiles, and loads the neighbor’s own secondary tiles and palette at the moment you cross, with no fade.910 Emerald’s map screen is a grid of 28 by 15 squares; a wall map upstairs in the player’s house in Littleroot opens it, the PokéNav carries it from Rustboro on, and it draws every place, visited or not, except two that wait on story flags, while Fly lists only the towns whose visited flag was set when you walked in.111213 Kiradex World today is one 40-by-30 town with nothing past the fence.14 So I measured the canon’s roads, seams, gates and map screens from the decompilations, read Stardew Valley, Animal Crossing and Link’s Awakening as the contrasting models, and turned the numbers into a brief for four areas past the plaza, a map screen, and a tram that opens a stop the first time you arrive.

TL;DR

  • A walk cell costs 16 frames, about a quarter of a second. Red, Crystal and Emerald all walk at 16 frames a cell and run or ride at 8, which at the hardware’s 59.7 hertz is 3.73 and 7.47 cells a second; Kiradex is set to walk 4 tiles a second, about 7% faster than the handhelds, and to run at a nominal 6.4, which a frame model of its code puts at 6.00 at 60 hertz, about 20% under their run.1231541617
  • A route is 2 to 10 screens long, and the first one is short and the grassiest. Sixteen measured routes span 2.0 (Emerald Route 101) to 10.0 (Crystal Route 32) console screens along their axis; the four first routes are 14.4% to 22.8% tall grass by map area, the most in each game, and have no trainers. On the nine routes whose two ends meet on foot, the longer walk across is 1.15 to 1.70 times the route’s long side because the path winds, and the walk home 0.95 to 1.42.5617
  • Ledges make the way home shorter. On all nine measured routes whose two ends meet on foot, every one of them with ledges, the walk toward the earlier town is 2% to 44% shorter, and the fewest tall-grass cells on the way home are 0 to 5 against 4 to 19 on the way out.5618
  • Gatehouses stand where the art changes, and they carry the rules. Every Red gate between two places joins two tilesets; the gates hold a badge check, a thirsty guard, and three rewards for owning 10, 30 and 50 species. Hoenn’s engine loads a new tileset at the seam and keeps only 4 gate buildings to Red’s 27 gate-tileset maps.8192010
  • A Gen 3 seam draws seven cells of the neighbor (eight on the east) and loads its art at the crossing. The buffer margin is MAP_OFFSET 7 because “the player has 7 metatiles of view horizontally in either direction”, and the east side copies MAP_OFFSET + 1 columns; crossing loads the new map’s secondary tileset, music and weather and slides in a name popup for about 3.2 seconds, with no fade.91021
  • The map screen shows every place; fast travel shows where you have been. Emerald’s map is 28 by 15 squares, 158 of them used by 54 places, and once the player can open it (a wall map upstairs at home, then the PokéNav) it draws every place, visited or not, except two held back by story flags; a town becomes a Fly target only when its FLAG_VISITED_* flag is set on entry, and Red, FireRed, Crystal and Link’s Awakening keep the same kind of visited record.11121322232425
  • What this gives Kiradex. A brief for four areas past the Square (Binder Row, the Meadow Walk, the Lakeside and the Gallery Quarter) at 2.8 times the Square’s area, open seams with no fade, one eight-way walking graph for the app and the server, a 16-by-12 map screen, a tram whose stops open on a first visit, finds that are only cosmetics or quest notes, and thirteen acceptance checks a script or a capture can run.262728

1. Routes, measured

The three October 3 posts in this series stayed inside the fence. Pixel-Art Worlds on iPhone set the tile system and the RealityKit recipe, Pixel-Art People the collector, and Pixel-Art Structures the buildings and the doors. Kiradex World came out of them as one town: 40 by 30 tiles, the woods drawn 12 tiles beyond the fence, seven buildings whose doors lead to rooms or the hall, and one arrival tile.14 This post is about what lies past the fence, and it starts where the earlier ones did, with the decompilations.

Every Pokémon number below was measured from shallow clones of pret’s decompilations at pokered d2704a6, pokecrystal 5beda23, pokeemerald 731ad5b and pokefirered 037335f, by six small Python scripts that each re-run in about a second or less; the notes name the script behind each figure.29 The unit is the cell, one 16-by-16-pixel walk square: a Gen 3 metatile, or a quarter of a Gen 1 or Gen 2 block. A Game Boy screen shows 10 by 9 cells (160 by 144 pixels) and a Game Boy Advance screen 15 by 10 (240 by 160).29 The walking model is the same in every script: a step costs one cell; a ledge is crossed only in its direction and lands one cell beyond, two cells of movement; in Crystal, a step may not pass a tile’s one-sided wall, and a corner ledge hops either of its two ways (section 2 has the code); a seam counts only where the neighbor’s facing cell can be reached on foot from one of the neighbor’s doors; trainers and other people are ignored, and surfing is not modeled.29

The clock

All three generations walk at the same pace. In Red, OverworldLoop calls DelayFrame twice per iteration and AdvancePlayerSprite moves the view 2 pixels per iteration for 8 iterations (wWalkCounter is 8), so a cell takes 16 frames; on the bicycle AdvancePlayerSprite runs twice per iteration, 8 frames a cell.1 Crystal’s StepVectors give a walking step 8 ticks of 2 pixels and a bike step 4 ticks of 4 pixels, and its overworld runs one tick every 2 frames (MaxOverworldDelay: db 2), which is again 16 frames a cell walking and 8 on the bike.2 Emerald’s step tables have 16 entries for walking (sStep1Funcs), 8 for running and surfing, 6 for the Acro Bike and water currents, 4 for the Mach Bike at full speed and 2 for the fastest; a ledge jump (JUMP_DISTANCE_FAR) takes 32 frames for two cells and rises 12 pixels at its peak (sJumpY_High).3

The frame is the other half of the clock. GBATEK gives the Game Boy Advance’s frame as 280,896 cycles, “ca. 59.737 Hz”; Pan Docs gives the Game Boy’s as 70,224 dots “@ 59.7 fps”.1530 At 16 frames a cell, walking is about 3.73 cells a second and running about 7.47.17 The seconds in this post use 224 hertz divided by 280,896, which is 59.7275 frames a second; GBATEK gives 59.737, and the difference is under 0.02%.29

Kiradex’s collector walks at tilesPerSecond = 4 and runs at 1.6 times that, a nominal 6.4 tiles a second.4 The run’s figure is the constant, not the speed the code reaches: this series’ motion post modeled the code frame by frame and found the run covers 6.00 tiles a second at 60 hertz and 6.32 at 120, because each step throws away the progress it overshoots by.16 The walk is about 7% faster than the handhelds’ walk; the run is about 20% under theirs at 60 hertz, and 14% under at its nominal 6.4.17 The walk is close enough that a distance measured in their cells converts to ours at a fixed rate: a route’s time is its cells times 0.27 seconds at the handhelds’ walk, and its tiles times 0.25 seconds at ours.17

Sixteen routes

I measured the first four routes of each game: Red’s Routes 1 to 4, Crystal’s 29 to 32, Emerald’s 101 to 104 and FireRed’s 1 to 4. Gen 3 cells are read from map.bin (bits 0 to 9 the metatile, 10 and 11 collision, 12 to 15 elevation) and each cell’s behavior looked up in the primary or secondary metatile_attributes.bin; trainers are the map’s object events whose trainer_type is not TRAINER_TYPE_NONE.6 Gen 1 cells read the lower-left 8-by-8 tile of each 16-by-16 cell against the tileset’s collision list, the grass tile $52 and the ledge table; Gen 2 cells read the four collision bytes each block carries per quadrant.5

Game Route Size (cells) Screens along its axis Walkable Tall grass, cells (% of map) Ledge cells / runs Trainers Shortest walk across, each way (cells)
Red 1 20 by 36 4.0 76.8% 104 (14.4%) 42 / 10 0 south 40, north 52
Red 2 20 by 72 8.0 55.9% 84 (5.8%) 52 / 14 0 split by a forest
Red 3 70 by 18 7.0 35.1% 100 (7.9%) 36 / 10 8 toward Pewter 82, away 84
Red 4 90 by 18 9.0 45.0% 60 (3.7%) 169 / 27 1 split by a cave
Crystal 29 60 by 18 6.0 47.7% 160 (14.8%) 35 / 13 0 east 71, west 90
Crystal 30 20 by 54 6.0 47.6% 140 (13.0%) 21 / 6 3 south 57, north 74
Crystal 31 40 by 18 4.0 39.3% 64 (8.9%) 13 / 5 1 west end is a gate
Crystal 32 20 by 90 10.0 48.3% 152 (8.4%) 6 / 5 8 south 132, north 128
Emerald 101 20 by 20 2.0 59.2% 91 (22.8%) 13 / 3 plus 1 corner 0 south 19, north 34
Emerald 102 50 by 20 3.3 48.9% 143 (14.3%) 17 / 4 4 east 55, west 62
Emerald 103 80 by 22 5.3 27.3% 92 (5.2%) 24 / 3 9 split by sea
Emerald 104 40 by 80 8.0 34.0% 126 (3.9%) 13 / 4 8 split by a forest
FireRed 1 24 by 40 4.0 62.3% 178 (18.5%) 61 / 10 0 south 43, north 58
FireRed 2 24 by 80 8.0 40.8% 84 (4.4%) 44 / 13 0 split by a forest
FireRed 3 84 by 20 5.6 37.6% 117 (7.0%) 42 / 10 8 toward Pewter 94, away 97
FireRed 4 108 by 20 7.2 42.9% 84 (3.9%) 186 / 28 1 split by a cave

Sources for the table: measure_gen12_routes.py and measure_gen3_routes.py over the four decompilations.56 The screens column divides the long side by the console’s view along that axis (10 or 9 cells on the Game Boy, 15 or 10 on the Game Boy Advance). The walkable column is the share of cells a walker may stand on. Ledge cells are the jump cells in Gens 1 and 3 and the lip cells in Gen 2. Walks run between door-reachable seam cells, and a split route is one where no seam-to-seam walk exists inside the map because a forest, a cave, a gate or the sea stands between the halves.29

Bar chart of sixteen early Pokémon routes: the long side of each map in cells, with dots for the shortest walk across it each way and a label for the console screens it spans, from Emerald Route 101 at 2.0 screens to Crystal Route 32 at 10.0, over an axis in cells and seconds at a walk.

Route length on the long axis, with the shortest walk across each way; drawn by figures/make_figures.py from the two route scripts’ outputs.

Five things fall out of the table.

Routes span 2 to 10 screens, and the first is short. Emerald Route 101 is two Game Boy Advance screens tall; Crystal Route 32 is ten Game Boy screens tall; the first route of each game is two to six screens.56 In cells the measured routes run from 20 to 108 along their long side.6

The longer walk across is 1.15 to 1.70 times the long side. Nine of the sixteen routes can be walked end to end. On those nine, the shortest walk in the longer direction, set against the route’s long side, is 34 over 20, 1.70, northbound on Emerald Route 101; 90 over 60, 1.50, on Crystal Route 29; 132 over 90, 1.47, on Crystal Route 32; 58 over 40, 1.45, on FireRed Route 1; 52 over 36, 1.44, on Red Route 1; 74 over 54, 1.37, on Crystal Route 30; 62 over 50, 1.24, on Emerald Route 102; 84 over 70, 1.20, on Red Route 3; and 97 over 84, 1.15, on FireRed Route 3.5617 The walk home is straighter, 0.95 to 1.42 times the long side: 19 over 20 on Emerald Route 101, 57 over 54 on Crystal Route 30, 43 over 40 on FireRed Route 1, 55 over 50 on Emerald Route 102, 40 over 36 on Red Route 1, 94 over 84 on FireRed Route 3, 82 over 70 on Red Route 3, 71 over 60 on Crystal Route 29, and 128 over 90 on Crystal Route 32, whose one-sided walls send the walk the long way round in both directions.5617 A ratio under 1 is not a shortcut through space: a walk from a seam cell on the first row to one on the last row of a 20-cell map takes 19 steps, so a dead-straight route scores 0.95.17 On my reading the outward figure is the number to size a route by: its winding walk, not its bounding box.

Grass thins as the journey goes on. Tall grass covers 3.7% to 22.8% of a route’s map. The four first routes, Red 1, Crystal 29, Emerald 101 and FireRed 1, are the grassiest of their games’ four at 14.4%, 14.8%, 22.8% and 18.5%; the second routes run 4.4% to 14.3% and the third and fourth 3.7% to 8.9%.56 Counted over the ground you can stand on instead, the shares are larger and the trend holds only on average: the first routes are 18.8% to 38.4% tall grass and the later twelve 8.2% to 29.2%, and Red Route 3 (22.6%) is grassier underfoot than Red Route 1 (18.8%). On Emerald Route 101, 91 of the 237 walkable cells are tall grass, 38.4%.5617

No first route has a trainer. Red 1, FireRed 1, Emerald 101 and Crystal 29 have none; trainers start on the second or third route, with 4 on Emerald Route 102, 3 on Crystal Route 30 and 8 on Route 3 in Red and FireRed.56 Their sight ranges on these routes run from 0 to 7 cells; Emerald Route 103’s nine trainers see 1 to 5 cells and Route 104’s eight see 0 to 7.6

An encounter zone rolls about one step in nine, after a short grace. Emerald never tests the first four steps after the player enters a map, by a seam or a door, or after a battle: CheckStandardWildEncounter counts those steps off while sWildEncounterImmunitySteps < 4 and restarts the count after every encounter, and every map load and battle start restarts it too. After that, each step onto an encounter cell is tested: a 40% chance to skip the test when the step moves onto a different behavior, then Random() % 2880 < rate × 16. Routes 101 to 104 all use rate 20, so the unmodified roll is 320 in 2,880, 11.1% a step on foot; a bicycle, a flute, a Cleanse Tag or some lead abilities scale it first.31 FireRed adds a floor and a ramp: after an encounter, and on entering a map, a cooldown of 8 − rate/10 encounter-cell steps (6 for Routes 1 to 4’s rate of 21), on each of which a 5% roll lets that one step try for an encounter without ending the cooldown; then the 60% roll on a new behavior; then rate × 16 out of 1,600, 21%, plus a buff that grows by the rate after every failed roll (encounterRateBuff).32 I read the grace, the floor and the ramp as ways to keep both droughts and floods short. Kiradex will have no wild battles, so the number matters here only as a rhythm: past the first few steps, a first route offers something to notice about once every nine steps of grass.

How much of a world is road

Game Route maps Route cells Town maps Town cells Route to town
Red 25 31,500 11 11,880 2.65
Crystal (Johto and Kanto) 54 49,880 23 25,380 1.97
Emerald (land routes) 41 87,787 16 23,700 3.70
FireRed (with Sevii) 57 98,451 19 25,470 3.87

Roads are two to four times the area of towns.33 Emerald’s 11 ocean routes would add another 45,600 cells.33 The ratio depends on how a map is classified, and each game classifies differently: Red by map id and name, Crystal by environment (its ROUTE environment includes, for example, the Ruins of Alph outside), Emerald and FireRed by map_type, where FireRed’s routes include the Sevii Islands and Emerald’s exclude the ocean.33 On Emerald’s map screen the same world reads 129 route squares to 22 town squares, 5.9 to 1, because a town takes one or two squares however large it is: ten of its 16 towns and cities take one, and six take two.341117

Route 1, three ways

Red, FireRed and Crystal draw the same idea at three resolutions, and Route 1 is the cleanest comparison. Red’s is 10 by 18 blocks, 20 by 36 cells, four Game Boy screens tall, with 42 ledge cells in 10 south-facing runs between fence posts and tree lines and 104 cells of grass.5 To check the Gen 1 cell model I rendered that one map from its blockset at twice size with a 16-pixel grid; it shows a 3-cell strip of open ground outside the western tree line that touches both seams and cannot be reached from either town’s doors, which is why the searches seed their crossings from the neighbors’ doors.5 The Gen 1 model reads one 8-by-8 tile per cell, the lower-left one, and it was checked by eye on that render only; tile-pair collisions such as the water-to-land pairs are not modeled.29

FireRed’s Route 1 is 24 by 40 cells, still four screens tall on the larger screen, with 61 ledge cells and 178 grass cells, 18.5% of the map: the remake kept the length in screens, grew the map by 4 cells each way, and added ledge.6 Pallet’s front door to Viridian’s Center is 94 cells, 25 seconds, and the reverse is 76.7 Crystal’s opening route, Route 29, is 60 by 18 cells, six Game Boy screens wide, 14.8% grass, with no trainers; the walk across it from New Bark’s side to Cherrygrove’s is 90 cells and the walk back 71.5

2. Door to door, and the way home

A route’s own length is only part of a trip. What a player feels is the leg: out of one building, through a town, across the route and the next town, into the next building. measure_travel.py searches that whole path, over (map, cell) pairs, through seams, warps and ledges, from the cell below the first door to the last door, counting the step up into it.7

Game From To Cells Walking Running Maps crossed
Emerald Littleroot, player’s house Oldale Center 58 15.5 s 7.8 s town, route, town
Emerald Oldale Center Petalburg Center 87 23.3 s 11.7 s town, route, city
Emerald Petalburg Center Rustboro Center 250 67.0 s 33.5 s city, route, forest, route, city
FireRed Pallet, player’s house Viridian Center 94 25.2 s 12.6 s town, route, city
FireRed Viridian Center Pewter Center 267 (156 after Cut) 71.5 s (41.8 s) 35.8 s through the forest’s two gatehouses
FireRed Pewter Center Route 4 Center 150 40.2 s 20.1 s city, route, route
FireRed Route 4 Center Cerulean Center 314 84.1 s 42.3 s through three cave floors, one of them twice

Seconds at a walk are cells times 16 frames over 59.7275 hertz. Running is a second search for the fewest frames, 8 a cell, with each ledge hop still 32 frames, because the hop is the same 32-frame jump at any gait; of the seven legs above, only the cave leg hops a ledge, once, which makes it 2,528 frames rather than 2,512. The “after Cut” figure is the same search with Route 2’s five Cut trees removed, which opens the east path through ROUTE2_EAST_BUILDING. Fades and battles are not counted.7 Two simplifications in the search matter most on the cave leg: Gen 3 elevation is reduced to two cases, equal heights or either side at 0 or 15, and a warp fires when it is stepped into rather than when it is arrived on, so the 314 cells through the cave, whose path runs 1F, B1F, B2F and B1F again, are the least certain number in the table.29

Horizontal bars of seven measured door-to-door legs in Pokémon Emerald and FireRed, out and back, in seconds at a walk with cell counts, with a return bar for the five legs measured both ways; the two first legs are 15.5 and 25.2 seconds out and 11.3 and 20.4 back; below them, three range bars for the Kiradex brief's targets at four tiles a second.

Door to door, out, and back where the return was measured, with the brief’s targets beside the canon; drawn by figures/make_figures.py from travel.json.

A first leg is 15 to 25 seconds of walking. The house door to the next town’s Center is 58 cells, 15.5 seconds, in Emerald and 94 cells, 25.2 seconds, in FireRed.7 The legs that reach a minute (Emerald’s 250 cells, FireRed’s 267 and 314) pass through a forest or a cave; on my reading they are dungeons, not roads, and a dungeon is its own kind of place.

The way back is shorter. Oldale’s Center to the player’s house in Littleroot is 42 cells against 58 out; Viridian to Pallet 76 against 94; Petalburg to Oldale 81 against 87; Rustboro to Petalburg 196 against 250; Pewter to Viridian 254 against 267.7

An HM is a shortcut through a gate you already walked past. With Route 2’s Cut trees removed, Viridian to Pewter is 156 cells instead of 267, and the path goes through Route 2’s east building instead of the forest.7

Hoenn’s first three legs

Emerald opens with three different answers to the question of what lies between towns, and the measurements make the design legible.

Route 101 is a corridor with a front door at each end. It is 20 by 20 cells, two screens tall, 22.8% tall grass, 91 of the 237 cells you can stand on; three south-facing ledge runs of four cells cross it. Walking north from Littleroot takes 34 cells and crosses at least 10 grass cells; walking south from Oldale takes 19 and can avoid the grass entirely by hopping the ledges. From the player’s front door to Oldale’s Center is 58 cells, 15.5 seconds at a walk.6187

Route 102 is wider and has the first trainers. It is 50 by 20 cells, 3.3 screens wide, 14.3% grass, with 4 trainers whose sight is 2 or 3 cells, a pond of 26 water cells and 17 ledge cells. Petalburg joins it at an offset of −10, so the route’s 20 rows face Petalburg’s rows 10 to 29. Center to Center, Oldale to Petalburg is 87 cells, 23.3 seconds, and the walk back 81.67

Route 104 is a route in two halves. It is 40 by 80 cells, eight screens tall, a quarter of it water, and no walk joins its three seams inside the map: the southern half reaches Petalburg Woods’ south entrance, 51 cells from the Petalburg seam, and the northern half its north exit, 60 cells from the Rustboro seam to the nearer of the exit’s two doorway cells (61 to the other). Petalburg’s Center to Rustboro’s is 250 cells across five maps (city, route, woods, route, city), 67 seconds at a walk, and 196 on the way back.67

What changes across the three is the denominator. The first route is a walk of under 20 seconds with no trainers and a grass-free way home; the third is a minute’s walk through a dungeon. On my reading the game spends its distance only after the player has learned to walk.

Ledges point home

Dumbbell chart of nine early routes showing the shortest walk out, away from the earlier town, and the walk home, in cells: Red Route 1 52 and 40, FireRed Route 1 58 and 43, Emerald Route 101 34 and 19, Emerald Route 102 62 and 55, Crystal Route 29 90 and 71, Crystal Route 30 74 and 57, Red Route 3 84 and 82, FireRed Route 3 97 and 94, Crystal Route 32 132 and 128; below, paired bars of the fewest tall-grass cells each way on four measured routes.

Out and home on every measured route whose two ends meet on foot, and the fewest grass cells each way; drawn by figures/make_figures.py from the route scripts’ outputs and grass_paths.txt.

On every measured route whose two ends meet on foot, all nine of them with ledges, the walk toward the earlier town is shorter. Red Route 1 is 40 cells home against 52 out, 23% shorter; FireRed Route 1 43 against 58, 26%; Emerald Route 101 19 against 34, 44%; Emerald Route 102 55 against 62, 11%; Crystal Route 29 71 against 90, 21%; Crystal Route 30 57 against 74, 23%; Red Route 3 82 against 84, FireRed Route 3 94 against 97 and Crystal Route 32 128 against 132, 2% to 3% each. Route 32’s 4 cells come from one sideways hop off a corner ledge, the walk home’s only hop.5617 The ledges on the first routes all face the same way: Red Route 1’s 42 ledge cells in 10 runs, FireRed Route 1’s 61 in 10 runs and Emerald Route 101’s 13 (three runs of four and one corner cell) all face south, the corner south-east, which on each of those maps is the way back to the starting town.56

The ledges also take the grass out of the way home. A second search, which minimizes tall-grass cells crossed rather than steps, finds that northbound on Red Route 1 a walker must cross at least 15 grass cells and southbound only 4, all of them in the gateway beside Pallet; FireRed Route 1 is 19 against 5; Emerald Route 101 10 against 0; Emerald Route 102 4 out against 0 home.18 Bulbapedia’s walkthrough of Kanto Route 1 says the same in prose: heading south, trainers “can either hop down ledges to completely avoid any contact with wild Pokémon” or travel through “the grass patches, the required path for northbound travel.”35 That is one wiki page used once, as a cross-check on the search, and the search agrees with it except for the gateway beside Pallet: it is two cells wide and four rows of grass deep, so every southbound walk in the cell model crosses 4 grass cells there, one a row. The ledges take a walker around all the other grass on the route, not quite all of it.18

The Gen 2 numbers need one caveat each. Crystal’s collision is four bytes per 32-pixel block, one per quadrant, and the scripts assume they run in row-major order (top-left, top-right, bottom-left, bottom-right), because the tilecoll macro does not name the order.29 A Gen 2 COLL_HOP_* byte marks the lip the player stands on rather than the cell beyond it, which probe_gen2_ledges.py settled by finding a WALL cell below every one of the 21 HOP_DOWN cells on Route 30; the lip reading was probed on Routes 29 and 30 only.529 Crystal also has one-sided walls. A collision byte from COLL_RIGHT_WALL to COLL_UP_LEFT_WALL is land, but GetMovementPermissions refuses a step out of such a tile through its walled side, and a step into one through that side; on Route 32, the only one of the four with any (41 cells, all UP_WALL), they lengthen the shortest walk from 110 cells each way, which a search that ignores them finds, to 132 out and 128 home. Its corner ledges, HOP_DOWN_RIGHT and HOP_DOWN_LEFT, hop down or sideways, whichever way the player faces, once the plain step is refused, and the walk home takes one of them sideways. Red has no one-sided walls: its only other movement rule, the tile-pair collisions, works both ways and is listed only for the cave and forest tilesets, which none of these maps use.5 And the search counts a ledge as two cells of movement, which matches the 32-frame jump in Gen 3 and is assumed for Gens 1 and 2.293

What the data show is an outcome, not an intent: I found no developer statement that ledges were placed to shorten the way home, only that on every route measured they do.29 The rule I take from it is that a ledge is a one-way shortcut back, never a wall forward.

The elevation question

This finding sits awkwardly against the previous post. The structures dossier behind Pixel-Art Structures refused ledges outright, “No ledges to jump, no climbing, no isometric,” and that post lists a one-way ledge among the things its build does not do.3637 This dossier measures ledges as the canon’s homeward shortcut. The two are not in conflict about the facts; they disagree about whether a collecting town needs height to get the effect. The decision belongs to the next post in the program, on elevation, ledges and bridges, which is not published yet. Until it is decided there, the brief in section 7 defers ledges to the elevation post and gets its shorter way home from a hedge gate instead: a gate on the Meadow Walk that opens only from the lake side, the same one-way shortcut back with no height in it.26

3. Seams, gates and the map screen

A Pokémon overworld is not one big map. It is many small ones, each with its own size, tiles and music, joined edge to edge so that you walk from one into the next without a cut. How the join works decides almost everything else in this section: where a building has to stand in the road, why the remakes have fewer of them, and what the map screen can know.

Gen 1 and Gen 2: a strip copied into a margin

A Red connection is one line in a map’s header naming a direction, the neighbor and an offset in blocks; Route 1’s is connection north, ViridianCity, VIRIDIAN_CITY, -5, and the macro precomputes which strip of the neighbor’s blocks is copied into the current map’s buffer.38 The buffer, wOverworldMap, holds the map with a margin of MAP_BORDER EQU 3 blocks, 6 cells, on every side; the connection fills that margin with the neighbor’s nearest 3 rows or columns of blocks, and CheckMapConnections swaps maps when the player’s coordinate passes −1 or the map’s width or height.39

Because the strip is copied as block numbers and drawn with whatever blockset is loaded, two maps can only meet at a seam if they share a tileset, and Red’s data keeps to that: of its 78 connection lines, 76 join maps with the same tileset. The two exceptions are Route 22 and Route 23, OVERWORLD against PLATEAU, and the header files mark both lines “; unnecessary”.840 Crystal has 142 connection lines; 138 join the same tileset (the exceptions are Goldenrod and Route 35, and Route 32 and Route 33, Johto against Johto Modern), and 92 stay within one map group.841

Gen 3: seven cells of the neighbor (eight on the east), and the art at the crossing

A Gen 3 connection is an entry of map, offset and direction in the map’s map.json. Emerald has 134 up, down, left and right entries plus 14 dive and emerge entries, and every one of the 134 has a matching reverse entry with the offset negated.8 Porymap, the map editor the decompilation community uses, describes the feature in three sentences: “Maps can be connected together so that the player can seamlessly walk between them”; “A connection has a direction, offset, and destination map”; and “Connections are one-way, which means that you must keep the two connections in sync between the two maps.”42

The engine copies the current map into a buffer with MAP_OFFSET 7 cells of margin on each side (8 on the east, because the buffer is the map’s width plus MAP_OFFSET_W, 2 × 7 + 1), and the header gives the reason in a comment: “the player has 7 metatiles of view horizontally in either direction.” FillSouthConnection and its siblings copy 7 rows or columns of the neighbor into that margin (8 columns on the east) at the connection’s offset, spanning only the neighbor’s own width (FillNorthConnection starts at the offset plus MAP_OFFSET and copies the neighbor’s width where it fits), and the whole buffer may hold at most MAX_MAP_DATA_SIZE 10240 cells.9 Where no connection exists, the margin is the layout’s 2-by-2 border pattern, ORed with MAPGRID_IMPASSABLE so that it can never be walked (GetBorderBlockAt).9

Schematic of a Gen 3 map buffer for a 20-by-20-cell route with a 20-cell-wide neighbor joined to its north at offset 0: the route in the middle, a margin of 7 cells on the west, north and south and 8 on the east; 7 rows of the neighbor fill the north margin over the route's 20 columns only, the corners and the other margins hold the impassable border pattern, and the 15-by-10-cell screen straddles the north edge.

What the buffer holds at a seam, schematic: one square per cell, sized from MAP_OFFSET, FillNorthConnection and Route 101’s 20-by-20 layout with Oldale’s 20-wide layout to the north at offset 0; drawn by figures/make_figures.py, no game art.

The neighbor’s strip is drawn with the current map’s tilesets (DrawMetatileAt takes the primary and secondary sets of the map you are on) until the player crosses. Crossing calls LoadMapFromCameraTransition, which runs the new map’s on-transition script, loads only its secondary tileset and palette, changes the music and the weather, and shows the map-name popup, with no fade.10 That is why no connected pair differs in primary tileset: 0 of Emerald’s 134 and 0 of FireRed’s 120. 38 of Emerald’s and 34 of FireRed’s join different secondary tilesets, and in 24 of each the neighbor’s strip in the margin (7 cells, 8 on the east, cut where it would leave the buffer, as the engine cuts it) uses primary metatiles only, so it draws correctly from either side.8

Offsets are common. 36 of Emerald’s 134 connections and 68 of FireRed’s 120 are non-zero; FireRed’s Route 1 sits 12 cells into Viridian’s 48-cell width.8 Reciprocity is not quite universal in FireRed: 112 of its 120 entries are reciprocal, and the walled city accounts for 6 of the 8 others. Saffron City connects one way to Routes 5 to 8, while those routes connect not to Saffron but to a separate SAFFRON_CITY_CONNECTION map; the last two are prototype Sevii maps.8 I read the Saffron arrangement as a drawing trick: the connection exists to draw the city wall beyond the route’s edge, and the way in is through four gatehouses, whose guards in Red turn the player back until given a drink.819 When a place must look continuous and still be gated, Gen 3 draws the neighbor in the margin and puts the door in a building.

Crossing a seam into a map with show_map_name set slides the place’s name in. The popup task waits 31 frames, slides in 40 pixels at 2 pixels a frame (20 frames), holds until its timer passes 120 (121 frames) and slides out (20 frames): about 190 frames, 3.2 seconds.21 I counted the task’s states by their thresholds, so each state may be a frame longer or shorter than I have it.29

Gatehouses: where the art changes

Red has 27 maps on the GATE or FOREST_GATE tileset: two-floor gates on Routes 11, 12, 15, 16 and 18 (10 maps), single gates on Routes 2, 5, 6, 7 and 8, the Route 22 gate, the Safari Zone gate and its 4 rest houses, 4 Underground Path entrances, and the 2 Viridian Forest gates.8 Every Red gate that joins two different places joins two tilesets: OVERWORLD to FOREST (Viridian Forest, the Safari Zone), to UNDERGROUND (the four path entrances) or to PLATEAU (Route 22 to Route 23), joins that Red’s connections almost never make.8

Route 2 is the clearest case. It is 20 by 72 cells in Red and 24 by 80 in FireRed and cannot be walked end to end: its southern and northern halves meet only through Viridian Forest, which in Red is drawn from the FOREST tileset rather than OVERWORLD and is entered through two gatehouses.58 In FireRed, Viridian’s Center to Pewter’s is 267 cells through the south gate, the forest and the north gate.7 Three readings follow, and they are readings of the data, not statements from the developers.

  1. The gate is where the art changes. A Gen 1 seam draws the neighbor’s blocks with the current blockset, so two maps can only meet at a seam if they share a tileset, which Red keeps to in 76 of its 78 connections. A forest drawn from a forest tileset therefore needs a door, and a gatehouse is the door.388
  2. The gate is where a rule can live. The four Saffron gates turn the player back until a drink is given (TEXT_ROUTE5GATE_GUARD_GEE_IM_THIRSTY, BIT_GAVE_SAFFRON_GUARDS_DRINK); the Route 22 gate checks BIT_BOULDERBADGE.19 And three gates reward collecting: Oak’s aides give an item when the count of species owned (CountSetBits over wPokedexOwned) reaches 10 at the Route 2 gate, 30 at the Route 11 gate’s second floor, and 50 at the Route 15 gate’s second floor.20
  3. The gate is a pause with people in it. Route 2’s gate holds Oak’s aide and a youngster; the walk resumes after a fade, in a new place.43

The remakes split by engine. Crystal has 25 maps of environment GATE, of which 19 join maps in different map groups and 7 join different tilesets.8 FireRed keeps Kanto’s gates: 8 indoor maps lead to two different outdoor maps (the Viridian Forest pair, the four Saffron entrances, Route 22’s north entrance and the Safari entrance), and 13 more have doors on two separate sides of one outdoor map, among them the five two-floor route gates and Route 2’s east building.8 Hoenn nearly drops them. In Emerald only 2 indoor maps lead to two different outdoor maps (Mt. Pyre’s ground floor and the Safari Zone entrance) and 5 have doors on two sides of one, the two Cycling Road stations among them; routes meet towns at open seams.8 Counted as buildings, Emerald has 4 gates (the two Cycling Road stations, the Safari Zone entrance and the Battle Frontier gate) against FireRed’s 14 and Red’s 27 gate-tileset maps.8 My reading, and it is a reading: Hoenn could drop the gates because its engine loads a new secondary tileset at the moment of crossing, so a route can meet a town drawn in different art without a building between them.10

The map screen and Fly

Emerald’s region map is a grid of 28 by 15 squares (MAP_WIDTH 28, MAP_HEIGHT 15), 420 in all; 158 of them, 37.6%, belong to a place, divided among 54 sections: 34 routes, 16 towns and cities and 4 others. Routes cover 129 squares and towns 22.11 Of the 213 entries in region_map_sections.json, 95 carry a rectangle on the grid; 49 of those are a single square, the largest is 4 by 3 (Route 124 and its underwater twin), Slateport is 1 by 2 and Mauville 2 by 1.11 A map screen, on this evidence, is a coarse grid of named rectangles, and most places are one square.

Fly is where the screen meets the walking. Emerald’s Fly needs the sixth badge (FIELD_MOVE_FLY against FLAG_BADGE06_GET in the badge table) and an outdoor map type (Overworld_MapTypeAllowsTeleportAndFly: route, town, city or ocean route). On the map, a town is MAPSECTYPE_CITY_CANFLY only if its FLAG_VISITED_* flag is set, and each of the 16 towns and cities sets its own flag in its on-transition script; Oldale’s says setflag FLAG_VISITED_OLDALE_TOWN.13

The other games agree on the shape. FireRed’s map is 22 by 15 squares per page, four pages (Kanto and three Sevii sets) each in two layers, the overworld and the dungeons; Kanto’s overworld layer fills 90 squares with 38 sections, and Fly needs the third badge. A FireRed place counts as visited when its FLAG_WORLD_MAP_* flag is set, which each town’s on-transition script does on entry (setworldmapflag FLAG_WORLD_MAP_CELADON_CITY), and Fly accepts only a visited square.23 Crystal’s map places 95 landmarks by pixel position and offers 24 fly points, 12 in Johto and 12 in Kanto; a town’s fly point is set by a callback when you enter it (VioletCityFlypointCallback: setflag ENGINE_FLYPOINT_VIOLET), and Fly checks ENGINE_STORMBADGE.24 Red’s town map lists 37 outdoor entries on a 4-bit grid (one marked unused) and 60 indoor entries with positions of their own; entering any of its 11 city maps sets that city’s bit in wTownVisitedFlag, with the source comment “mark town as visited (for flying)”, the fly list skips unvisited towns, and Fly needs the Thunder Badge and an outdoor map.22

None of the four starts the player with a map to carry; each hands one over during play. Red’s and FireRed’s Town Map is an item from the rival’s sister in Pallet (in Red, offered once the player has the Pokédex); Crystal’s Map Card is a gift in Cherrygrove, the first town past home; Emerald’s PokéNav comes from the Devon building in Rustboro, the third town past home.442345127 Wall maps open the same screen sooner: Emerald hangs one upstairs in the player’s house and on the ground floor of every Pokémon Center, FireRed in its Centers, Viridian’s school and some houses, and Red’s HOUSE tileset, used by the rival’s house in Pallet, has a wall-map tile.122344

Put together, the rule is consistent across four games and three generations. Once the player has the map, it draws every place in the region, visited or not; the exceptions are late places held back by the story or an event, FireRed’s Sevii pages until scripts in One Island’s Pokémon Center set their flags, and on those pages Navel Rock and Birth Island, painted over until the player has been there; Emerald’s Battle Frontier and Southern Island until their landmark flags; and Crystal’s Kanto map until the player stands in Kanto.44451223 Fast travel lists only places you have walked into, recorded by a flag set on entry, available only outdoors, and only after a mid-game badge: the third in Red and FireRed, the sixth in Emerald.13232422

Pokémon is one answer to the land between towns. Three other games answer differently, and each difference is a choice Kiradex has to make. The numbers in this section come from the games’ community wikis and, for Link’s Awakening, from a disassembly; I did not check them against game code, except where a note says so.29

Stardew Valley: a hub with spokes, opened by the calendar

Stardew fades at every edge. In its wiki’s words: “When you reach the edge of an area or enter a building, and the screen fades to black during the transition, you’re moving between maps.” A warp is a map property whose value the wiki gives as Warp [ <int fromX> <int fromY> <string toArea> <int toX> <int toY> ]+, with the example “6 20 Mountain 76 9”.46

The valley is a small graph around one hub. Pelican Town connects to the Bus Stop and the Farm to the northwest, Cindersap Forest to the southwest, the Beach to the south and the Mountain to the north.47 The Bus Stop “connects the Farm to the west with Pelican Town to the east” and gives onto the lower Backwoods by the road west.48 Cindersap Forest “has exits to the north into the Farm, to the east into Pelican Town, to the south into The Sewers, and to the northwest into the Secret Woods.”49 The Backwoods “consists of two disconnected sections”, an upper path joining the Farm to the Mountain and a lower section reached from the Bus Stop road.50 The locations box on these pages lists 26 places, from the Backwoods to the Witch’s Swamp, by my count.51

The spokes open by date and by deed. The Mountain starts with “only two exits: to the south leading to Pelican Town, and to the west leading to the Backwoods”; the Mines open on Spring 5, the Railroad after an earthquake on Summer 3, and the Quarry bridge for the Crafts Room bundles or 25,000g.52 The Desert needs the bus repaired, by the Vault bundles or 40,000g; the Secret Woods need a log cleared by a steel axe or better; the Beach’s tide pools need a bridge of 300 wood.53 The wiki lists the player’s base speed as 2 walking, 5 running and 6.6 riding a horse, without units, and I did not open the game’s code to find them.54

My reading: Pokémon gates an area by an ability the player carries, a badge or an HM. Stardew gates it by something the community did, a bundle, a bridge, or an earthquake on a date. The second is the kind a shared, collecting town can use without making anyone feel locked out by their level.

Animal Crossing: the acre grid and the train

The GameCube Animal Crossing builds its town from acres. “Acres are grid elements measuring 16x16 spaces”; the town is “five acres across by six down”, with the train station “always located in Acre A-3”, and the map labels the columns 1 to 5 and the rows A to F.55 That is 80 by 96 spaces in all.17 Later games changed the grid: Wild World is 4 by 4 acres, City Folk 5 by 5, New Leaf 5 by 4, New Horizons 7 by 6, 42 acres.55

The acre is also a spawn rule. “Every time the player moves into an acre (with the exception of a player exiting their house upon loading the game), one fish and one bug spawn at the locations programmed within the acre data,” and they disappear once the player is six squares away from that acre.55 The town map arrives early, from Tom Nook during the part-time job; it “is organized in a grid, with each square representing an acre,” and shows the sea, the rivers, the buildings and the homes, not trees, items or villagers.56

The train is the GameCube game’s only way to another town, by memory card, and “The train ride takes a few minutes”; the station “is located at the top of the player’s town,” and a new game begins with the player arriving there.57

My reading: acres make a town legible, a map of named squares, and give a spawn rule that rewards moving around without per-step dice. The train makes the trip between worlds a scene rather than a seam.

Link’s Awakening DX takes the opposite approach to Pokémon’s continuous scroll. In the zladx disassembly’s documentation, play “takes place in non-scrollable screen-wide rooms,” and “On the Overworld, rooms are stored as they are laid out during the game, on a 16x16 grid of rooms.”58 The overworld map is 512 bytes of two-byte room pointers, 256 rooms, and a room’s tile overlay is “a straight forward array of 10x8 tile numbers”.59 “Overworld rooms are grouped in 2x2 sections (i.e. 4 rooms). Each section has a tileset ID,” and the section’s 32 tiles are swapped during the transition into a room that needs them.58 Every overworld room has a status byte in wOverworldRoomStatus, 256 bytes, with OW_ROOM_STATUS_VISITED EQU $80 beside bits for doors, changes and owls; I read the bit from the disassembly’s constants and did not trace whether the map screen draws only the rooms that have it.25

My reading: Pokémon scrolls a continuous world and names it in sections; Link’s Awakening cuts the world into equal screens and records which ones you have seen. On a phone whose view differs by device, 10.3 tiles across on an iPhone 18 Pro Max in portrait and 29.7 on an open iPhone Duo, only the scrolling model works without letterboxing every room, which is why the brief uses it.60

5. The craft, as rules with numbers

These are the rules the measurements support, each with where it came from. Where a rule turns a measured fact into a recommendation, the recommendation is mine and the rule says so by its verb.

Element Rule Source
Pace A walk cell costs 16 frames, about 0.27 seconds; Kiradex’s tile costs 0.25. Size every trip in seconds at the game’s own walk. Red, Crystal and Emerald step code; GBATEK; PlazaRig.swift
Route length 2 to 10 screens along the axis of travel; the first route of a game 2 to 6. sixteen routes measured
Winding The longer walk across is 1.15 to 1.70 times the route’s long side, the walk home 0.95 to 1.42. Size a route by its path, not its bounding box. shortest walks over long sides on the nine routes whose ends meet on foot
First leg 15 to 25 seconds from a door to the next town’s main door. A leg of a minute is a dungeon, not a road. Emerald 58 cells, FireRed 94; 250, 267 and 314 through a forest or a cave
Proportion Road is 2 to 4 times town by area; on the map screen 5.9 to 1, because a town is one or two squares. Crystal 1.97, Red 2.65, Emerald 3.70, FireRed 3.87; Emerald’s map
Density Encounter ground is 14% to 23% of a first route’s map and thins to 4% to 9% by the third and fourth routes; over walkable ground a first route is 19% to 38%. A first route has no trainers. the route table; grass over walkable cells
Rhythm Something to notice about one step in nine in encounter ground, after a few steps’ grace on arrival; keep droughts and floods short with a floor and a ramp. Emerald’s four-step immunity, then rate 20, an unmodified 11.1%; FireRed’s cooldown and buff
The way home Shorter than the way out, by 2% to 44% on all nine routes with ledges whose ends meet on foot, with 0 to 5 grass cells against 4 to 19. A ledge is a one-way shortcut back, never a wall forward. nine routes; the fewest-grass search
Seams Let two areas meet at an open seam only where both draw the edge from the same ground set; put a building with two doors where the art changes. Red 76 of 78, Crystal 138 of 142, Gen 3 0 of 134 and 0 of 120 with different primary sets; every Red gate between two places
Neighbor strip Draw at least half a view of the neighbor beyond the edge. Gen 3’s 7 cells (8 on the east) for a 15-cell screen; Gen 1’s 6 cells for 10
Connections Offsets are normal; every connection has a reverse with the negated offset, and a one-sided one is a deliberate drawing trick. Emerald 36 of 134 offset, 134 of 134 reciprocal; FireRed’s Saffron
Name card Name the place on entry for about three seconds. Emerald’s popup, about 190 frames
Gates A gate is where a rule and a reward live: a milestone check, a guard, a gift at a count. Red’s badge check, thirsty guard, and gifts at 10, 30 and 50 species owned
Map screen A coarse grid of named rectangles; most places one square, the largest a few. Emerald 28 by 15, 49 of 95 rectangles a single square, largest 4 by 3; Animal Crossing’s 5-by-6 acres
Fast travel Once the player has the map, it shows every place, visited or not, but a few that story or event flags hold back; fast travel shows only where you have been, set by a flag on entry, from outdoors only. the Town Map, Map Card, PokéNav and wall maps; Red’s wTownVisitedFlag, Crystal’s fly points, Emerald’s FLAG_VISITED_*, FireRed’s FLAG_WORLD_MAP_*; a visited record not traced to its map screen: Link’s Awakening’s OW_ROOM_STATUS_VISITED bit
Unlocks Areas open by deed and date as well as by ability. Stardew’s Mines, Railroad, Quarry, Desert and Secret Woods; Cut’s 267 cells to 156
Transitions Seam inside one outdoor world; fade through doors and at the edge of the world. Pokémon’s seam, Stardew’s fade, Link’s Awakening’s push
Orientation Run a route along the device’s long axis; a route that fits whole in one view has nothing left to reveal. the October 3 tile counts; Emerald Route 101’s 20 by 20 against an open Duo’s 29.7 by 20.9

Sources for the table: the step code and frame timing in section 1;12315 Kiradex’s walk speed;4 the route, travel, grass and connection scripts;567188 the encounter code;3132 Emerald’s buffer, crossing and popup code;91021 the gate scripts;1920 the map screens, how the player gets them, and Fly;1112132345244422 Stardew Valley, Animal Crossing and Link’s Awakening;465253555825 the tile counts per device from the first post in this series.60

Three of those rules deserve a sentence more.

The seam rule is stated as a rule about art, not about engines. The Game Boy drew a neighbor’s strip with the current map’s blockset, so it could not show a neighbor in a different tileset at all; the Game Boy Advance draws the strip with the current map’s tilesets until you cross, which on my reading is why its seams keep to one primary set and mostly to primary metatiles.38108 I read both as limits of tile memory, which a phone drawing one atlas does not share. What survives is the visual reason: a path that changes material at a straight line across the screen reads as a seam whether or not the engine needed one. That is why the rule keeps its first half (meet openly where the ground continues) and its second (a building where the art changes) even when nothing forces it.

The fast-travel rule is the one most worth copying exactly. Every Pokémon game measured here hands over the map early in play, draws every place on it whether visited or not, save a few late places that story or event flags hold back, and gates only the shortcut; every one of them earns the shortcut by having walked somewhere, not by paying for it.44451213232224 For a collecting app whose XP comes only from cards scanned in the real world, the visited flag is the right currency, because it costs a walk and nothing else.27

The orientation rule comes from the phone, not the canon. A Pro Max in portrait sees 10.3 by 22.4 tiles at Kiradex’s scale and an open iPhone Duo 29.7 by 20.9, so a route that runs north and south shows 22 tiles of its length at once on the common phone, about 11 ahead of a collector the camera keeps centered, while one that runs east and west shows 30 at once, about 15 ahead, only on the open Duo.602717 Emerald Route 101, 20 by 20, would fit whole inside one open-Duo view, which means a route that short has nothing left to reveal there.617

6. The Apple way: views, seams, rooms and a map

The engine underneath Kiradex World is the one the first post set out: a RealityKit scene used as a 2D renderer, an orthographic camera at a whole number of device pixels per texel, the ground as one MeshDescriptor mesh drawn in one call, every material an UnlitMaterial with an opacity threshold, and RealityView’s motion blur and tone mapping switched off.60 The structures post added objects sorted by depth in a second mesh, warps as data, and floors swapped in place by giving the stage a new identity, .id(floor.name), so that SwiftUI tears down one RealityView and builds the next.37 Areas past the fence need three more things from that engine: a view of the neighbor across a seam, a way to change rooms on the server without a cut, and a map screen. None of it has been built yet, and nothing in this section has been measured on a phone; it is the plan the brief rests on, with each cost named and marked unmeasured.

What a phone sees

The tile counts come from the first post’s table, computed from Apple’s spec pages and the Xcode 27 simulator profiles at Kiradex’s integer scales.60

Device and orientation Pixels per texel Tiles visible (across by down) Half a view
iPhone 18 Pro Max, portrait 8 10.3 by 22.4 6 across, 12 down
iPhone Duo outer display, portrait 6 14.6 by 21.2 8 across, 11 down
iPhone Duo inner display, open 6 29.7 by 20.9 15 across, 11 down

The last column is half the view rounded up, the neighbor strip the seam rule asks for.17 Apple gives the iPhone Duo’s inner display as 1878 by 2670 pixels at 430 pixels per inch and the outer as 1398 by 2034 at 460.61 The inner display’s tile counts are not taken from those panel pixels: they come from the simulator’s logical framebuffer of 2007 by 2853 at scale 3.0 (2853 ÷ 96 is 29.7 and 2007 ÷ 96 is 20.9), which the first post explains is downsampled by about 0.936 to the glass, so on hardware the same number of tiles should fill the panel, at about 5.6 panel pixels a texel, if the compositor downsamples as the first post expects; that is unverified on hardware, and the first post’s first step is to log nativeScale on a device.6017 The Human Interface Guidelines ask that games “look good and behave well at various aspect ratios”, and the first post read that as an argument for showing more world rather than bars, which is what the plaza does.6260

Two things follow for the areas. With the camera following the collector, the view ahead is about half the view.27 A route that runs north and south is the one every phone shows well: 22 tiles of it at once on a Pro Max in portrait, about 11 ahead, and 21 at once on the open Duo, about 10 ahead. A route that runs east and west shows 30 tiles at once on the open Duo, about 15 ahead, and only 10 on a Pro Max in portrait, about 5 ahead, so it belongs where the destination is close.6017 That is why the brief’s long walk, the Meadow Walk, runs north and south, and why Binder Row, the area that runs most strongly east and west (44 by 14, more than three times as wide as it is tall), is a street of shop fronts you can see most of from wherever you stand on the open Duo. The Lakeside (36 by 20) and the Gallery Quarter (30 by 20) are wider than tall too, but in the brief they are places to stop in, a shore and a museum district, not walks to somewhere else.2617

A seam in RealityKit

The structures post’s floor swap is the wrong tool for a seam. Tearing down one RealityView and building the next needs a fade to hide it, and the app’s doors do not have one yet: today the place changes 220 milliseconds after the step onto a door, a floor change swaps the stage with no fade, and this series’ motion post proposes the veil that would cover both. A seam has no fade, by definition.376316 So the plan for a seam keeps one scene. When the collector comes within half a view of an edge that has a connection, the stage builds the neighbor’s ground as a second mesh, from the same kind of MeshDescriptor as the first, placed at the connection’s offset in world units, and adds the neighbor’s objects at their own depths. When the collector’s feet cross the edge, the stage re-bases: the neighbor becomes the current area, the old one becomes the strip behind, and the camera, which follows the player clamped to the map today, is clamped to the union while both are loaded.2726

Three engine facts make that cheap on paper. The ground is one mesh and one draw call per area, so a neighbor adds one draw call for its ground and one for its objects.6037 Every pixel is cut-out and writes depth, so a neighbor’s trees sort against the collector by the same depth rule as the current area’s, with no new sorting.37 And the forge already exports a whole area as letters, autotiled ground, objects and warps, so a neighbor is a second file of the same kind; the brief adds a connections list to it.1426 What none of that tells me is what the second mesh costs to build at the moment it is needed, or whether building it inside one frame causes a hitch; that is unmeasured. Check 6 in the brief therefore has two halves, and both cover the whole approach, from before the neighbor’s mesh is built to the end of the crossing: a per-frame timing log, which catches a main-thread stall, and an inspection of every captured frame, which catches a black frame. A sampled check would not do: one black frame among sixty a second need not disturb the callbacks’ timing, and a sample every 100 milliseconds sees one frame in six at 60 hertz.17 The timing half and the every-frame rule are my additions to the dossier’s check, which sampled brightness.

Autotiling is the one thing the GBA’s rule does not cover. Gen 3 kept its seams on shared ground because the neighbor’s strip was drawn with the current map’s tiles.108 Kiradex draws every area from one atlas palette, so that limit does not apply, but the blob autotiles at the edge of an area are computed from the area’s own letters; if the forge does not look across the seam, a path that crosses it ends in a rim on both sides. The brief therefore has the forge compute the edge masks across every connection.26

Rooms, presence and the reconnect

Kiradex’s plaza is a server room: rooms of up to about 40 players, sharded by region, on FastAPI and WebSockets.27 An area past the fence is naturally another room, which raises the problem a single-player handheld never had: the people across the seam. The plan is for the client to subscribe to the neighboring room’s walkers when it starts drawing that room’s strip, so the people on Binder Row are visible from the Square’s edge, and to switch its own room at the crossing, so the walker never stops.26 Doors and the tram get a fade, the veil the motion post’s brief adds to doors, and that fade covers the reconnect, as the structures dossier already proposed for interiors.1626 The first post’s fix for a black view applies to that fade: animating the opacity of the SwiftUI view that holds the RealityView left it unpainted, so the fade is a veil drawn over it.60

The server needs the same map the client draws. Today server/app/plaza.json carries the town’s letters so the server can validate a walk; the brief has each area’s copy carry its letters and its connections, so a walk that crosses a seam is validated on both sides of it.6026 What a room switch costs on a real network, and whether a subscription to a second room doubles the plaza’s message rate near a seam, is unmeasured.

The name card, the map and the tram in SwiftUI

The area’s name belongs in SwiftUI, not in the pixel layer. The first post found that a five-texel pixel font at Kiradex’s scales falls at 13.3 or 10 points, the second under the Human Interface Guidelines’ 11-point minimum, and moved dialogue text to SwiftUI at UI scale; a name card is the same kind of text.60 Its timing comes from Emerald: about three seconds on screen.21

The map screen is a SwiftUI view over a small model, a grid of named rectangles, the current area and the set of visited areas. On the open Duo it sits beside the world as a panel, the way the world plan puts the collector’s profile card beside the plaza (“The plaza on the open inner display is the best version of this: wide view, your profile card beside the world when you tap someone”); on a phone it is a sheet.27 The tram is a warp from the map: fade out, change rooms, fade in at the destination’s stop.

The visited set has to travel with the collector. The Human Interface Guidelines’ games page says “Let players pick up their game on any of their devices,” so people can “start back up exactly where they left off on a different device.”62 A tram stop opened on the phone should be open on the iPad, so the visited set lives with the collector’s profile on the server rather than in the app’s local storage.26 That extends the world plan’s section 3, which says “Our server holds only the public profile card and the economy”; I would add the visited set as one more field beside them, kept to a list of which of the five areas a collector has entered, with no location, no text and no time of visit, keyed like the rest by the Game Center player id; the privacy reading the plan asks for would have to cover it.2726

What it costs, and what is not measured

Nothing in this section has been timed. The unmeasured costs are: building a neighbor’s ground and object meshes at the moment the collector nears an edge; drawing two areas’ meshes while both are loaded; subscribing to a second room near a seam; and the room switch at a crossing. The first post’s capture rule decides how they will be measured: on the iPhone Duo simulator, RealityKit frames are faithful only when captured from inside the test bundle (XCUIScreen.screens[1]), not from the host.60 The brief’s check 6 uses exactly that capture for its view of the neighbor before the seam, and runs its every-frame inspection and its frame-timing log, read from CADisplayLink callbacks, on a device build rather than the simulator: on an open iPhone Duo once one is at hand, and until then on an iPhone 18 Pro Max, because no iPhone Duo is paired with my Mac as I write.64 No capture method has yet been shown to record every displayed frame; the check’s frame-count match, the recording’s frames against the timing log’s callbacks, decides whether one does.

7. The brief: what Kiradex builds and the checks it must pass

Author synthesis. What follows is my proposal, derived from sections 1 to 6 and fitted to the world plan in the Kiradex repository, its section 4 (“The game”) and section 7 (“Order of work”).2726 It names no place, creature or mark from any Pokémon game; where it borrows a mechanic it cites the rule in section 5, not the source game’s vocabulary. Every size is in 16-pixel tiles, and a walk’s length is its cost on the app’s own path search, a diagonal step counting √2 tiles (item 3).28 Every time is that length at the walk’s nominal 4 tiles a second, a figure for comparing with the canon, not a measured one; the motion post’s brief would walk 16 ticks a straight tile at 60 hertz, 3.75 tiles a second, and round a diagonal up to 23 ticks, under which each time here grows by a fifteenth on straight steps and by about a twelfth on diagonals.41617

Kiradex’s loop is real-world. XP comes only from cards scanned and registered: “XP comes only from the real world, which is the point of the app.”27 So walking is a cost, not content, and every area must give the walker something to do with their collection: show it, trade around it, earn a cosmetic for it, or be pointed back to the scanner. Nothing found or earned by walking is ever a card or XP, and nothing in the world is sold for money except through the shop the world plan already defines.27

1. Five areas: the Square and four beyond it

Area What it is Size (tiles) Joined to Role in the collecting loop
The Square (exists) The town: houses, hall, kiosk, fountain terrace, arrival court 40 by 30 the hub Arrive, flaunt the favorite card, enter rooms and the hall
Binder Row A shopping street: the card shop from the structures kit, the trade post, a wants board, later a row of six market stalls 44 by 14 the Square, east, open seam Spend coins on cosmetics; see what the town’s collectors ask to be shown; the exchange screen; the marketplace stalls when that phase comes
The Meadow Walk A park path through meadow and copses, with flower patches where finds appear, and a hedged lane home whose gate opens only from the lake side 24 by 60, long axis north and south the Square, north, open seam Finds (item 6); a walk with friends; the way to the lake
The Lakeside The far end of the walk: a shore, a pier, benches, a boathouse 36 by 20 the Meadow Walk, north, open seam The quiet place to sit and show a card at sunset; the weekly gathering spot
The Gallery Quarter A stone district: the museum and the gallery of collectors’ displays 30 by 20, plus an 8-by-6 arch house the Square, west, through the arch (two doors) Sets completed across the whole server fill the museum; the milestone keeper in the arch (item 7)

The total area beyond the Square is 616 plus 1,440 plus 720 plus 600, 3,376 tiles, 2.8 times the Square’s 1,200, inside the canon’s band of 1.97 to 3.87 (section 5, Proportion).1733 The Gallery Quarter sits behind a building because it is drawn in stone from a different ground set (section 5, Seams). The other three share the Square’s lawn and paving, so they join at open seams, three in all: Binder Row to the Square’s east edge, the Meadow Walk to its north edge, and the Lakeside to the Meadow Walk’s north edge.26 Binder Row’s wants board shows what the town’s own collectors ask to be shown, judged against the real cards by the code that already does it (Kiradex/World/Wants.swift); its stalls wait for the marketplace, which the world plan routes through eBay in a later phase.6527

Schematic of the brief's five areas on a 16-by-12 map screen at one square per 10 tiles: the Lakeside at the top, the Meadow Walk below it, the Square at the bottom center, Binder Row to the Square's east and the Gallery Quarter to its west through a dashed arch; a dot marks each area's tram stop, and a note gives 3,376 tiles beyond the Square, 2.8 times its 1,200.

The proposed areas, drawn to the map screen’s grid; schematic only, drawn by figures/make_figures.py, which asserts each rectangle is its area’s size over 10, rounded.

Checks: 4 (proportion) and 5 (orientation).

2. Distances and times

Trip Target (tiles) At 4 tiles a second Canon reference
Arrival court to the card shop’s door at most 60 at most 15 s section 5, First leg: 15 to 25 s
Arrival court to the Lakeside pier, outward 110 to 120 28 to 30 s Longer than a first leg (15 to 25 s), under the canon’s road legs of up to 40 s and its minute-long dungeons; Winding, 1.15 to 1.70 times the long side outward
Lakeside pier to the arrival court, homeward, through the hedge gate at most 0.8 times the outward walk at most 24 s The way home is shorter
Arrival court through the arch to the museum door at most 70 at most 18 s First leg
Any area to any visited area by tram one fade about 1 s plus the reconnect Fast travel; Transitions

The Meadow Walk’s 60-tile length winds to 78 to 90 tiles of path, a factor of 1.3 to 1.5 (section 5, Winding).26 A path alone cannot make the way home shorter: on a grid where every step can be walked both ways, the shortest walk from the arrival to the pier is the shortest walk back, and a straighter path would be taken going out as well. The saving needs something one-way. Here it is a hedge gate. A hedged lane 2 tiles wide runs straight down the Meadow Walk’s east side, in line with the pier, to the Square’s north edge between the hall and the house east of it, where the lawn between them leads down toward the arrival court. The gate at the lane’s lake end opens only from the lake side. Walking out, it stays shut and the path winds; walking home, it opens and the lane is straight. That is the canon’s one-way shortcut back (section 5, The way home) laid flat. I modeled the three areas on the shared eight-way graph of item 3, with the town as the forge draws it today and the lane and pier placed that way. I chose to wind it with four hedges across the meadow, one every 12 rows, each with a 2-tile gap. Diagonal steps cut every switchback short. Over every gap position, two evenly spaced hedges cannot wind the meadow 78 tiles on this graph: they reach at most 66.46 tiles from edge to edge. Three, evenly spaced, can, but only just: 6 of their 8,000 gap positions wind it 78 to 79.77 tiles, and 5 of those 6 also walk out inside the outward band of 110 to 120 tiles, at 114.05 to 119.02, with the way home 0.740 to 0.772 of the way out, under the 0.8 target. Four hedges wind it 78 to 90 tiles in 5,912 of their 160,000 positions, which leaves the forge room to lay the meadow out. That margin is my reason for four; the graph does not force it. On those four-hedge layouts the way home is 88.07 tiles against 108.74 to 133.75 out. The 0.8 target needs at least 110.09 out, and inside the outward band of 110 to 120 tiles all 4,111 layouts meet it, at 0.73 to 0.80. With the gate open both ways, the two walks come out equal.66 The eight-way walk is why the earlier model’s two hedges no longer suffice: it shortens the lane home only from 91 tiles to 88.07, because the lane is already straight, but it takes far more off a winding path out, so the gate saves less unless the meadow winds harder. The same model sets the band’s lower end. No layout in it, at any offset or pier position it tries, walks out in under 107.18 tiles, and the walk home is never under 88.07, so a walk out much under 110 tiles fails the 0.8 target.66 One-way drops from the meadow’s terraces would do the same the canon’s way, but the structures work refused ledges, so the drops are deferred to the elevation post, which decides them.3626

Check: 3 (distances).

3. Connections as data

Each area is a forge export like town.json: letters, autotiled ground, objects, warps and the arrival, plus connections: [{"dir": "north"|"south"|"east"|"west", "area": "<id>", "offset": <tiles>}], where the offset is the neighbor’s origin along the shared edge, Gen 3’s convention.148 Every connection has a reverse with the negated offset (section 5, Connections), with no exception: the canon’s one-sided connections are a drawing trick this brief does not need. The server’s copy of each area carries the letters and the connections, so a walk is validated across the seam.6026

One walking graph serves both sides. The app’s TileMap.path searches eight ways, a diagonal step costing √2 and allowed only when both tiles it passes between are walkable, so nobody cuts a wall’s corner; the server’s Plaza.path in server/app/rooms.py searches four ways, though its comment calls it “the same walk the app takes”.28 The brief makes the client’s search the contract: the server diff replaces Plaza.path with the same eight-way, √2, no-corner-cutting search, and both read the hedge gate (item 2) as a directed edge, entered from the lake side by a straight step only and never left toward the lake. Every distance in this brief is measured on that graph.

Checks: 1 (reciprocity), 2 (crossings) and 12 (server parity).

4. Open seams, no fade

Crossing an open seam has no fade (section 5, Transitions). The client draws the neighbor’s ground and objects at least half a view deep: 15 tiles across an east-west seam, half of the open Duo’s 29.7, and 12 across a north-south seam, half of a Pro Max’s 22.4 in portrait (section 5, Neighbor strip).6017 The forge computes the autotile masks across each seam, so a path that crosses it does not end in a rim, and cuts a gap in the town’s fence at every seam, at least 2 tiles wide, with the gap’s cells walkable on both sides.1426 The woods the forge draws 12 tiles deep around the town today (MARGIN = 12) give way to the neighbor along the whole shared edge: the neighbor’s strip replaces the woods margin there, and the woods stay only where no area joins. That revises the dossier, which cut the 2-tile gap in the woods margin as well and would have left the woods covering most of the neighbor’s strip.1426 The client subscribes to the neighboring room’s walkers when it starts drawing that room’s strip and switches its own room at the crossing.26

Check: 6 (no black frame, no main-thread stall, and the strip visible before the seam).

5. The name card

On entering an area by seam or tram, its name slides in, holds and leaves in about 3 seconds (section 5, Name card), at UI scale in SwiftUI, never in the pixel layer.2160

Check: 7 (name card timing).

6. Finds on the Meadow Walk

  • Where. Flower patches cover 12% to 18% of the Meadow Walk’s walkable tiles, drawn as their own autotile set so they read from a distance.26 That share is my choice, not a canon figure. Counted the same way, over walkable ground, the canon’s first routes are 18.8% to 38.4% tall grass and its later routes 8.2% to 29.2% (section 1), so the patches sit with the later routes and below every first route: a glint is placed and visible, so the patches only have to frame it, not carry a per-step roll.17
  • How they appear. Not by per-step dice. On entering the Meadow Walk, the server places at most one visible glint for that collector inside a patch, chosen deterministically from the collector, the date and the area, the acre-entry rule of Animal Crossing, until the collector has had three that day.5526 A visible glint keeps the rule legible to a child and avoids streaks without needing the cooldown-and-ramp of section 5’s Rhythm row.
  • What they are. World-side things only: a sticker or frame for the room, a sleeve or pin cosmetic, or a note that names one of the day’s quests, which only a real scan can complete; the quests are already judged from the collection itself (Kiradex/World/Quests.swift).2765 Never a card, never XP, never anything sold; a find can never become a reason to buy. Coins wait: the world plan lets coins be earned by daily visits but sets no amount or cap for them, and puts coins in its fourth phase, so coin finds are deferred until that rule exists, and then they come out of the same daily-visit budget rather than adding to it.27
  • Who sees them. Each collector’s glint is theirs; friends walking together see their own. There is nothing to snatch and nothing to fight over.

Check: 10 (finds).

7. The arch and its keeper

The building between the Square and the Gallery Quarter is an 8-by-6 room with a door on each side and a keeper at a counter. The keeper hands out a cosmetic when the collector’s registered card count first passes 10, 30, 50 and 100, the collection-milestone gate of section 5’s Gates row, counted from the real-world collection the way XP is.2026 The room is also where the art changes from lawn to stone (section 5, Seams). Nothing is locked: the arch is always open, and the keeper only gives.

Check: 11 (arch keeper).

8. The map screen

A 16-by-12 grid of named rectangles, one square per 10 tiles, rounded: the Square 4 by 3, Binder Row 4 by 1 on the Square’s east side, the Meadow Walk 2 by 6 above it, the Lakeside 4 by 2 at the top, the Gallery Quarter 3 by 2 to the west. Stacked, the Lakeside, the Meadow Walk and the Square take 11 of the 12 rows (section 5, Map screen).2617 Every area is drawn and named from the first day. That is Kiradex’s own choice, not the canon’s: the four games draw every place once the player has the map, save a few late places, but hand the map over during play (section 5, Fast travel), and a collecting town has no reason to make anyone earn the right to see it. The current area pulses; visited areas show their tram stop. On the open Duo the map sits beside the world as a panel; on a phone it is a sheet.27

Check: 8 (map screen model).

9. The tram

Each outdoor area has a stop. A stop opens the first time the collector enters that area, the visited flag of section 5’s Fast travel row, set on entry and never by level or payment.1326 From the map screen, tapping a visited area rides there: fade out, the room changes, fade in at that area’s stop, then the name card. There are no rides from indoors, as Fly allows none (section 5, Fast travel).13 The tram turns the 28-to-30-second walk to the Lakeside into a tap once the walk has been done once, a shortcut earned by visiting rather than by an ability (section 5, Unlocks).26

Check: 9 (tram rules).

10. Names and art

Every area’s name, sign and string passes a deny list of protected names, and every tile and sprite comes from the forge.2726 The deny list does not exist yet: the dossier promised one in the repository, and the repository has none. Making it is part of this brief: a plain list of the protected names, one per line, checked into the repository beside the forge, and a test that reads every area’s name, signs and strings from the forge’s exports and fails on any entry of the list found in them, matched without regard to case.26 No numbered road names, no “region” naming scheme, and no building that reproduces a canon gatehouse’s look: the sizes and rules can match, but the shapes and names must be Kiradex’s own.26

Check: 13 (names and art).

11. Order of work

The world plan puts the plaza (rooms, sync, bubbles, profiles, the exchange screen) third and coins and the shop fourth.27 The areas fit as a phase 3b, after the plaza’s networking holds and before or alongside coins:26

  1. Connections in the forge and the server (format, reciprocity, seam drawing, room switch), the server’s eight-way search, and the deny list with its test, with Binder Row as the first area, because it uses the card shop the structures work already designed and is the smallest.
  2. The Meadow Walk and finds (server placement, the daily cap, the payloads).
  3. The map screen and the tram.
  4. The Lakeside.
  5. The Gallery Quarter with the arch, when the museum’s interior exists. The stall row on Binder Row waits for the marketplace phase.

Each step is a TestFlight build, as the world plan asks of every phase, with captures for its checks.27

The acceptance checks

Each can be run by a script over the forge’s exports and the server’s tests, or by a capture on the simulator; check 6 runs on a device, apart from its one simulator capture.26

  1. Reciprocity. The exports hold exactly three open seams, Square east to Binder Row, Square north to the Meadow Walk and Meadow Walk north to the Lakeside, and for every connection (a, dir, b, off) the export holds (b, opposite(dir), a, −off); the test fails on any one-sided connection, with no exceptions.
  2. Crossings. A breadth-first search from each area’s arrival and doors finds at least 2 crossing tiles on each side of every seam, facing walkable tiles across it, the method of measure_gen3_routes.py.6
  3. Distances. The shared eight-way search of item 3 over the joined areas, with the hedge gate as a one-way edge (entered from the lake side by a straight step only, never left toward the lake), and every length a path cost with a diagonal step counting √2, reports arrival to card shop at most 60 tiles; arrival to the Lakeside pier 110 to 120; pier to arrival at most 0.8 times the outward walk; arrival to the museum door at most 70. The forge prints the times at 4 tiles a second.
  4. Proportion. Tiles beyond the Square divided by the Square’s tiles lies between 2.0 and 3.9.
  5. Orientation. The Meadow Walk’s height exceeds its width.
  6. No black frame and no main-thread stall at a seam. On a device build, the collector walks across the seam between the Square and Binder Row, from a tile more than half a view short of the seam, before the stage starts building Binder Row’s mesh, until the first step past the seam has finished and the Square has become the strip behind. Two records cover that whole span. For the run, the display link asks for 60 hertz through its preferredFrameRateRange, so that a ProMotion display’s changing rate does not move the count mid-walk; Apple describes the range as one the display link makes a best attempt to honor, so the timing log, not the request, shows the rate that held.67 The first record is every frame the display shows, kept by a recording at that rate and inspected one frame at a time: a frame is black when its mean brightness is under a quarter of the span’s median frame (my threshold), and a single black frame anywhere in the span fails the check. The recording’s frame count over the span must equal the timing log’s callback count over the same span, so a capture that drops frames cannot pass by missing the black one. No capture method has yet been shown to record every displayed frame, and this match is what decides whether one does. When the counts differ and the timing log passes its own rule below, the capture is at fault and the run does not count; when they differ and the timing log fails that rule, the check fails. The second is the targetTimestamp of a CADisplayLink callback registered on the main run loop, as Apple’s own example registers it, the time at which Apple’s documentation says the next frame displays, logged on every frame; no interval between successive values may exceed 25 milliseconds, one and a half frames at 60 hertz, so a single dropped frame fails the check as a single black frame does, which catches a main-thread stall while the neighbor is built as well as at the crossing. A run whose timing log settles at any rate other than 60 hertz does not count, and Low Power Mode is off for it, since Apple names that mode, a critical thermal state and accessibility settings among what can change the rate.67 The device is an open iPhone Duo once one is at hand; no iPhone Duo is paired with my Mac as I write, so until then the check runs on an iPhone 18 Pro Max across the same seam, which shows whether the approach and the crossing stall or blank the screen on a phone but not how the Duo’s inner display paces its frames. The simulator cannot stand in: on my reading, its frame timing measures the Mac that runs it, not a phone. Separately, a capture on the open Duo’s simulator from inside the test bundle, with the collector on the Square’s last tile before the seam, shows at least 14 tiles of Binder Row.6064
  7. Name card. The card is on screen between 2.5 and 3.5 seconds after a seam crossing or a tram arrival.
  8. Map screen model. Unit tests: every area’s rectangle lies inside 16 by 12, no two overlap, every area has a name, the current area is marked, and an unvisited area’s stop is disabled.
  9. Tram rules. Server tests: a ride to an unvisited area is refused; a ride from an interior is refused; a ride ends at the destination’s stop.
  10. Finds. Server tests: at most one glint per area entry, at most three per collector per day, the same glint for the same collector, date and area, and payloads drawn only from the cosmetic and quest-note tables, never a card, XP or coins. A forge test: flower patches cover 12% to 18% of the Meadow Walk’s walkable tiles.
  11. Arch keeper. A unit test: the four milestone gifts fire once each, at registered counts of 10, 30, 50 and 100, and never from coins or purchases.
  12. Server parity. The server loads every area’s letters and connections and walks a collector from the arrival to the Lakeside pier across two seams and back through the hedge gate, with the eight-way search of item 3; the app and the server return the same tiles and the same cost both ways, and a step the client’s search would refuse, a corner cut or a step from the lane out through the gate, is refused by the server too, the pattern of the existing server tests.3728
  13. Names and art. The deny list exists in the repository with its test, and the test passes: every area name, sign and string clears the list; every tile and sprite comes from the forge.

Not in this brief

  • Per-step random encounters, or anything that plays like a wild battle. Finds are placed and visible.
  • Ability gates on core areas. No area opens by a level, a pin, a purchase or a tool; areas open by being walked to, and only the shortcut, the tram, is earned, by visiting. That is section 5’s Unlocks row read the kind way.5226
  • Journeys longer than about 30 seconds between two places people meet, without a tram. The canon’s minute-long legs are dungeons.7
  • Ledges, terraces with one-way drops, and any per-cell height. Deferred to the elevation post, which decides them; until then the brief gets its shorter way home from the hedge gate, which is one-way but flat.36
  • Numbered road names, a “region” naming scheme, badge-gated fast travel, or a building that copies a canon gatehouse’s look.27
  • One-sided connections. The canon uses them as a drawing trick; this brief has none, and check 1 fails on any.8
  • Coin finds, until the world plan sets how many coins a daily visit earns.27
  • The marketplace stalls on Binder Row before the marketplace phase.27

Key Takeaways

If you draw the art

  • Draw a seam only where the ground continues. Red joins one tileset across 76 of its 78 connections, and every Red gatehouse between two places is where the tileset changes; a building with two doors is the honest way to change material.8
  • Make the first route short and the grassiest: two to six screens, 14% to 23% of its map encounter ground, no trainers. Thin it out as the journey goes on.56
  • Draw the map screen as a coarse grid of named rectangles. Emerald’s is 28 by 15 squares, and 49 of its 95 rectangles are a single square.11

If you build the engine

  • Store connections as data with a direction, a neighbor and an offset, and test that every one has a reverse with the negated offset; Emerald’s 134 all do.842
  • Draw at least half a view of the neighbor beyond the edge. Gen 3 copies 7 cells (8 on the east) because the player sees 7 either side; at Kiradex’s scales that is 15 tiles on the open Duo and 12 on a Pro Max in portrait.960
  • Keep one scene across a seam and save the scene swap for doors and fast travel, where a fade hides it.1037
  • Measure distances with a search, not a ruler, and with every movement rule the engine has: on the nine measured routes whose ends meet on foot, the longer walk across is 1.15 to 1.70 times the long side and the walk home 0.95 to 1.42, and the way back can be a quarter shorter than the way out. A search without Crystal’s one-sided walls and sideways corner hops puts Route 32 at 110 cells each way; with them it is 132 out and 128 home.5617
  • Give the app and the server one walking graph. If the client walks eight ways and the server four, every distance a test measures belongs to only one of them.28

If you design the loop

  • Size every trip in seconds. A first leg is 15 to 25 seconds of walking in the canon; a minute is a dungeon.7
  • Make the way home shorter than the way out, and give it something one-way to do it with, because on a grid that can be walked both ways the shortest walk back is the shortest walk out. The canon does it with ledges, by up to 44%; a gate that opens only from the far side does it without height.5666
  • Once the player has the map, show every place on it, and earn only the shortcut, by visiting. Every Pokémon game measured here hands over the map during play, draws every place on it whether visited or not, save a few late places held back by story or event flags, sets the visited flag on entry, and lists only visited places for fast travel; Kiradex goes one step further and shows its map from day one.4445121323222426
  • Open areas by deed and date, the way Stardew does, rather than by a level or a purchase, and give the walker something to do with the collection everywhere they go.5227

FAQ

How long should a route be in a top-down RPG?

In the 2D Pokémon games, two to ten console screens along the axis of travel, and the first route two to six. In cells, the sixteen routes I measured run from 20 to 108 along their long side, and on the nine that can be walked end to end, the shortest walk across in the longer direction is 1.15 to 1.70 times that length because the path winds, and the walk home 0.95 to 1.42. At 16 frames a cell, a first leg from a door to the next town’s main building takes 15.5 seconds in Emerald and 25.2 in FireRed.56717

How do Pokémon games connect maps without a loading screen?

Each map lists its neighbors with a direction and an offset. In Emerald the engine copies the current map into a buffer with a 7-cell margin (8 on the east), “the player has 7 metatiles of view horizontally in either direction”, and fills the margin on a connected side with 7 rows or columns of the neighbor (8 columns on the east), drawn with the current map’s tiles. When the player crosses, it loads the new map’s secondary tileset, palette, music and weather and slides in a name popup, with no fade. Red does the same with a 3-block, 6-cell margin.91039

Why do the Kanto routes have gatehouses?

On my reading of the data, because a Game Boy seam can only join two maps drawn from the same tileset, and a gatehouse is a door where the tileset changes: 76 of Red’s 78 connections join one tileset, and every Red gate between two places joins two. Gates also hold rules: the Saffron guards who want a drink, a badge check on Route 22, and three aides who give items at 10, 30 and 50 species owned. No developer statement confirms the tileset reason.8192029

Why are ledges one-way in Pokémon?

A ledge cell’s behavior names one direction of travel, and the player can cross it only that way. Measured on the early routes, the ledges face the earlier town: the walk home is 2% to 44% shorter than the walk out on all nine routes with ledges whose ends meet on foot. On the four routes searched for it, the way home crosses 0 to 5 cells of tall grass against 4 to 19 on the way out.365618

How does Fly decide which towns you can fly to?

By a visited flag set when you enter the town. In Emerald each of the 16 towns and cities sets its FLAG_VISITED_* flag in its on-transition script, and the region map marks a town as a Fly target only when the flag is set; Red keeps a bit per city in wTownVisitedFlag, and Crystal sets a fly point in a map callback. Fly also needs a badge (the third in Red and FireRed, the sixth in Emerald) and an outdoor map.13222423

How big is a town compared with its roads?

Two to four times smaller. Route cells divided by town cells are 1.97 in Crystal, 2.65 in Red, 3.70 in Emerald’s land routes and 3.87 in FireRed; on Emerald’s map screen the ratio reads 5.9 to 1, because a town takes one or two squares however large it is.3334

Mechanics, sizes and methods are not protected by copyright. Specific tiles and sprites are protected by copyright, and names and marks by trademark. The first post in this series covers the line, with the Copyright Office’s Circular 33, which puts systems and methods of operation outside copyright, and the patents in Nintendo’s suit against Palworld’s developer.60 This brief borrows numbers and rules and draws every tile from Kiradex’s own forge, with names checked against a deny list.26


How this post was made. The research dossier behind it was compiled on October 4, 2026 from shallow clones of the pret decompilations, measured by six Python scripts saved with their outputs, and from saved copies of the Stardew Valley Wiki, Nookipedia, the zladx disassembly, Porymap’s manual, GBATEK, Pan Docs, one Bulbapedia page, and Apple’s pages. Every Pokémon number in the text is a script’s output, and each note names the script. Before publication, a second review on October 5 led to three re-measurements, Crystal’s one-sided walls and corner hops, running over ledges, and the brief’s meadow on the app’s eight-way walk, and to a closer reading of the encounter code’s grace steps; each note says what moved. The proposal in section 7 is mine and labeled so; none of it has been built.

Related on this site: Pixel-Art Worlds on iPhone is the first post in this series, with the tile systems, the RealityKit recipe and the per-device tile counts this post’s views rest on; Pixel-Art People: Characters and a Creator on iPhone is the collector who walks these routes; Pixel-Art Structures: Houses, Halls and Interiors on iPhone has the doors, warps and floor swaps the tram and the arch reuse, and the refusal of ledges this post leaves to the elevation post; iPhone Duo for Developers derives the inner display’s size the half-view strip is computed from; Prepare Your App for iPhone Duo covers the side-by-side layout the map panel follows; and Xcode 27.1 Beta: Your App in the iPhone Duo Simulator covers the simulator the brief’s seam check runs on.

Sources


  1. pret, pokered/home/overworld.asm at commit d2704a6 (OverworldLoop calling DelayFrame twice per iteration; AdvancePlayerSprite moving 2 pixels per iteration for 8 iterations, wWalkCounter 8; the bicycle calling AdvancePlayerSprite twice per iteration), read October 4, 2026, https://github.com/pret/pokered/blob/master/home/overworld.asm. ↩↩↩↩

  2. pret, pokecrystal/engine/overworld/map_objects.asm (StepVectors: a walking step of 8 ticks of 2 pixels, a bike step of 4 ticks of 4 pixels) and pokecrystal/engine/overworld/events.asm (MaxOverworldDelay: db 2) at commit 5beda23, read October 4, 2026, https://github.com/pret/pokecrystal/blob/master/engine/overworld/map_objects.asm. ↩↩↩↩

  3. pret, pokeemerald/src/event_object_movement.c at commit 731ad5b (the step tables: 16 entries in sStep1Funcs for walking, 8 for running and surfing, 6 for the Acro Bike and currents, 4 for the Mach Bike, 2 for the fastest; JUMP_DISTANCE_FAR 32 frames over two cells; sJumpY_High peaking at 12 pixels), read October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/event_object_movement.c. ↩↩↩↩↩

  4. Kiradex source, Kiradex/World/PlazaRig.swift, line 101 (tilesPerSecond: Float = 4) and line 122 (runPace: Float = 1.6), read from the working tree on October 4, 2026, and lines 660 and 666 (each frame adds dt × tilesPerSecond × pace ÷ length to a step’s progress, and a finished step sets the progress back to 0, dropping the overshoot), read October 5, 2026; private repository. The 6.4 tiles a second is the nominal run, 4 × 1.6. ↩↩↩↩↩

  5. Author’s measurement, October 4, 2026: measure_gen12_routes.py in the author’s evidence folder for this post, output gen12_routes.txt. Inputs from pret pokered at d2704a6: constants/map_constants.asm (sizes in blocks, doubled to cells), maps/Route*.blk, gfx/blocksets/overworld.bst against Overworld_Coll, grass tile $52 and data/tilesets/ledge_tiles.asm (one 8-by-8 tile per cell, the lower-left), data/maps/objects/Route*.asm (trainers as object_event lines with an OPP_ class), data/maps/headers/Route*.asm (connections). From pret pokecrystal at 5beda23: maps/Route*.blk, data/tilesets/<tileset>_collision.asm through CollisionPermissionTable (the four bytes per block assumed row-major), maps/Route*.asm (trainers as OBJECTTYPE_TRAINER). Extended October 5, 2026 (the earlier output is kept as gen12_routes.pre-walls.txt): Crystal’s side walls, the collision bytes COLL_RIGHT_WALL to COLL_UP_LEFT_WALL ($b0 to $b7) and the side buoys, refuse a step out through the walled side and a step in through it, as GetMovementPermissions sets them (home/map.asm, from line 1511) and .CheckLandPerms reads them (engine/overworld/player_movement.asm, line 686); the corner ledges HOP_DOWN_RIGHT and HOP_DOWN_LEFT hop down or sideways (.ledge_table, line 383), and a hop is tried only after the plain step fails (.Normal, lines 45 to 56); shortest paths are found by Dijkstra’s search, since a hop costs 2. Only Route 32 has side walls (41 cells, all UP_WALL, among them the block at data/tilesets/johto_collision.asm line 113), and only its walks moved: 110 each way before, 132 south and 128 north after. probe_gen12_exact.py (output probe_gen12_exact.txt) runs every combination of the three changes: the walls alone give 132 each way, the two-way corner hops then shorten the walk home to 128, and the exact search changes nothing; probe_route32_path.py traces the hop, from the HOP_DOWN_RIGHT lip at cell (8, 80) over a WALL cell to (10, 80). pokered has no per-tile one-sided permission; its TilePairCollisionsLand (data/tilesets/pair_collision_tile_ids.asm) blocks a pair of tiles in both directions and lists only the CAVERN and FOREST tilesets, while every map measured here is OVERWORLD. The Gen 2 lip reading is from probe_gen2_ledges.py (21 of 21 HOP_DOWN cells on Route 30 have a WALL cell below). The Gen 1 cell model was checked by eye on render_gen1.py’s render of Red Route 1 at twice size with a 16-pixel grid (render_Route1.png, analysis only, derived from copyrighted art and not published). Also the route and town areas behind note 33. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  6. Author’s measurement, October 4, 2026: measure_gen3_routes.py in the author’s evidence folder for this post, outputs gen3_routes.txt and gen3_routes.json. Inputs from pret pokeemerald at 731ad5b and pokefirered at 037335f: data/layouts/layouts.json (sizes), every cell of each route’s map.bin (bits 0 to 9 metatile, 10 and 11 collision, 12 to 15 elevation), its behavior from the primary or secondary metatile_attributes.bin (Emerald u16, behavior bits 0 to 7; FireRed u32, behavior bits 0 to 8, encounter type bits 24 to 26), counts of MB_TALL_GRASS, MB_JUMP_* and water behaviors, and data/maps/Route*/map.json (connections, trainers as object_events whose trainer_type is not TRAINER_TYPE_NONE, trainer_sight_or_berry_tree_id). Shortest walks by breadth-first search. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  7. Author’s measurement, October 4, 2026: measure_travel.py in the author’s evidence folder for this post, outputs travel.txt and travel.json, over pret pokeemerald at 731ad5b and pokefirered at 037335f. Breadth-first search over (map, cell) pairs through seams, warps and ledges, from the cell below the first door to the last door, the count including the final step up into it (line 136, “+1: the step up into the door”); seconds as cells × 16 frames ÷ 59.7275 hertz walking. Running, extended October 5, 2026 (the earlier output, which priced every running cell at 8 frames, is kept as travel.pre-ledgerun.txt), is a second search for the fewest frames, 8 a step and 32 a ledge hop, because FireRed’s hop is Jump2 at JUMP_DISTANCE_FAR, 32 frames at any gait (src/field_player_avatar.c PlayerJumpLedge, line 905; src/event_object_movement.c DoJumpSpriteMovement, line 9094); the Route 4 Center to Cerulean leg is 2,528 frames, 42.3 seconds, with one hop, and no other outward leg in the table hops a ledge; Cut trees, Rock Smash rocks and Strength boulders block their cells unless the run says otherwise (the “after Cut” run removes them, which on Route 2 opens ROUTE2_EAST_BUILDING). Fades and battles are not counted. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  8. Author’s measurement, October 4, 2026, extended October 5, 2026 to read 8 columns on the east, as FillEastConnection copies them, and to cut each strip where it would leave the buffer, as FillNorthConnection, FillSouthConnection, FillWestConnection and FillEastConnection cut it; the primary-only counts moved from 22 of 38 (Emerald) and 25 of 34 (FireRed) to 24 of 38 and 24 of 34: measure_connections.py in the author’s evidence folder for this post, outputs connections.txt and connections.json, over all four decompilations: every map connection, tileset agreement across each seam (for Gen 3, primary and secondary sets, and whether the neighbor’s strip in the margin, 7 rows or columns and 8 columns on the east, uses primary metatiles only), reciprocity with negated offsets, non-zero offsets, maps on the GATE and FOREST_GATE tilesets in Red (data/maps/headers/*.asm), environment GATE in Crystal (data/maps/maps.asm), and Gen 3 indoor maps whose warps lead to two different outdoor maps or to two sides of one. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  9. pret, pokeemerald/include/fieldmap.h (MAP_OFFSET 7 and its comment, “the player has 7 metatiles of view horizontally in either direction”; MAX_MAP_DATA_SIZE 10240; MAP_OFFSET_W as MAP_OFFSET * 2 + 1 and MAP_OFFSET_H as MAP_OFFSET * 2), pokeemerald/src/fieldmap.c (InitMapLayoutData sizing the buffer as the map plus MAP_OFFSET_W by MAP_OFFSET_H; FillSouthConnection and its siblings, with FillNorthConnection setting x = offset + MAP_OFFSET and width = cWidth when the strip fits, MAP_OFFSET rows tall, and FillEastConnection copying MAP_OFFSET + 1 columns; GetBorderBlockAt ORing the border with MAPGRID_IMPASSABLE), data/maps/Route101/map.json (Oldale Town to the north at offset 0) and data/layouts/layouts.json (LAYOUT_ROUTE101 and LAYOUT_OLDALE_TOWN, each 20 by 20) at 731ad5b, read October 4, 2026, https://github.com/pret/pokeemerald/blob/master/include/fieldmap.h and https://github.com/pret/pokeemerald/blob/master/src/fieldmap.c. ↩↩↩↩↩↩↩

  10. pret, pokeemerald/src/field_camera.c (DrawMetatileAt drawing with the current layout’s primary and secondary tilesets) and pokeemerald/src/overworld.c (LoadMapFromCameraTransition: the on-transition script, the secondary tileset and palette, music, weather and the map-name popup, with no fade) at 731ad5b, read October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/overworld.c. ↩↩↩↩↩↩↩↩↩↩

  11. pret, pokeemerald/src/region_map.c (MAP_WIDTH 28, MAP_HEIGHT 15), src/data/region_map/region_map_layout.h and src/data/region_map/region_map_sections.json at 731ad5b, read October 4, 2026, with counts by measure_region_maps.py (output region_maps.txt), https://github.com/pret/pokeemerald/blob/master/src/data/region_map/region_map_layout.h. ↩↩↩↩↩↩↩

  12. pret, pokeemerald/src/field_control_avatar.c (a metatile with behavior MB_REGION_MAP runs EventScript_RegionMap), data/event_scripts.s (EventScript_RegionMap, special FieldShowRegionMap), data/maps/RustboroCity_DevonCorp_3F/scripts.inc (setflag FLAG_SYS_POKENAV_GET), src/start_menu.c (the PokéNav menu entry only when FLAG_SYS_POKENAV_GET is set) and src/region_map.c (the Battle Frontier and Southern Island MAPSECTYPE_NONE until their FLAG_LANDMARK_* flags, lines 1213 to 1216) at 731ad5b, read October 4, 2026, with the wall-map layouts by scan_wall_maps.py in the author’s evidence folder for this post (output wall_maps.txt: the upstairs of both Littleroot houses and every Pokémon Center’s ground floor), https://github.com/pret/pokeemerald/blob/master/data/event_scripts.s. ↩↩↩↩↩↩↩↩

  13. pret, pokeemerald/src/party_menu.c (FIELD_MOVE_FLY against FLAG_BADGE06_GET), src/overworld.c (Overworld_MapTypeAllowsTeleportAndFly), src/region_map.c (MAPSECTYPE_CITY_CANFLY when the town’s FLAG_VISITED_* is set) and data/maps/OldaleTown/scripts.inc (setflag FLAG_VISITED_OLDALE_TOWN) at 731ad5b, read October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/region_map.c. ↩↩↩↩↩↩↩↩↩↩

  14. Kiradex source, scripts/forge/town.py, lines 79 and 80 (MARGIN = 12, WIDTH, HEIGHT = 40, 30) and its BUILDINGS list (seven buildings, doors to room:me, room:npc-* or hall, one arrival), read October 4, 2026; private repository. ↩↩↩↩↩↩

  15. Martin Korth, GBATEK, LCD timing (“Total 228 lines, 16.743 ms, 280896 cycles - ca. 59.737 Hz”), saved October 4, 2026 as gbatek.txt, https://problemkaputt.de/gbatek.htm. ↩↩↩

  16. Blake Crosley, “Pixel-Art Motion: Walks, Cameras and Doors on iPhone,” blakecrosley.com, October 5, 2026, section 7 (“Where the walk stands today”: the frame model of Kiradex’s walking code, in which the run takes 10 frames a tile at 60 hertz, 6.00 tiles a second, and 19 at 120, 6.32, because each tile’s overshoot is dropped; the door’s 220-millisecond wait and the floor change with no fade; and the brief’s walk of 1 pixel a tick, 16 ticks a tile at 60 hertz, 3.75 tiles a second, with the stepped veil over doors and floors), https://blakecrosley.com/blog/pixel-art-motion-on-iphone. ↩↩↩↩↩

  17. Author’s arithmetic from the measured values in the text, the October 5 figures printed by arith_oct5.py in the author’s evidence folder for this post (output arith_oct5.txt): cells a second as 59.7275 ÷ 16 and ÷ 8; Kiradex’s 4 tiles a second against 3.73 (7.2% faster), and its run against 7.47 at 6.00 (19.6% under) and 6.4 (14.3% under); a time at 4 tiles a second against one at 3.75 as 4 ÷ 3.75, a fifteenth longer, and a diagonal’s 23 ticks at 60 hertz against √2 ÷ 4 seconds as 0.3833 ÷ 0.3536 = 1.084, about a twelfth longer (printed by r6_arith.py); seconds per cell as 16 ÷ 59.7275 (0.27) and per Kiradex tile as 1 ÷ 4 (0.25); path factors as the shortest walk divided by the route’s long side, for the longer direction and for the walk home, on the nine routes with a seam-to-seam walk each way (a straight walk from the first row to the last of a 20-cell map is 19 steps, 0.95), and the savings as (out − home) ÷ out, 2.38% (Red Route 3) to 44.12% (Emerald Route 101); tall grass over walkable cells per route from the two route scripts’ grass and walkable counts; the towns’ squares on Emerald’s map from the width and height of the 16 town and city sections in region_map_sections.json (ten 1 by 1, six 1 by 2 or 2 by 1, 22 in all); the inner Duo’s tile counts as 2853 ÷ 96 and 2007 ÷ 96, 96 being 16 texels at 6 pixels; tiles ahead of a centered collector as half the tiles visible along the axis of travel; a 100-millisecond sample as one frame in 100 × 60 ÷ 1,000 = 6 at 60 hertz; the timing threshold as two frames at 60 hertz, 33 milliseconds; Animal Crossing’s 5 by 6 acres of 16 by 16 spaces as 80 by 96; the brief’s areas as 44 × 14 + 24 × 60 + 36 × 20 + 30 × 20 = 3,376 tiles over 40 × 30 = 1,200; half-views as the October 3 tile counts halved and rounded up; map-screen squares as each area’s tiles over 10, rounded. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  18. Author’s measurement, October 4, 2026: measure_grass_paths.py in the author’s evidence folder for this post, output grass_paths.txt: a 0-1 breadth-first search where entering a tall-grass cell costs 1 and any other move 0, ledges one way, using the cell models and door-reachable crossings of the two route scripts; Red Route 1, FireRed Route 1, Emerald Routes 101 and 102. The gateway cells are from probe_grass_gateway.py (output grass_gateway.txt), which re-runs Red Route 1’s southbound search with each grass cell in turn made plain ground: only the 8 cells of the gateway’s last four rows, two a row, lower the minimum. ↩↩↩↩↩↩

  19. pret, pokered/scripts/Route5Gate.asm (TEXT_ROUTE5GATE_GUARD_GEE_IM_THIRSTY, BIT_GAVE_SAFFRON_GUARDS_DRINK) and pokered/scripts/Route22Gate.asm (BIT_BOULDERBADGE) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/scripts/Route5Gate.asm. ↩↩↩↩↩

  20. pret, pokered/scripts/Route2Gate.asm, scripts/Route11Gate2F.asm, scripts/Route15Gate2F.asm (thresholds of 10, 30 and 50) and engine/events/oaks_aide.asm (CountSetBits over wPokedexOwned) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/engine/events/oaks_aide.asm. ↩↩↩↩↩

  21. pret, pokeemerald/src/map_name_popup.c at 731ad5b (POPUP_OFFSCREEN_Y 40, the slide of 2 pixels a frame, tOnscreenTimer > 120), read October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/map_name_popup.c. The 190-frame total is the author’s count of the task’s states by their thresholds; each state may be a frame longer or shorter. ↩↩↩↩↩

  22. pret, pokered/data/maps/town_map_entries.asm (37 outdoor entries, one unused; 60 indoor), engine/overworld/toggleable_objects.asm (wTownVisitedFlag, commented “mark town as visited (for flying)”), engine/items/town_map.asm (the fly list skipping unvisited towns) and engine/menus/start_sub_menus.asm (Fly needs the Thunder Badge, bit 2, and an outdoor map) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/engine/items/town_map.asm. ↩↩↩↩↩↩↩

  23. pret, pokefirered/src/data/region_map/region_map_layout_kanto.h and the three Sevii layouts (22 by 15 per page, overworld and dungeon layers), src/party_menu.c and include/constants/party_menu.h (Fly as FLAG_BADGE01_GET + fieldMove with FIELD_MOVE_FLY 2, the third badge), src/region_map.c (GetMapsecType returning MAPSECTYPE_VISITED only when the place’s FLAG_WORLD_MAP_* flag is set, from line 2957; Fly accepting only a visited square; the Sevii pages withheld until FLAG_SYS_SEVII_MAP_123 and FLAG_SYS_SEVII_MAP_4567, lines 1028 and 1556, which the One Island Center’s scripts set; Navel Rock and Birth Island painted over until FLAG_WORLD_MAP_NAVEL_ROCK_EXTERIOR and FLAG_WORLD_MAP_BIRTH_ISLAND_EXTERIOR are set, lines 1521 to 1524), data/maps/CeladonCity/scripts.inc (setworldmapflag FLAG_WORLD_MAP_CELADON_CITY in the on-transition script), data/maps/PalletTown_RivalsHouse/scripts.inc (the rival’s sister giving the Town Map, RECEIVED_TOWN_MAP) and data/event_scripts.s (EventScript_WallTownMap, special ShowTownMap) at 037335f, read October 4, 2026, with counts by measure_region_maps.py and wall maps by scan_wall_maps.py (output wall_maps.txt: every Pokémon Center’s ground floor, Viridian’s school and some houses), https://github.com/pret/pokefirered/blob/master/src/data/region_map/region_map_layout_kanto.h. ↩↩↩↩↩↩↩↩↩↩

  24. pret, pokecrystal/data/maps/landmarks.asm (95 landmarks), data/maps/flypoints.asm (24 fly points), maps/VioletCity.asm (VioletCityFlypointCallback: setflag ENGINE_FLYPOINT_VIOLET) and engine/events/overworld.asm (ENGINE_STORMBADGE) at 5beda23, read October 4, 2026, https://github.com/pret/pokecrystal/blob/master/data/maps/flypoints.asm. ↩↩↩↩↩↩↩

  25. zladx, LADX-Disassembly at commit 2a5c2c0, src/constants/memory/wram.asm (wOverworldRoomStatus, ds $100) and src/constants/gameplay.asm (OW_ROOM_STATUS_VISITED EQU $80 and the other status bits), saved October 4, 2026 as ladx-wram.asm and ladx-gameplay.asm, https://github.com/zladx/LADX-Disassembly/blob/main/src/constants/gameplay.asm. ↩↩↩

  26. Author’s research dossier, “Beyond the plaza: routes, map connections and districts in the canon,” October 4, 2026, section 4 (“The brief for Kiradex”), the author’s synthesis: the five areas and their sizes, the distance targets, the connection format, the seam, presence and fence-gap plan, the finds, the arch keeper, the map screen, the tram, the order of work, the thirteen acceptance checks and the refusals. Kiradex repository docs/research/routes/01-routes.md; private. The outward band was narrowed on October 5, 2026 from the dossier’s 90 to 120 tiles to 110 to 120, for the reason in note 66; the dossier’s copy still carries the earlier band. Also set on October 5, after the dossier and not in its copy: the eight-way walking graph shared by the app and the server, the meadow’s four hedges, check 6’s every-frame inspection, the deny list as work to do, and the deferral of coin finds. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  27. Kiradex, docs/WORLD.md, “Kiradex World: research and plan,” read October 4, 2026 (private repository): section 1 (“The rules for Kiradex World”: nothing of theirs in the world); section 4 (“Levels”: “XP comes only from the real world, which is the point of the app”; “Coins and the shop”: coins earned by scans, levels and daily visits; “The plaza”: rooms of up to about 40 players, sharded by region, the camera following the player clamped to the map); section 5 (“What the Duo gives us”: “The plaza on the open inner display is the best version of this: wide view, your profile card beside the world when you tap someone”); section 6 (the marketplace through eBay, the stall); section 7 (“Order of work”, each phase a TestFlight build); and the decisions of October 2, 2026 (the server on FastAPI and WebSockets). ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  28. Kiradex source, read October 5, 2026 (private repository): Kiradex/World/TileMap.swift, path(from:to:) from line 325 (eight moves; a diagonal costs Float(2).squareRoot() and, at line 348, is skipped unless both tiles it passes between are walkable; the cheapest open tile expanded first), and server/app/rooms.py, Plaza.path from line 52 (breadth first over the four moves at line 66; its docstring: “the same walk the app takes”). ↩↩↩↩↩

  29. Author’s research dossier, “Beyond the plaza: routes, map connections and districts in the canon,” compiled October 4, 2026, sections “Method” and 5 (“What is measured and what is not”): the shared walk definitions (a step is one cell; a ledge one way and two cells; a seam counts only where the neighbor’s facing cell is reachable from one of its doors, seeded from other connections one level deep for a neighbor with no warps; trainers, NPCs and story blocks ignored; no surfing; Gen 3 elevation reduced to equal heights or either side at 0 or 15; warps fire when stepped into; Cut trees, Rock Smash rocks and Strength boulders blocked unless stated), the Gen 1 and Gen 2 cell-model caveats, the popup timing caveat, the frame-rate figure, the classification caveats, the secondary sources not checked against game data, and the readings that are not facts. Kiradex repository docs/research/routes/01-routes.md; private, with a copy in the author’s research state. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  30. gbdev, Pan Docs, “Rendering” (70,224 dots a frame, “@ 59.7 fps”), saved October 4, 2026 as pandocs-timing.txt, https://gbdev.io/pandocs/Rendering.html. ↩

  31. pret, pokeemerald/src/field_control_avatar.c (CheckStandardWildEncounter, lines 668 to 686: while sWildEncounterImmunitySteps < 4 it counts the step and returns without testing; after a successful StandardWildEncounter it sets the count back to 0), src/overworld.c (RestartWildEncounterImmunitySteps in LoadMapFromCameraTransition, line 800, and LoadMapFromWarp, line 850), src/battle_setup.c (the same call at a battle’s start, line 370), src/wild_encounter.c (StandardWildEncounter: the 40% skip on a behavior change, lines 531 to 539 and 599; WildEncounterCheck, from line 502: the rate times 16, scaled by the Mach and Acro Bikes to 80%, by ApplyFluteEncounterRateMod and ApplyCleanseTagEncounterRateMod, and by the lead’s ability, then Random() % 2880 against it) and src/data/wild_encounters.json (land rate 20 on Routes 101 to 104) at 731ad5b, read October 4 and 5, 2026, https://github.com/pret/pokeemerald/blob/master/src/field_control_avatar.c. ↩↩

  32. pret, pokefirered/src/wild_encounter.c at 037335f, read October 4 and 5, 2026: GetMapBaseEncounterCooldown (8 − rate/10 steps, line 686); HandleWildEncounterCooldown, lines 707 to 755 (once the steps since the last encounter reach the cooldown, every step may try; before that each encounter-cell step adds one to the count and lets that one step try when Random() % 100 < 5, without ending the cooldown); TryStandardWildEncounter, lines 757 to 776 (the count and the buff go back to 0 only after an encounter starts); the same reset on every map load, where src/overworld.c (lines 764 and 799) calls RestartWildEncounterImmunitySteps, which in FireRed calls ResetEncounterRateModifiers (src/field_control_avatar.c, lines 735 to 737); the 60% roll on a new behavior (line 370); DoWildEncounterRateTest, line 309 (rate × 16 plus encounterRateBuff × 16 / 200, out of MAX_ENCOUNTER_RATE 1,600); and AddToWildEncounterRateBuff, line 778 (the rate added after every failed roll unless a Repel is active), https://github.com/pret/pokefirered/blob/master/src/wild_encounter.c. ↩↩

  33. Author’s measurement, October 4, 2026, from measure_gen12_routes.py (Red: ROUTE_1 to ROUTE_25 against the 11 map ids below $0B in constants/map_constants.asm, blocks times 4; Crystal: environment ROUTE against TOWN in data/maps/maps.asm, sizes from constants/map_constants.asm) and measure_connections.py (Emerald and FireRed: map_type with sizes from layouts.json; Emerald’s 11 MAP_TYPE_OCEAN_ROUTE maps, 45,600 cells, excluded from the land figure; FireRed’s routes include the Sevii Islands). Outputs gen12_routes.txt and connections.txt. ↩↩↩↩↩↩

  34. Author’s measurement, October 4, 2026: measure_region_maps.py in the author’s evidence folder for this post, outputs region_maps.txt and region_maps.json (Emerald: 129 route squares and 22 town squares on the 28-by-15 grid). ↩↩

  35. Bulbapedia, “Kanto Route 1,” walkthrough section, saved October 4, 2026 as bulba-route1.txt, https://bulbapedia.bulbagarden.net/wiki/Kanto_Route_1. Used once, as a cross-check on the fewest-grass search. ↩

  36. Author’s research dossiers for the structures post, Kiradex repository docs/research/structures/01-structures-in-the-canon.md, section 8.8 (“What to refuse”: “No ledges to jump, no climbing, no isometric”), and 02-structures-craft-and-engine.md (Emerald’s GetLedgeJumpDirection, which lets a ledge be crossed only in the direction its behavior names), October 3, 2026; private. ↩↩↩↩

  37. Blake Crosley, “Pixel-Art Structures: Houses, Halls and Interiors on iPhone,” blakecrosley.com, October 3, 2026 (section 6: one depth rule and the objects mesh, warps as data, floors swapped in place with .id(floor.name); section 7: the server’s tests on plaza.json and the list of what the build does not do, including “a one-way ledge”), https://blakecrosley.com/blog/pixel-art-structures-on-iphone. ↩↩↩↩↩↩↩

  38. pret, pokered/data/maps/headers/Route1.asm (connection north, ViridianCity, VIRIDIAN_CITY, -5) and pokered/macros/scripts/maps.asm (the connection macro’s strip pointers) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/macros/scripts/maps.asm. ↩↩↩

  39. pret, pokered/constants/map_data_constants.asm (MAP_BORDER EQU 3) and pokered/home/overworld.asm (CheckMapConnections) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/constants/map_data_constants.asm. ↩↩

  40. pret, pokered/data/maps/headers/Route22.asm and Route23.asm (connection north, Route23, ROUTE_23, 0 ; unnecessary and its reverse) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/data/maps/headers/Route22.asm. ↩

  41. pret, pokecrystal/data/maps/attributes.asm (connections) and data/maps/maps.asm (tilesets, environments and map groups) at 5beda23, read October 4, 2026, https://github.com/pret/pokecrystal/blob/master/data/maps/attributes.asm. ↩

  42. Porymap documentation, “Editing Map Connections,” saved October 4, 2026 as porymap-connections.txt, https://huderlem.github.io/porymap/manual/editing-map-connections.html. ↩↩

  43. pret, pokered/data/maps/objects/Route2Gate.asm (Oak’s aide and a youngster) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/data/maps/objects/Route2Gate.asm. ↩

  44. pret, pokered/scripts/BluesHouse.asm (the rival’s sister giving TOWN_MAP once EVENT_GOT_POKEDEX is set, then EVENT_GOT_TOWN_MAP), engine/items/town_map.asm (DisplayTownMap stepping through every entry of TownMapOrder with no visited check; wTownVisitedFlag read only in BuildFlyLocationsList) data/tilesets/bookshelf_tile_ids.asm (bookshelf_tile HOUSE, $3D, TownMapText, a wall map that opens the same screen), data/maps/headers/BluesHouse.asm (the rival’s house on the HOUSE tileset; the player’s house is on REDS_HOUSE_1 and REDS_HOUSE_2), gfx/blocksets/house.bst (tile $3D only in block 14) and maps/BluesHouse.blk (block 14 in the second slot of the top row) at d2704a6, read October 4, 2026, https://github.com/pret/pokered/blob/master/scripts/BluesHouse.asm. ↩↩↩↩↩↩

  45. pret, pokecrystal/maps/CherrygroveCity.asm (the guide gent’s gift, setflag ENGINE_MAP_CARD, line 72) and engine/pokegear/pokegear.asm (the map card’s POKEGEAR_MAP_CARD_F; PokegearMap_CheckRegion showing Kanto’s map only when the player stands at a Kanto landmark; Kanto’s fly points withheld until Indigo Plateau is visited) at 5beda23, read October 4, 2026, https://github.com/pret/pokecrystal/blob/master/maps/CherrygroveCity.asm. ↩↩↩↩↩

  46. Stardew Valley Wiki, “Modding:Maps,” saved October 4, 2026 as sdv-modding-maps.txt, https://stardewvalleywiki.com/Modding:Maps. ↩↩

  47. Stardew Valley Wiki, “Pelican Town,” saved October 4, 2026 as sdv-pelican-town.txt, https://stardewvalleywiki.com/Pelican_Town. ↩

  48. Stardew Valley Wiki, “Bus Stop,” saved October 4, 2026 as sdv-bus-stop.txt, https://stardewvalleywiki.com/Bus_Stop. ↩

  49. Stardew Valley Wiki, “Cindersap Forest,” saved October 4, 2026 as sdv-cindersap.txt, https://stardewvalleywiki.com/Cindersap_Forest. ↩

  50. Stardew Valley Wiki, “Backwoods,” saved October 4, 2026 as sdv-backwoods.txt, https://stardewvalleywiki.com/Backwoods. ↩

  51. Stardew Valley Wiki, the locations navigation box as it appears on “Railroad,” saved October 4, 2026 as sdv-railroad.txt, https://stardewvalleywiki.com/Railroad; 26 places by the author’s count. ↩

  52. Stardew Valley Wiki, “The Mountain” (the two starting exits; the Mines on Spring 5; the Railroad after the Summer 3 earthquake; the Quarry bridge for the Crafts Room bundles or 25,000g), saved October 4, 2026 as sdv-mountain.txt, https://stardewvalleywiki.com/The_Mountain. ↩↩↩↩

  53. Stardew Valley Wiki, “The Desert” (the bus, Vault bundles or 40,000g), “Secret Woods” (the log and a steel axe) and “The Beach” (the 300-wood bridge), saved October 4, 2026 as sdv-desert.txt, sdv-secret-woods.txt and sdv-beach.txt, https://stardewvalleywiki.com/The_Desert, https://stardewvalleywiki.com/Secret_Woods and https://stardewvalleywiki.com/The_Beach. ↩↩

  54. Stardew Valley Wiki, “Speed,” saved October 4, 2026 as sdv-speed.txt, https://stardewvalleywiki.com/Speed. The page gives no units. ↩

  55. Nookipedia, “Acre” (the 16-by-16-space acre; the GameCube town of five acres by six; the station in A-3; the labels; the fish-and-bug spawn on entry and the six-square despawn; the town sizes of later games), saved October 4, 2026 as nook-acre.txt, https://nookipedia.com/wiki/Acre. ↩↩↩↩↩

  56. Nookipedia, “Map,” saved October 4, 2026 as nook-map.txt, https://nookipedia.com/wiki/Map. ↩

  57. Nookipedia, “Train” and “Train station,” saved October 4, 2026 as nook-train.txt and nook-train-station.txt, https://nookipedia.com/wiki/Train and https://nookipedia.com/wiki/Train_station. ↩

  58. zladx, LADX-Disassembly wiki, “Game engine documentation,” saved October 4, 2026 as ladx-engine.txt, https://github.com/zladx/LADX-Disassembly/wiki/Game-engine-documentation. ↩↩↩

  59. zladx, LADX-Disassembly wiki, “Maps data format” (the 512-byte overworld map of two-byte room pointers; the 10-by-8 overlay), saved October 4, 2026 as ladx-maps-format.txt, https://github.com/zladx/LADX-Disassembly/wiki/Maps-data-format. ↩

  60. Blake Crosley, “Pixel-Art Worlds on iPhone: What the 16-Bit Masters Knew,” blakecrosley.com, October 3, 2026 (section 5: the RealityKit recipe, one MeshDescriptor mesh for the map, the RealityView defaults, the scaling table computed from Apple’s spec pages and the Xcode 27 simulator profiles, the 11-point text minimum and SwiftUI text, the opacity-animation bug and its veil, the in-bundle XCUIScreen capture; “Since publishing”: one letter map exported to the app and the server; the FAQ on copyright and patents), https://blakecrosley.com/blog/pixel-art-world-on-iphone. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  61. Apple, “iPhone Duo: Technical Specifications,” saved October 4, 2026 as apple-duo-specs.txt, https://www.apple.com/iphone-duo/specs/. ↩

  62. Apple, Human Interface Guidelines, “Designing for games” (through the documentation JSON), saved October 4, 2026 as hig-games-plain.txt, https://developer.apple.com/design/human-interface-guidelines/designing-for-games. ↩↩

  63. Kiradex source, Kiradex/World/PlazaStage.swift, read October 5, 2026 (private repository): lines 132 and 133 (on a door’s warp, Task.sleep(for: .milliseconds(220)) and then onWarp(warp), with no fade) and lines 698 to 700 (a floor: warp sets the new floor in place, with no fade). ↩

  64. Apple Developer Documentation, “targetTimestamp” (an instance property of CADisplayLink, Core Animation; iOS and iPadOS 10.0 and later), saved October 4, 2026 (the abstract, “The time interval that represents when the next frame displays,” and the example that adds the display link to the main run loop), https://developer.apple.com/documentation/quartzcore/cadisplaylink/targettimestamp. ↩↩

  65. Kiradex source, Kiradex/World/Wants.swift (“What the town’s own collectors ask to be shown, and whether the collection has it”) and Kiradex/World/Quests.swift (the day’s and the week’s quests, “judged from the collection itself”), read October 4, 2026; private repository. ↩↩

  66. Author’s measurement, October 5, 2026: measure_meadow_gate.py in the author’s evidence folder for this post, output meadow_gate.txt. It joins the brief’s Square, Meadow Walk and Lakeside into one grid at the sizes in section 7: the Square as the forge ships it (town.json, 40 by 30, the arrival at column 19, row 13, the server’s walkable letters), its north fence opened along the shared edge; the Meadow Walk, 24 by 60, 4 tiles in from the Square’s west end so its lane meets the lawn between the hall and the house east of it, the lane 2 tiles wide behind a hedge on the east side with the gate as a one-way edge at its lake end, the rest crossed by four hedges, at the meadow’s rows 12, 24, 36 and 48, with 2-tile gaps tried in every position; the Lakeside, 36 by 20, centered on the walk, its north half lake, the pier 2 tiles wide in line with the lane and measured to its landward tile. It walks the app’s graph (TileMap.path): eight ways, a diagonal costing √2 and refused when either tile it passes between is blocked; the gate refuses any step from the lane toward the lake and admits a step from the lake only straight. The winding is the meadow’s own shortest walk from its south edge to its north edge, west of the lane. Two hedges, at the meadow’s rows 20 and 40, wind it 59.00 to 66.46 tiles over all 400 positions, three (rows 15, 30 and 45) 59.00 to 79.77 (6 of 8,000 inside 78 to 90), four 59.00 to 95.43 (5,912 of 160,000 inside 78 to 90); those bounds are for evenly spaced hedges, and uneven spacings wind harder by the same function (r7_uneven_probe.py, October 5, output r7_uneven_probe.txt: two hedges at rows 0 and 2 reach 77.00, three at rows 20, 22 and 24 reach 95.00). The same sweep with three hedges, at the meadow’s rows 15, 30 and 45 (added to the script’s section 5 on October 5 after the gate’s sixth round): the 6 layouts walk home 88.07 tiles and out 114.05 to 120.44, ratio 0.731 to 0.772, all at or under 0.8, and 5 of them are inside the band of 110 to 120, outward 114.05 to 119.02, ratio 0.740 to 0.772. So three hedges meet every target in 5 positions; four, the author’s choice, meet them in 4,111. On those 5,912 four-hedge layouts: home 88.07 tiles, outward 108.74 to 133.75, ratio 0.658 to 0.810, 5,886 at or under 0.8; the 0.8 target needs 88.07 ÷ 0.8 = 110.09 out; inside the band of 110 to 120, 4,111 layouts, outward 110.15 to 119.95, ratio 0.734 to 0.800, all at or under 0.8. The arrival to the north edge is 17.07 tiles; with the gate open both ways the walks are equal (88.07 each way on one layout of each hedge count). Over every offset from 0 to 16 tiles and both pier positions, the shortest walk out is 107.18 and the shortest walk home 88.07; at 4 tiles a second, 110 and 120 tiles are 27.5 and 30 seconds. The same output checks itself against the earlier model: run from its saved copy, the four-way breadth-first search with two hedges keeps 125 layouts, outward 113 to 119, home 91, ratio 0.765 to 0.805, and those 125 layouts walked eight ways come to outward 97.18 to 99.67, home 88.07, ratio 0.884 to 0.906, none at 0.8. That earlier model counted the winding as the meadow steps of whichever shortest path its search returned, which ties can change; the edge-to-edge winding cannot. Placements the brief does not describe, swept in the same output: with the pier at the shore’s middle the best ratio is 0.721 (offset 4, 2,182 of 5,912 layouts at or under 0.8), and where the lane meets a building the gate saves nothing. ↩↩↩↩

  67. Apple Developer Documentation, “preferredFrameRateRange” (an instance property of CADisplayLink, Core Animation; iOS and iPadOS 15.0 and later), saved October 4, 2026 (the Discussion: the display link makes a best attempt to call back within the range, the system also weighs the hardware, other work, Low Power Mode, thermal state and accessibility settings, and by default the range equals the display’s maximum refresh rate), https://developer.apple.com/documentation/quartzcore/cadisplaylink/preferredframeraterange. ↩↩

Related Posts

Pixel-Art Structures: Houses, Halls and Interiors on iPhone

How Pokémon, the SNES RPGs and Stardew build houses, interiors and floors, measured from source, and how Kiradex's town …

80 min read

Pixel-Art People: Characters and a Creator on iPhone

How the best pixel-art games build and dress their people, measured, and how we rebuilt Kiradex's collector, its wardrob…

79 min read

Prepare Your App for iPhone Duo: A Worked Example

Prepare and submit an app for iPhone Duo: the SDK stamp that switches the layout on, a real app walked through every pos…

64 min read