Pixel-Art Ledges, Stairs and Bridges in a Tile World

This post has not been translated yet, so you are reading the English original. Read it at the English URL

A ledge in the 2D Pokémon games does not require a drop in height. It is a one-way door in the walk graph, and it usually joins two cells at the same stored elevation: in FireRed every one of its 1,042 ledge cells is stored at the transition value 0, 984 of them (94.4%) join a take-off and a landing at the same elevation, and none joins two different land levels; in Emerald 784 of 944 do (83.1%), and 28 (3.0%) hop from one land level to another, where the engine simply hands the walker the landing cell’s elevation, as it does after any step.1234 No ledge in the maps read from Red, Crystal, Emerald or FireRed is crossed up the screen, and in Red, Crystal and Emerald the hop is two cells in 32 frames, 0.536 seconds, on a 12-pixel arc with the shadow left on the ground.156 Where Gen 3 does store height it is a second level, rarely a third: 50 of Emerald’s 68 outdoor layouts and 67 of FireRed’s 76 use at most one land level, Emerald’s outdoor stairs are mostly one or two cells (73 of 84) that cost an ordinary step (FireRed’s rock stairs slow the walk), and only 252 of Emerald’s 702 bridge cells (35.9%) carry the multi-level value that lets someone pass underneath.789 Replayed on all 114 outdoor stairs of the two games, Emerald’s walk rule climbs every one, and the rule sketched in Kiradex’s own engine notes climbs none.10 Kiradex World’s town has stood on two levels since build 35, with a retaining wall and a flight of stairs every 7 or 8 tiles, and a drop placed anywhere in that wall would save at most 0.59 tile on any trip from an upper door to a lower door, and nothing on a trip to the arrival.114 So the brief says yes to drops, as directed edges, at the plaza’s edge where a walk home is long; no to per-cell height until some tile is walkable at two heights; and it carries a corrected walk rule, a hop, a walkable roof row, a footbridge and nine checks a script or a capture can run.

TL;DR

  • A ledge is an edge, and it needs no height. In FireRed all 1,042 ledge cells sit at the transition value and 94.4% join equal elevations; in Emerald 83.1% of the straight ledge cells with a cell on each side do (784 of 944), the commonest triple being take-off 3, ledge 0, landing 3, 598 times, and only 28 join two different land levels, 22 from 5 to 3 and 6 from 3 to 5. In Gen 3 the engine gives the player a ledge only when the cell’s behavior names the straight direction of travel; it never reads the ledge’s elevation, and after the hop the walker takes the landing cell’s.121234
  • Ledges go down or sideways, never up, and mostly south. Counting the cells each engine hops, Emerald’s 946 ledge cells are 69.5% south, FireRed’s 1,042 are 92.3%, Red’s 758 are 93.5% down, and Crystal’s 1,148 are 84.0% straight down; Crystal’s up-hop constants are marked unused and appear in no map read. Emerald’s 77 diagonal corner pieces are drawn and blocked, and no code reads them; Crystal’s corners hop.1315144
  • The hop is two walking steps’ worth of time at any gait. Red, Crystal and Emerald all move the player two cells in 32 frames, 0.536 seconds (Red then waits at least three more frames before it reads the pad again), rising 12 pixels, with a shadow kept on the ground, a sound as it starts and, in Emerald, a three-frame puff of dust on landing; in Emerald a running player hops in the same 32 frames, twice what running the two cells takes.6151612174
  • Height, where it is stored, is two levels joined by a one-cell stair. Outdoors, 99.7% of Emerald’s and 99.8% of FireRed’s adjacent walkable pairs on a land level stand at one level; 73 of Emerald’s 84 outdoor stairs are one or two cells and cost an ordinary step, while FireRed’s rock stairs slow a walk to 23 frames a cell from 16.7864
  • On a stair the walker belongs to no level. Emerald sets the walker’s elevation to 0 on a transition cell; replayed on all 114 outdoor stairs of Emerald and FireRed, that rule climbs every one and the sketch in Kiradex’s engine notes, which keeps the old height, climbs none.31018
  • A ledge earns its cell where the stair is far. Half of the 549 straight outdoor ledge cells measured in Emerald (269) have no walk round inside their map, and the rest a median of 12 cells against the hop’s 2; Kiradex’s terrace has a flight every 7 or 8 tiles, so a drop there saves at most 0.59 tile.19114
  • What this gives Kiradex. A brief for one-way drops in the Meadow Walk’s terrace walls, which keep the routes post’s way home of 88.07 tiles and, joined to the Square, shorten the walk out on some layouts, so the drop design passes the routes brief’s bands on 4,607 of the 160,000 gap layouts against the gate’s 4,111; a hop that takes its two tiles’ time at the walker’s own gait, 0.5 seconds at today’s walk, with the shadow on the ground, departing from the canon at a run, where a fixed hop would make the Meadow’s run home slower than the hedge gate’s (section 9); a corrected walk rule for the day a map needs height; a walkable roof row; a footbridge over the pond that cuts one walk from 12.83 tiles to 6.00; and nine acceptance checks.2021221123

Kiradex is my card-collecting app for iPhone, and Kiradex World is the small pixel town inside it where collectors walk, meet and show cards. The town has stood on two levels since TestFlight build 35: a retaining wall the width of the town with five flights of stairs through it, the houses, the hall and the fountain’s terrace above, the arrival court, the shop and the park below.2425 Its height is drawn, not walked. The forge that builds the town says so in a sentence: “Height is drawn, not simulated: the wall’s cells are blocked and the stairs are stone, so nothing about the feet changed.”24 Three earlier pieces of this series left the next question open. The structures research refused ledges (“No ledges to jump, no climbing, no isometric”), the homage post narrowed that to “a one-cell, one-way drop” with no height in it, and the routes post got its shorter way home from a hedge gate and deferred one-way drops to this post.262717

So this post measures how Gen 3 stores height (Red and Crystal store none per cell), what a ledge is in all four games’ data, how long a hop takes, what a stair costs, how a bridge carries one walker over another, and how often any of it is needed. It then reads the SNES and modern references through what the structures research already established, and settles the ledge question for Kiradex with numbers taken from the town as it ships.

1. How Gen 3 stores height, measured from source

The numbers come from shallow clones of the pret decompilations, the community projects that rebuild each game from C and assembly with its constants named: pokered at d2704a6 (committed September 22, 2026), pokecrystal at 5beda23 (September 29), pokeemerald at 731ad5b (October 1) and pokefirered at 037335f (September 26).28 Every count below is the output of a Python script saved with its output in the author’s evidence folder for this post. There are twelve of them, seven from the first draft and five added in review (r3_jump_behaviors.py, r4_corner_cells.py, astra_ledge_triples.py, astra_meadow_joined.py and cr3_bridge_ledge_cells.py), with a helper, engine_terrain.py, that reads the engine’s own water and bridge tests out of the C source. The second-engine review found the land filter of measure_gen3_elevation.py wrong, a name filter that took the bridge behaviors for water, and it was rebuilt from the engine’s test; the earlier script and its outputs are kept beside the new ones, and the section on stairs below says which numbers moved. I re-ran all twelve for this draft, in a scratch copy of the folder, and got their saved outputs back byte for byte, with two exceptions, both in astra_meadow_joined.py: a line that prints how long its first section took to run, and the 160,000-layout sweep, which was run once and not repeated. A thirteenth, arith.py, prints every figure derived from theirs.2072913222304 Gen 3 cells are decoded with the decoder the routes post used, so the two posts read the same maps the same way.177

Two units recur. A cell is the handhelds’ 16-by-16-pixel map square, and a tile is Kiradex’s, 16 texels on a side, so the two compare one for one. Seconds at the handhelds’ frame rate use 2^24 ÷ 280,896, 59.7275 frames a second.204

Sixteen bits a cell, four of them height

A Gen 3 map cell is a 16-bit value. The low ten bits name the metatile, the next two the collision, and the top four the elevation: MAPGRID_ELEVATION_MASK 0xF000 // Bits 12-15. The header names four of the sixteen values (its fifth name, ELEVATION_INVALID, is outside them): ELEVATION_TRANSITION = 0, ELEVATION_SURF = 1, ELEVATION_DEFAULT = 3 and ELEVATION_MULTI_LEVEL = 15.31 Porymap, the map editor the decompilation community uses, explains the field in plain words: “Elevation is how the game determines whether or not an object is on the same level as something else.” The transition type “allows the player to move between different elevations. The most common use case is for stairs.” And the multi-level type “is used for bridges” and “remembers the player’s previous elevation”.32

The game uses few of the sixteen. Counted over every layout a map uses, once each, Emerald’s cells stand at elevation 0 157,795 times, 1 58,262 times, 2 28 times, 3 80,178, 4 3,652, 5 2,832, 6 55, 7 845, 9 112 and 15 523. Elevations 8 and 10 to 14 are never used.7 On land outdoors (routes, towns, cities and ocean routes; collision 0, and not water by the engine’s own test, MetatileBehavior_IsSurfableWaterOrUnderwater, which reads a flag table in metatile_behavior.c), Emerald stands 34,315 cells at elevation 3, 2,240 at 5, 1,006 at 4, 835 at 7, 109 at 9, 2,427 at the transition value 0 and 261 at 15, 248 of those the decks of the bridges a surfer passes under (section 4).733 The first draft of this post took its water test from the routes post’s script, which matched the words OCEAN and POND anywhere in a behavior’s name and so counted every MB_BRIDGE_OVER_OCEAN and pond-bridge cell as water; the second-engine review caught it, and every count in this post that stands on which cells are land was rerun with the engine’s test. In Emerald that moved 552 outdoor cells onto land, 300 of them bridge decks stored at 4, 248 at 15 and 4 at the transition value 0, the cells at the ends of two Route 110 bridges that the stairs below count, and the stairs moved with them; in FireRed, which has no bridge behavior, nothing moved.74 FireRed’s cells use only 0, 1, 3, 4 and 5.7 Read against the header’s names, elevation 3, the default, is the ground; 1 is water with a surfer on it; 0, the transition value, is ground that belongs to no level; and the rest are the raised ground of a handful of maps.317 Not all of the 0 is stairs. Of Emerald’s 2,427 outdoor land cells at 0, the stairs are the 169 that form patches touching two levels (counted below), and the other 2,258 are transition ground in patches that touch one level or none. Ledge cells are not among them: most ledge cells are stored at 0 too (section 2), but every one is stored blocked, and the land count leaves blocked cells out.78134

One level is the norm

Stacked bars of outdoor layouts by how many land elevations they use: Emerald, 68 layouts, 4 with none, 46 with one, 12 with two, 6 with three or more; FireRed, 76 layouts, 4 with none, 63 with one, 9 with two, none with three. Below, of the adjacent pairs of outdoor walkable cells on a land level, 170 of Emerald's 61,197 and 122 of FireRed's 61,461 change level with no blocked cell between.

Land levels per outdoor map, and how rarely two walkable cells side by side differ in height; drawn by figures/make_figures.py from gen3_elevation.txt.

Of Emerald’s 68 outdoor layouts, 50 use one land level or none (46 one, 4 none), 12 use two, and 6 use three or more: Mossdeep City (3, 4, 5, 7 and 9), Route 114 (3, 4, 5 and 7), Ever Grande City (3, 5 and 7), and Route 116, Route 120 and the Safari Zone’s northwest, three each.7 FireRed never goes past two: of its 76 outdoor layouts, 63 use one land level, 9 use two and 4 none.7 As shares, 73.5% of Emerald’s outdoor maps and 88.2% of FireRed’s are flat as far as the walk can tell.4 On my reading, Emerald’s six maps with three levels or more are its showpieces, and a second level is a feature a map earns, not a default.

Height changes across a face, not across a number

The engine could let two walkable cells side by side stand at different heights, with nothing between them but the number, and the walk rule below would refuse the step. Emerald almost never does it. Over every outdoor layout, counting pairs of adjacent walkable land cells that both stand on a land level (transition and multi-level cells aside), 170 pairs stand at two different levels, against 61,027 pairs at the same level, 0.28%, in 14 layouts; FireRed has 122 against 61,339, 0.20%, in 8.74 The level pairs are mostly 3 against 5 (97 in Emerald) and 3 against 4 (42 in Emerald, 88 in FireRed).7 The script counts only pairs that touch; on my reading, everywhere else a change of level goes through a stair or across a blocked cell between the two sides, a cliff face the player can see, which is the same thing Kiradex’s wall row does.724 So outdoors, 99.7% of Emerald’s adjacent walkable pairs on a land level and 99.8% of FireRed’s stand at one level.4

Elevation 15: the bridge value, and rare

The multi-level value is rare. Thirteen of Emerald’s 441 layout files use it, 12 of them layouts some map uses, 523 cells in all, Route 110 alone 185; FireRed uses it in none of its 365.7 That agrees with the structures post’s “thirteen of 441 layouts.”25 What stands under elevation 15 in Emerald is about half bridge, 252 of the 523 cells (48.2%): MB_BRIDGE_OVER_OCEAN 201 cells, MB_CAVE 114, MB_NORMAL 81, MB_OCEAN_WATER 76, MB_BRIDGE_OVER_POND_HIGH 31, MB_BRIDGE_OVER_POND_MED 16 and MB_FORTREE_BRIDGE 4.7344 On my reading, the cave and water cells under 15 are the same idea away from bridges, ground a walker can be on at either of two heights; section 4 counts the bridges.

The walk rule, in two functions

The whole rule is two short functions in src/event_object_movement.c. Before a step, and after the cell’s own collision bits have been checked, IsElevationMismatchAt reports no mismatch if the walker’s elevation is 0, or if the target cell’s is 0 or 15; otherwise a different elevation is a collision.3 As each step begins and again as it ends, ObjectEventUpdateElevation returns without a change if either the cell entered or the cell left is 15. Otherwise it sets the walker’s currentElevation to the cell’s, including 0, and updates previousElevation, the value that picks the walker’s draw priority, only when the cell is neither 0 nor 15.3

The consequence is the whole trick of a stair. A walker who steps onto a transition cell takes elevation 0, and a walker at 0 has no mismatch with anything, so the next step may go onto either level. The stair does not join the two levels by being at either of them; it joins them by belonging to neither. The bridge is the opposite case: on a cell at 15 the walker keeps the height they arrived with, so the same deck is ground for someone who walked onto it from the high bank and nothing at all for someone who arrived from the water below.332

What a stair is in the data

A stair in Gen 3 is not a tile type. It is a small patch of transition cells that touches two land levels. Counted as 4-connected patches of walkable cells at elevation 0 touching two levels or more, Emerald’s outdoor layouts have 84 stairs, 169 cells; 73 of the 84 (86.9%) are 1 by 1, 1 by 2 or 2 by 1 cells (26, 26 and 21 of them), and the largest are a 3-by-4, a 5-by-3 and a 1-by-6 patch. They join levels 3 and 4 (57 stairs), 3 and 5 (17), 5 and 7 (4), 4 and 5 (4), 7 and 9 (1), and 3 and 7 (1). Four of the 84 are stairs to the walk rule and not to the eye: two-cell transition patches at the ends of bridges, on Route 110 at (21, 13) and (28, 91) and Route 120 at (7, 15) and (28, 15), where a deck stored at 4 meets a bank at 3; the first draft’s water filter had dropped the decks, and with them the second level those patches touch, and the engine’s test puts them back. FireRed has 30, 59 cells, 26 of them 2 by 1, joining 3 and 4 (20) and 3 and 5 (10).84

Emerald’s stairs carry no stair behavior. Their cells are MB_NORMAL (97), MB_SAND (56) or MB_NO_RUNNING (10), plus the four MB_BRIDGE_OVER_OCEAN cells at the Route 110 bridge ends, one MB_MOUNTAIN_TOP and one MB_BUMPY_SLOPE; the only behavior in the header with “STAIRS” in its name is MB_STAIRS_OUTSIDE_ABANDONED_SHIP, which MetatileBehavior_IsNorthArrowWarp counts as a warp. A stair in Emerald costs one ordinary step at the walk’s 16 frames a cell.834

FireRed’s do carry one: 49 of their 59 cells (83.1%) are MB_ROCK_STAIRS, and a step north off a rock-stair cell or south onto one, which is what PlayerIsMovingOnRockStairs tests, switches the player to PlayerWalkSlow or PlayerRunSlow. Replayed frame by frame from UpdateWalkSlowAnim and UpdateRunSlowAnim, that is 23 frames a cell walking instead of 16, 1.44 times as long, and 11 running instead of 8, 1.38 times.83564 The difference is 7 frames, about 0.12 seconds, on each step of a climb.4 On my reading, FireRed spends that tenth of a second to make a climb feel like one, and Emerald does not bother.

The rule, tested on every stair

The structures post pointed to a walk rule written for Kiradex in its engine dossier, for the day a map needs height: a canStep(to:height:) that allows a step onto the same height, onto a transition, or onto a bridge, and a height(after:was:) that returns the walker’s height “unchanged on a transition or a bridge.”1825 It reads like Emerald’s rule. It differs in one line: Emerald sets the walker’s elevation to 0 on a transition cell, and the sketch keeps the old one.318

Schematic of four cells in a row, elevation 3, 3, a stair at 0, and 4. Under Emerald's rule the walker's elevation reads 3, 3, 0, 4 and the last step is allowed; under the engine dossier's sketch it reads 3, 3, 3, and the step onto 4 is refused. Measured over every outdoor stair, Emerald's rule climbs 84 of 84 in Emerald and 30 of 30 in FireRed; the sketch climbs 0 of 114.

One stair, two rules; drawn by figures/make_figures.py from the rule test in gen3_elevation.txt.

measure_gen3_elevation.py tests both. For each of the 114 stairs it starts a walker on a cell of the stair’s lower level and searches breadth first over pairs of a cell and the walker’s elevation, under each rule in turn, to see whether any cell of the upper level beside the stair is reached anywhere in the map. Emerald’s rule climbs all 84 of Emerald’s outdoor stairs and all 30 of FireRed’s. The sketch climbs none, because a walker who reaches the stair at 3 is still 3 when it meets the 4 above it.10 The script records the first five failures in each game as examples: for Emerald, five stairs in Fortree City, and for FireRed, five in the Safari Zone’s east area, all between levels 3 and 4.10 Section 9 carries the corrected rule; the sketch was never built, and the engine dossier lists it as step 10 of its order of work, “only when a map uses them”, so nothing in the app is broken by it today.18

2. What a ledge is in the data

The name suggests a drop, and the art draws one: a lit surface over a darkening lip (section 3 measures it). The data says something else.

Gen 3: a behavior that names one direction

In Emerald a ledge is a metatile behavior, not a height. When the player pushes against a cell, GetLedgeJumpDirection looks up the facing in a table of four tests, MetatileBehavior_IsJumpSouth, IsJumpNorth, IsJumpWest and IsJumpEast, each of which matches one behavior, and returns DIR_NONE unless the cell’s behavior is the one for the direction of travel; when it is, the player gets COLLISION_LEDGE_JUMP, and the game counts the hop with IncrementGameStat(GAME_STAT_JUMPED_DOWN_LEDGES).312 The ledge check comes after the cell’s collision has been read and wins over it, and it has to: every one of the 1,023 cells in Emerald’s maps that carries a jump behavior is stored blocked, collision 1.1213 The header defines eight jump behaviors, north, northeast and northwest among them, and the four tests include a north jump, so the engine can hop north; no metatile in any of Emerald’s 70 tilesets carries one of the three north-going behaviors (0 of 232 jump metatiles), so no map asks it to.3429

The maps do carry two diagonal behaviors, MB_JUMP_SOUTHWEST on 44 cells and MB_JUMP_SOUTHEAST on 33. By their names and their art (section 3 measures six of them, drawn like the south ledges, a lit surface over a dark lip), they are corner pieces, where a ledge’s run ends or turns. No code reads them. Searched across the game’s src/ and include/, the four diagonal names appear in the header’s list and in one other place, a table of tile flags in metatile_behavior.c whose flag the source itself comments “Set but never read”; no test, no movement code, nothing else. With no ledge test that matches them, they fall through to their collision, and all 77 are stored blocked. So Emerald’s corner pieces are drawn corners that nobody hops: a solid end to a ledge, not a diagonal way down.1334 Crystal’s corners are different, as the Gen 2 section below shows: they hop. This post counts as an Emerald ledge cell only a cell the engine can hop, one of the four straight behaviors, 946 cells; the 77 corner pieces are counted apart wherever they appear. FireRed’s header defines only the four straight behaviors, and no FireRed metatile or map cell carries a value where Emerald keeps its diagonal ones.13

What stands under the behavior is the surprise. For every straight ledge cell with a cell on each side of it, measure_gen3_elevation.py reads three elevations: the take-off cell, the ledge cell and the landing cell.1

Stacked bars of take-off, ledge and landing elevations for straight ledge cells with cells on both sides. Emerald, 944 cells: equal take-off and landing in 784 (83.1%), led by 3-0-3 with 598 and 3-3-3 with 131; different in 160, led by 0-0-3 with 96, of which 132 have a transition cell on one side and 28 join two land levels, 22 of them 5-0-3 and 6 of them 3-0-5. FireRed, 1,042 cells: 3-0-3 904, 0-0-0 80, 0-0-3 58; equal in 984 (94.4%), and the 58 that differ all have a transition cell at the take-off.

Take-off, ledge and landing elevations of every straight ledge cell; drawn by figures/make_figures.py from gen3_elevation.txt.

In Emerald 784 of the 944 sit at elevation 0, and 784 have the same elevation at take-off and landing, 83.1%; the most common triple is take-off 3, ledge 0, landing 3, 598 times, then 3, 3, 3, 131 times, and 0, 0, 3, 96 times.14 The two 784s are different sets that happen to be the same size: 131 ledge cells stand at 3 between two cells at 3, and the cells at 0 include 96 whose take-off is itself a transition cell.1 In FireRed all 1,042 ledge cells are at 0, and 984 of them (94.4%) have equal take-off and landing elevations: 904 are 3, 0, 3, 80 are 0, 0, 0, and the other 58 are 0, 0, 3.14

The 160 Emerald cells that differ split two ways. 132 have a transition cell at the take-off or the landing, so one side of the hop belongs to no level at all: the 96 at 0, 0, 3 and 22 at 0, 3, 3 among them. Decoded cell by cell, 128 of the 132 have a take-off stored blocked, so no walker stands behind the ledge to hop it; the 4 with an open take-off all land on 3, and none is outdoors (two in Lavaridge’s gym, one in Fortree’s gym, one on Victory Road’s B2F). The other 28, 3.0% of the 944, join two different land levels: 22 are take-off 5, ledge 0, landing 3, and 6 are take-off 3, ledge 0, landing 5. The second-engine review found them in the output, and astra_ledge_triples.py decodes each: they stand in Lilycove City (8, among them the south ledge at column 48, row 9, whose take-off is MB_NORMAL at 5 and whose landing is MB_NORMAL at 3), on Route 115 (10), on Route 120 (2) and in the Safari Zone’s north and south areas (2 and 6), and all 28 have a walkable take-off and a walkable landing. FireRed has none: its 58 that differ all have the transition cell at the take-off.24

So the engine does not need a height to make a ledge, and it does not read one. The ledge test reads the cell’s behavior and never its elevation; the jump moves the walker two cells along an arc (section 3); and as it lands, ObjectEventUpdateElevation, the same function section 1 describes for a step, hands the walker whatever elevation the landing cell stores. On most ledges that is the height they left; on Emerald’s 28 that join two levels it is the other level; and on the 132 with a transition cell on one side it is whatever that landing stores, the ground’s 3 on 118 of them, the surf value 1 on the 12 on Route 118 whose landing is ocean water, 0 on one and 5 on one, though a walker takes it on only 4 of the 132, the indoor four that land on 3, since the other 128 have no open take-off.31230 Put plainly, a ledge is a one-way door in the walk graph wearing a cliff’s clothes, and the cliff is optional. That is the reading the homage post reached from the mechanic, that a one-cell drop “has no z axis, only a one-way edge in the walk graph”, and the data bears it out: the edge needs no z axis, and where the map happens to store one on each side, as on the 28, the engine takes the landing cell’s value without any rule of its own.271

Never up, mostly south

One hundred percent bars of ledge cells, the cells each engine hops, by direction in four games. Emerald, 946 cells: south 69%, west 18%, east 13%. FireRed, 1,042: south 92%, west and east the rest. Red, 758 on its overworld maps: down 94%. Crystal, 1,148 on 167 maps: down 84%, down corners, which hop, 5%, left 7%, right 5%. A note under the bars: Emerald's 77 corner pieces are not counted, because no code reads them and every one is blocked. No ledge in any of the four is crossed up the screen.

Which way the ledges face, all four games, counting the cells each engine hops; drawn by figures/make_figures.py from gen3_elevation.txt, r4_corner_cells.txt and gen12_ledges.txt.

No ledge in the maps read from any of the four games is jumped up the screen. Emerald has 946 ledge cells: south 657, west 169, east 120, north 0, and beside them the 77 corner pieces, 44 south-west and 33 south-east, which are not ledges.131 FireRed has 1,042: south 962, west 41, east 39.1 Red’s ledge table has 8 entries, 3 down, 2 left and 3 right, and its 34 maps on the OVERWORLD tileset hold 758 ledge cells: 709 down, 26 left, 23 right.536 Crystal’s 167 maps that the routes decoder reads hold 1,148 hop cells: HOP_DOWN 964, HOP_LEFT 76, HOP_RIGHT 56, HOP_DOWN_LEFT 30 and HOP_DOWN_RIGHT 22; its constants file marks COLL_HOP_UP and the two up corners “; unused”, and none appears in any map read, though the hop routine’s table would send a player up them like any other.51437 Straight south, or down the screen, is 69.5% of Emerald’s ledge cells, 92.3% of FireRed’s, 93.5% of Red’s and 84.0% of Crystal’s; with Crystal’s down corners, which hop, its share is 88.5%.4

Runs of about four

Ledges come in short runs. Emerald’s 233 straight runs and FireRed’s 189 both have a median of 4 cells; the longest is 17 in Emerald and 55 in FireRed.14 Of Emerald’s runs, 40 are a single cell, 38 two, 34 three, 31 four and 35 five, and only 18 are longer than 7.1 The routes post found the first routes laid out the same way: Emerald Route 101’s 13 ledge cells are three runs of four and one corner cell, and that corner cell is one of the 77 blocked corner pieces, so the hops on Route 101 are the twelve cells of the three runs.1713

Where ledges are: routes everywhere, towns in Kanto

By map type, Emerald puts 679 ledge cells on routes (21 of its 41 route layouts), 187 underground, 48 indoors and 32 in one city, Lilycove, 1 of its 9 city layouts; its 7 towns have none.13 The homage post counted every cell with a jump behavior, corner pieces included, and counted that way the figures are 726, 215, 48 and 34, which match its own; the 77 corner pieces are the whole difference.12713 FireRed is different. It puts 139 ledge cells in 7 of its 19 town layouts, Viridian 39, Pewter 35, Fuchsia 20, Cerulean 19, Celadon 14, Six Island 8 and Saffron 4, and 803 on 24 of its 57 route layouts, with 100 more underground and none indoors.1 Red’s Viridian (36), Pewter (27), Fuchsia (22), Cerulean (19) and Celadon (15) have them too.5 So a rule that towns have no ledges is Hoenn’s, not the series’. What the four games share is direction, not placement; section 6 says what that changes in an earlier post of this series.

What a ledge saves

A ledge earns its cell only if the walk round is long. For every straight outdoor ledge with land on both sides, measure_gen3_elevation.py searches the shortest walk from take-off to landing without jumping, four ways, under Emerald’s elevation rule, inside the ledge’s own map.19

Box summaries on a log scale of the shortest walk from a ledge's take-off to its landing without jumping. Emerald, 280 ledge cells with a way round: minimum 4, quartiles 6, 12 and 24, maximum 62; 269 of 549 have none. FireRed, 581 with a way round: minimum 4, quartiles 6, 10 and 20, maximum 170; 299 of 880 have none. A line marks the hop's 2 cells. Below, Kiradex's 17 drop places as stacked dots: 7 at 4 tiles round, 5 at 6, 3 at 8, one at 9.41 and one at 10.

The walk round against the hop, in Emerald and FireRed outdoors and on Kiradex’s terrace; drawn by figures/make_figures.py from gen3_elevation.txt and kiradex_elevation.txt.

In Emerald that covers 549 ledge cells. For 269 of them, 49.0%, there is no way round inside the map at all: the ledge is the only way from that side to the other without leaving the map. For the other 280 the walk round is 4 to 62 cells, quartiles 6, 12 and 24, against the hop’s 2; 175 of them are 10 cells round or more, 93 are 20 or more, and only 41 are 4 or less.194 FireRed has 880 such cells, 299 with no way round (34.0%), the rest 4 to 170 cells round, quartiles 6, 10 and 20.194 So among the straight outdoor ledges with a walk round, the median one in FireRed and in Emerald stands in for a walk five to six times its own length, 10 cells in FireRed and 12 in Emerald against the hop’s 2, and for half of the 549 measured in Emerald there is no walk round in the map at all.4 The count is cautious in three ways, which pull against each other: the search walks four ways, ignores people and objects, and does not leave the map, so a walk round through a neighboring map counts as none.20

Gen 1: a table of tile pairs, held down

Red has no ledge behavior. HandleLedges returns at once if a hop or a fishing cast is already under way or the current tileset is not OVERWORLD, then matches three things against the LedgeTiles table: the direction the player faces, the tile the player stands on, and the tile ahead. On a match it also needs the matching direction held on the pad before it simulates two presses of that direction, which carries the player over.36 So a Gen 1 ledge is a pair of tiles and a direction, eight entries in all, and only on the OVERWORLD tileset.536 The count above reads one 8-by-8 tile per cell, the lower-left, which is the routes post’s Gen 1 cell model.517

Gen 2: the lip, and corners that go either way

Crystal marks the cell the player stands on, the lip, rather than the cell beyond it: a collision byte in the ledge range (HI_NYBBLE_LEDGES). Its .TryJump routine, tried only after an ordinary step has been refused, reads wPlayerTileCollision, and that byte is the tile under the player: GetMovementPermissions fills it from the player’s own map coordinates, under the comment “get coords of current tile”, and the same byte is what .CheckTile reads to let a current or a waterfall carry the player off the tile they stand on. .TryJump then ANDs the player’s facing with a .ledge_table entry, so a corner lip, HOP_DOWN_RIGHT, hops down or right, whichever way the player faces.3738 Unlike Emerald’s corner pieces, Crystal’s corners are ledges. The routes post found that one sideways hop off a corner is the only hop on Route 32’s walk home.17

Crystal also draws cliff tops thinner than a cell. 1,417 of the cells read carry UP_WALL, a wall on the tile’s top side only, 7 carry LEFT_WALL and 5 RIGHT_WALL.5 The routes post describes how GetMovementPermissions refuses a step through the walled side of such a tile and a step in through it, and how on Route 32 they lengthen the shortest walk from 110 cells to 132 out and 128 home; this post’s count is of the same walls over all 167 maps read.175 On my reading, a one-sided wall is the other half of the same idea: an edge between two walkable cells that the walk cannot cross, drawn on the tile’s border instead of spending a whole cell on a face. A ledge is an edge crossed one way; a one-sided wall is an edge crossed neither way.

3. The hop: time, arc, shadow, dust and sound

If a ledge is an edge, the hop is what makes the edge feel like a drop. Every generation spends the same time on it and draws the same few things.

Two cells in 32 frames, in Red, Crystal and Emerald

measure_jump_timing.py reads the hop tables out of the source with regular expressions and replays them frame by frame.6

  • Red. PlayerJumpingYScreenCoords is 16 screen y values: 56, 54, 52, 50, 49, 48, 48, 48, 49, 50, 51, 52, 54, 56, 60, 60. _HandleMidJump reads one entry on each pass of OverworldLoop, which calls DelayFrame twice a pass, and the player moves two cells, because HandleLedges simulates two presses of the direction, each a step of 8 passes; so the two cells take 16 passes, 32 frames. Read from the code, the index stops before the sixteenth entry, so 15 are shown and the last, a second 60, never is; the script’s count, 16 entries at two frames each, gives the same 32. The player rests at y 60 and rises to 48, 12 pixels. The 32 frames are the movement. Once the walk counter has run out, _HandleMidJump calls Delay3, three frames of DelayFrames, and only then clears the held, pressed and released buttons, the index and the ledge flag, so Red’s hop holds the player at least 35 frames, 0.586 seconds, before the pad is read again: the 32 of movement and the 3 of cleanup.6393640414
  • Crystal. The jump step reads 16 offsets, two frames a tick: −4, −6, −8, −10, −11, −12, −12, −12, −11, −10, −9, −8, −6, −4, 0, 0, over 32 frames and 32 pixels, two cells, 12 pixels high at the top.642
  • Emerald. JUMP_DISTANCE_FAR lasts 32 frames and moves one pixel a frame, 32 pixels, two cells. Its height comes from sJumpY_High, read at timer >> 1, and peaks at −12 on frames 10 to 15. The table is identical to Crystal’s, entry for entry.63

So all three move the player two cells in 32 frames, 0.536 seconds, rising 12 pixels on a 16-pixel cell; that is the movement, and Red’s three-frame cleanup after it is the one cost beyond the movement traced here, since Crystal’s and Emerald’s landings were not followed past it.64 The hop does not change with the gait. Emerald’s PlayerJumpLedge always uses the far jump, and PlayerNotOnBikeMoving starts it as soon as the step ahead is a ledge and returns, before it ever reads the run button, so a running player hops in the same 32 frames; the routes post’s run search counts each hop as 32 frames at a walk or a run for that reason.1217 Two steps at a walk are also 32 frames, at the 16 frames a cell all three generations walk,17 so at a walk a ledge costs the time of the two cells it crosses and saves the walk round.64 Running is 8 frames a cell,17 so at a run the hop costs 16 frames more than running its two cells would, and saves time only where the walk round is longer than 4 cells: 239 of Emerald’s 280 ledges with a walk round, and 485 of FireRed’s 581.194

Height above the ground against time. The canon's hop, identical in Crystal and Emerald, steps through 16 offsets over 32 frames, 0.536 seconds, starting 4 pixels up, peaking at 12 and landing; the brief's proposed arc for Kiradex, dashed and shown at today's walk, rises from 0 to 10 texels and back over 0.5 seconds in whole-texel steps; at a run the brief crosses the same arc in two run tiles' time. The shadow stays on the zero line in both.

The canon’s hop table, and the arc the brief proposes; drawn by figures/make_figures.py from jump_timing.txt; the dashed curve is a proposal, not a measurement.

The shadow stays on the ground

Every generation draws a shadow under the hop and leaves it on the ground while the sprite rises. Red loads LedgeHoppingShadow, one 1-bit tile, into video memory and writes it into four sprite slots with the flips that make a round shadow.36 Crystal’s JumpStep spawns a shadow object for the jumper.42 Emerald’s InitJumpRegular calls DoShadowFieldEffect, and UpdateShadowFieldEffect places the shadow each frame at the walker’s y plus an offset; the hop itself lives in the sprite’s y2, so the shadow stays where the feet would be as the figure rises.315 The player’s shadow is SHADOW_SIZE_M, an image 16 pixels wide and 8 tall.16

On my reading, the shadow is what tells the eye the figure left the ground rather than walked up the screen. Without it, a 12-pixel rise on a top-down map reads as a step north.

Dust, and a sound

Emerald’s landing on plain ground starts FLDEFF_DUST through GroundEffect_JumpLandingDust: three frames of 16 by 8 pixels, 8 ticks each. A landing in tall grass or water starts their own effects instead.16 Each game plays a sound as the hop starts: SFX_LEDGE in Red, SFX_JUMP_OVER_LEDGE in Crystal, SE_LEDGE in Emerald.363712

How Emerald draws a south ledge

measure_ledge_art.py renders the 33 metatiles with a jump behavior in Emerald’s shared primary tileset, 27 straight ledges and 6 corner pieces (fourteen secondary tilesets carry 199 more, not rendered here), using tiles.png, the tileset’s palettes and metatiles.bin, and prints each pixel row’s mean luminance over the pixels the two layers draw. Every tile entry that draws a pixel uses palette 2, 3 or 5, all among the six a primary tileset owns (palette 0 appears only on the empty tile), so the render draws them in the tileset’s own colors, not borrowed from any one map’s secondary tileset. The render is derived from copyrighted art and is for analysis only; the chart below plots its numbers, and no game art appears in this post.43

Mean luminance of each of the 16 pixel rows of the 15 south-facing metatiles with a jump behavior in Emerald's shared primary tileset, 9 south ledges and 6 blocked corner pieces, one thin line per tile and a thick line for their mean: the top eight rows hold between 130 and 205, the mean between 163 and 176; from row 8 the values fall to their darkest at row 13 or 14, between 88 and 108, and rise a little at row 15.

How a south ledge is lit, as numbers; drawn by figures/make_figures.py from ledge_art.txt.

All 33 are layer type 1, Covered, which DrawMetatile puts on the map’s bottom and middle background layers, BG3 and BG2, at priorities 3 and 2. The elevation table gives a walker’s sprite priority as 0, 1 or 2, and on the Game Boy Advance a sprite whose priority equals a background’s draws on top of it, so the ledges draw under any walker whose priority comes from that table.433144345 On the 15 that face south (9 south ledges, and the 3 south-west and 3 south-east corner pieces, which section 2 shows are blocked and never hopped but are drawn the same way), the top eight pixel rows are the ground’s own surface, grass, sand or dirt, with row luminance between 130 and 205; the bottom eight rows are a rock lip whose luminance falls to its darkest at row 13 or 14, between 88 and 108, and lifts a little at the last row.434 The mean of the fifteen falls from 169 over the top half to 113 over the bottom half.4 The 18 west- and east-facing tiles show no such fall: their top half is between 14 points darker and 22 points brighter than their bottom half, against 37 to 89 points brighter on the south-facing ones.434

That is the look the homage post put on its “must not resemble” list for Kiradex’s drop: “a grass lip with a light top edge and a dark shadow line.”27 The mechanic is free to borrow; this drawing is not, and section 9 draws the drop another way.

4. Bridges, and height as a scene

Most bridges are ground

Emerald has 702 bridge cells across nine bridge behaviors in five families (the engine names eleven; MB_BRIDGE_OVER_POND_LOW and MB_UNUSED_BRIDGE occur in no layout a map uses): MB_BRIDGE_OVER_OCEAN 609, MB_BRIDGE_OVER_POND_HIGH 35 plus 4 cells on its two edge behaviors, MB_FORTREE_BRIDGE 27, MB_BRIDGE_OVER_POND_MED 17 plus 4 on its two, and MB_BIKE_BRIDGE_OVER_BARRIER 6. FireRed has no bridge behavior in any layout a map uses.9

Horizontal stacked bars of Emerald's bridge cells by behavior and stored elevation. Over the sea, 609 cells: 201 multi-level, 288 fixed at 4, 120 at 0 to 3. Pond high, 39: 31 multi-level. Log bridges, 27: 4 multi-level, 23 at 4. Pond medium, 21: 16 multi-level. Bike bridge, 6, all at 4. In all 252 of 702 cells, 35.9%, are multi-level.

Emerald’s bridge cells by stored elevation; drawn by figures/make_figures.py from gen3_elevation.txt.

Only 252 of the 702 (35.9%) are multi-level, at elevation 15; 329 sit at a fixed elevation 4, and the other 121 at 0, 1 or 3.94 The over-the-sea bridges split three ways: 201 cells at 15, 288 at 4 and 120 at 0 to 3.9 248 of the 252 multi-level bridge cells are on Routes 110, 119 and 120, where a surfer can pass under; the other 4 are Fortree City’s log bridges at the multi-level value, where a walker passes beneath (below, the Fortree sound). Among the eight layouts with the most elevation-15 cells, the outdoor ones are Route 110 (185), Route 120 (48) and Route 119 (22), and the others are caves, a Battle Frontier corridor and Victory Road.7 The structures post described the Route 119 case from Porymap’s manual, one bridge cell that lets a player walk across over a surfer passing beneath.2532 Of the other 450, the 329 at elevation 4 are decks at a fixed height that nothing passes under: 294 on Route 110, 23 of Fortree’s 27 log-bridge cells and 12 on Route 120. The remaining 121 are not decks. 69 are stored blocked, all on Route 110 (68 at 0 and 1 at 3), and GetCollisionAtCoords refuses a step onto a blocked cell before it reads any elevation; 47 are open cells stored at the surf value 1 (46 on Route 110, 1 on Route 120), the bridge behavior over cells at water’s height, which a surfer at 1 may enter and a walker at 3 or 4 may not, since IsElevationMismatchAt refuses a cell whose stored elevation differs from the walker’s unless the walker is at the transition value or the cell is at the transition or multi-level value; 4 are the transition cells at the ends of two Route 110 bridges that section 1 counts as stairs; and 1 is an indoor cell at 3, in the Union Room. On my reading, a bridge over water nobody swims in is ground drawn as planks, and the data stores the 329 that way.9303

Drawn in two layers, sorted by a table

Of the 702 bridge cells, 685 are layer type Normal and 17 Covered.94 The overworld draws the map on three backgrounds, BG1 at priority 1, BG2 at priority 2 and BG3 at priority 3, and DrawMetatile puts a Normal metatile’s bottom layer on BG2, the middle, and its top layer on BG1, the top, under a comment that says it “covers object event sprites”.3144 Who draws over the deck comes from a sixteen-entry table indexed by the walker’s elevation, sElevationToPriority = {2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 0, 2}: a walker at an even elevation from 4 to 12 draws at sprite priority 1, and a surfer at 1 at priority 2.3 The tie is settled by the hardware, not the game’s code: GBATEK, the standard technical reference for the Game Boy Advance, says that when a sprite’s priority equals a background’s, the sprite “is displayed on top of that BG layer”.45 So the walker at 1 draws over the top layer too, and the surfer at 2 draws over the middle layer and under the top layer, where a Normal deck’s upper art sits. The same deck draws over a surfer and under a walker on it, without the deck knowing which.

How high a bridge is reads below it

Emerald tells the player how high a pond bridge stands by the reflection. On a pond bridge the walker’s reflection in the water drops below them by a value of bridgeReflectionVerticalOffsets: 12, 28 or 44 pixels for the low, medium and high types, and the reflection is loaded with a dark palette instead of the walker’s own.15 Only 28 and 44 occur in play. MetatileBehavior_GetBridgeType marks the low type “(Unused)”, and no layout a map uses carries it; the medium and high types are Route 120’s, by the same function’s comments. The bridges over the sea, the 609 MB_BRIDGE_OVER_OCEAN cells, return type 0, which gets no offset and the walker’s regular reflection.33915 The source explains it for the high bridge on Route 120: “the reflection is a solid dark blue color. This is so the sprite blends in with the dark water metatile underneath the bridge.”15 The code loads that dark palette for the medium pond bridge as well as the high one, not for the high one only.15

Fortree’s log bridges answer the step. The plank under the player is drawn lowered and the one just left springs back over a 16-frame timer, and SE_BRIDGE_WALK plays only when the player’s elevation is even, which the code’s own comment glosses as “Make sure player isn’t below bridge”; a walker beneath makes no sound.46 The source also notes, in a comment beside a BUGFIX switch, that the plank is not lowered on the first step onto a bridge from anything other than another plank.46 On my reading, these are the two ways a top-down game shows height without a side view: what happens under the thing (a reflection pushed further down) and what happens on it (a plank that gives and a sound only the deck makes).

Height as a scene: the cable car

When Emerald needs a big change of height it stops walking altogether. The cable car between Route 112 and Mt. Chimney is its own scene. Replayed from src/cable_car.c, the car moves 0.14 and 0.067 pixels a frame across and up, a slope of 0.48; the weather turns from sun to ash at frame 350 going up, and from ash to sun at frame 265 going down; and the fade out starts at frame 570, 9.54 seconds, before the warp onto the summit.6474 On my reading, a mountain is too tall for the tile grid’s honest height of one or two levels, so the game makes the climb a short film with its own weather, which is a design choice a collecting town could borrow for any trip that is more than a step up.

5. The SNES and the modern references

The structures research read these games for its own question, how tall things stand; this section re-reads them for this post’s question, how a walker changes height, with the sources saved again for this post. None of it is measured here; it is each source’s own words or code.20

Final Fantasy VI: two z-levels and a transition flag

Final Fantasy VI keeps one z-level for the party, upper or lower, and two flags per tile, “passable on lower z-level” and “passable on upper z-level”. The disassembly’s notes on field memory add that “if both of these are set, this tile can be a transition between upper and lower”, and that the sprite-priority flags are “not active for bridge tiles”. Stairs are two more flags, “tile uses up/left movement (stairs)” and “up/right movement (stairs)”.48 On my reading, those two make a sideways step on a stair climb on the diagonal, and the whole is Emerald’s design with two levels instead of sixteen: a tile walkable at both heights is the transition, and the bridge tile switches off the drawing rule that would otherwise put the walker under the deck.

A Link to the Past, as the snesrev zelda3 reimplementation writes it, keeps a dungeon’s tile attributes in two planes. In its player code, the check of where a pushed block would land reads dung_bg2_attr_table[(y & ~7) * 8 + (x & 0x3f) + (link_is_on_lower_level ? 0x1000 : 0)], and the hammer’s splash test adds the same 0x1000 when Link is on the lower level, so the same position is a different tile on each level.49 Dungeon_HandleLayerChange sets link_is_on_lower_level = 1 for an in-room staircase unless its kind is 2, and another staircase path flips it.49 I read only the player code saved for this post, not the reimplementation’s tile detection, so where else the two planes are read is not checked here. That is reimplementation code with no prose source, and I read it only for the shape of the idea: the walker carries the level, and the map answers differently for each.

CrossCode: height matters, jumping does not

Radical Fish Games built CrossCode on real height, and its developers wrote down what that costs. Height, they wrote, “is definitely an important part of CrossCode, jumping is not.” Their auto jump “jumps at the last possible moment in front of the gap”.50 Their pathfinding marks “jump-up-edges” by hand, where the level designer says a climb is possible, and computes “jump-down-edges” automatically.51 A reader in the comments of that post suggested marking heights with more distinct colors, and the team’s lachsen answered on October 4, 2013: “That level was pushing the whole 3D situation a bit too much.” And: “For future environment we’ll use different colors to mark the heights more explicitly.”50 The structures research also read CrossCode’s community map editor, which draws each level’s wall face as level.height / 16 tile rows; that source was read for the structures post and not saved again for this one.26

This is the warning the structures research refused ledges on: free height is hard to read top-down.26 On my reading, the same posts carry the other half of the lesson: a jump down is an edge the engine can compute, and a jump up is a decision someone makes per place. The four games measured here never make that decision at all: no ledge in the maps read goes up the screen (section 2).15

Sea of Stars: away from tiles on purpose

Sabotage Studio’s Thierry Boulanger told Screen Rant in August 2023 that the game’s second pillar was “unshackled traversal. The idea that you can just hoist up, jump down off of everything,” and called it “going as far away as possible from tile-based movement”. The levels, he said, had “to all read well with different levels of height, with the light and everything, and that you still know where to go.”52 That is one interview and the designer’s own account. I read it as the far end of the spectrum from Kiradex: free climbing is a game’s pillar there, and the cost it names, reading height with light, is the same cost CrossCode’s team named.

Eastward

The structures research found no developer statement on Eastward’s elevation system, and this post’s search for one could not run. I cite nothing about it.2026

6. Kiradex’s terrace, measured

Everything in this section is measured on the town as it ships: the forge’s export Kiradex/Resources/World/town.json in the Kiradex repository, 40 by 30 tiles, the arrival at column 19, row 13, the file dated October 3, 2026, read only.1124 The walk is the app’s own: TileMap.path searches eight ways, a diagonal step costs √2 and is allowed only when both tiles it passes between are walkable, so nobody cuts a wall’s corner. That is the walking contract the routes post set for the app and the server, and every length below is a cost on it, in tiles.5317

Two levels, drawn

The wall is row 11 of the town: 29 blocked tiles and five flights of stairs, at x 3 (one tile wide), 10 (one), 17 (the grand stair, five wide), 28 (one) and 36 (one). The upper level has 216 walkable tiles and the lower 482.11 A flight comes every 7 or 8 tiles: measured from each flight to the next, from the grand stair’s east edge going east, they are 7, 7, 7 and 8 tiles apart, with 6, 6, 6 and 7 tiles of wall between them and 2 more at each end.4 In the forge’s own letters the wall is W, “the terrace’s wall: the upper town stands a step above the lower, and this is the face of that step, seen from the lower side”, and a stair is /, “a stair through the wall (plaza stone to the feet)”; in the exported letters the app and the server read, the wall’s tiles are blocked and the stairs are paving.24

Nothing about the walk changed with the terrace. From the arrival the four upper doors are 18.07, 10.07, 8.24 (the hall) and 16.49 tiles away, and the three lower doors 20.07 (the shop), 12.41 and 13.41; each walk is the same length back, as every walk on a graph with no one-way edge is.11 Each of those walks is 7 steps or more, and the app runs any path of 6 steps or more, at runPace, 1.6 times the walk’s 4 tiles a second, a nominal 6.4.54 So in today’s code the hall is about 1.3 seconds from the arrival and the shop 3.1; walked, they would be 2.1 and 5.0.4 Every time in this section is today’s code at that nominal run. The motion post’s model of the same code at 60 hertz finds the run slower than its constant, 6.00 tiles a second on straight steps, because each tile’s overshoot is thrown away, so these times are lower bounds.55

Where a drop could go, and what it would save

Schematic of row 11 of Kiradex's town, 40 tiles: the fence at each end, 29 wall tiles, and the five flights at x 3, 10, 17 to 21, 28 and 36. Above it, bars for the 17 places where a drop's take-off and landing are both walkable, the walk round by the stairs from 4 to 10 tiles, and labels of 0.59 tile at x 8, 9, 16 and 22, the only places where a drop shortens any trip between an upper door and the arrival or a lower door.

The terrace wall, the places a drop could go, and what each would save; drawn by figures/make_figures.py from kiradex_elevation.txt and the wall row of town.json.

measure_kiradex_elevation.py models a drop as the canon’s ledge: a directed edge from the take-off tile on row 10 straight south over the blocked wall tile to the landing tile on row 12, cost 2, and nothing climbs it.11 There are 17 places where the take-off and the landing are both walkable: x 1, 2, 4, 5, 6, 8, 9, 16, 22, 29 to 34, 37 and 38. Without a drop, the walk round from take-off to landing by the nearest stairs is 4 to 10 tiles: 4 at seven of them, 10 at x 32, the farthest from a flight.11

Then the script adds one drop at a time and walks every trip from each of the four upper doors to the arrival court and to each of the three lower doors, 16 trips. A drop at x 8 or x 9 shortens two of the 16 trips by 0.59 tile each; a drop at x 16 or x 22, beside the grand stair, shortens one by 0.59; the other 13 places shorten none.11 Runs of drops at x 4 to 6 and at x 30 to 33, the long blank stretches of wall where, on my reading, a terrace drop would look most natural, shorten no trip and change none of the 16 walks back up.11 Every trip a drop shortens is 19 steps or more, so it is run, and at the nominal run, with the drop crossed at the run’s pace as the brief’s item 4 sets it, 0.59 tile is about 0.09 seconds.4

Two variants probe the obvious alternatives. Turning the two outer one-tile flights, at x 3 and x 36, into drops saves nothing going down, because a drop replaces the stair exactly, and adds 4.83 tiles to one walk up, the walk from the shop’s door to the house above it, 18.83 tiles today and 23.66 with the flight gone; removing those flights with no drops at all, as a control, costs the same 4.83 both ways.23 Giving the court’s flower beds either side of the grand stair back to paving, and putting drops above them, saves 2.93 tiles over the 16 downward trips, of which 2.34 come from the paving alone, which saves the same 2.34 on the way up.23 So the most any drop in the Square buys is 0.59 tile on a trip, about 0.09 seconds at a run, against the median outdoor walk round of 10 to 12 cells in FireRed and Emerald (section 2).1119 The Square already has what a ledge is for: stairs close enough that no trip goes far round.

The walkable roof row

Emerald lets a walker step onto a building’s top roof row and be drawn behind the ridge; the structures post listed that as missing in Kiradex, “the layer would draw it correctly, the letters forbid it.”25 Kiradex’s seven buildings have 37 top-roof-row cells, 5 each and 7 for the hall, and all 37 would be reachable from the arrival if their letters were walkable.114 For every building the depth rule already puts a walker on that row behind the building: the four upper buildings have their top row at row 1 against bases at rows 5 and 6, and the three lower at rows 14 and 16 against a base at row 20.1153 Opening them shortens 8 door-to-door walks by 0.59 tile each, all of them by walking behind a ridge: the house at (5, 6) to the lower door at (24, 20), for one, goes from 31.49 tiles to 30.90, and the longest of the eight, the upper door at (31, 5) to the shop, from 35.97 to 35.38.1123

A bridge over the pond

The park’s pond spans x 2 to 7, rows 23 to 27. A north-south footbridge at x 4, five water tiles long, turns the walk from (4, 22) to (4, 28) from 12.83 tiles into 6.00, 53.2% shorter, and at today’s nominal run, since both walks are runs (12 steps and 6), about 2.0 seconds into 0.9; at x 5, also five water tiles, from 10.83 into 6.00. The other columns: x 2, three water tiles, 18.24 into 4.00; x 3, four tiles, 15.83 into 5.00; x 6, four tiles, 8.41 into 5.00; x 7, two tiles from (7, 23) to (7, 26), 5.00 into 3.00.114 Nobody swims in Kiradex, so the deck is ground (section 4).

The Meadow Walk: a gate or a row of drops

The routes post got its shorter way home from a hedged lane with a one-way gate and left one-way drops to this post.17 Its numbers stand as published: on the shared eight-way graph, with four hedges across the meadow, the way home from the Lakeside pier to the arrival is 88.07 tiles, the brief’s outward band is 110 to 120 tiles, and 4,111 four-hedge layouts fall inside that band, every one with the way home at 0.73 to 0.80 of the way out.17

Two schematic plans of the routes brief's 24-by-60-tile meadow at one sampled set of gap positions, 18, 2, 15 and 8. Left, the hedge-gate model: four hedges with 2-tile gaps and a hedged lane on the east side whose gate admits walkers only from the north; outward 59.41 to 85.43 tiles over the 400 sampled layouts, this one 76.77, homeward 59.00. Right, the drop model: the hedges become terrace walls with their gaps kept as stairs and a 2-tile run of one-way drops at the lane's columns; the same walks on the meadow alone, a difference of 0.00 both ways in all 400 layouts sampled. A line beneath adds the joined-grid result: home 88.07 under both, and the walk out shorter with drops on 114 of the 400.

The Meadow Walk with a gate and with drops; schematic drawn by figures/make_figures.py from the layout constants and output of probe_meadow_drops.py, the first of its 400 sampled layouts, with the joined-grid line from astra_meadow_joined.txt.

probe_meadow_drops.py asks whether drops can do the gate’s job. It models the meadow alone, 24 columns by 60 rows, edge to edge, with the routes brief’s four hedges at the meadow’s rows 12, 24, 36 and 48, each with a 2-tile gap. In the gate model, column 21 is the lane’s hedge, columns 22 and 23 the lane, entered only from the north edge, never left northward, and open to the meadow only at its south end. In the drop model the four hedges become terrace walls across the full width, each keeping its 2-tile gap as a stair, the lane’s hedge is gone, and each wall has a 2-tile run of drops where the lane was, columns 22 and 23: from the tile above, a straight step south lands two tiles down for cost 2, and nothing climbs them.21 It walks both on the app’s eight-way graph, outward from the south edge to the north and homeward from the north to the south, for 400 layouts of the four gap positions drawn with a seeded random generator (seed 6) from the 160,000 the routes post swept, 0.25% of them.214

On the meadow alone the two models give exactly the same walks. Homeward is 59.00 tiles in every layout under both; outward is 59.41 to 85.43 tiles, median 66.80, under both; and the difference, drops minus gate, is 0.00 both ways in all 400.21 The drops need no lane hedge and no gate. Equal in tiles is equal in seconds only if a drop takes its two tiles’ time at the walker’s gait, and the way home, 51 single steps and 4 drops, is always run; section 9’s item 4 settles that on these same 400 layouts.4

The first draft of this post read that result as settling the full route too, on the reasoning that the drops sit in the lane’s columns and the rest of the route is unchanged. The second-engine review showed the reasoning wrong, and the measurement that replaced it stands here. Joined to the Square and the Lakeside, as the routes post’s measure_meadow_gate.py joins them, the drop design opens the meadow to the Square along all 24 of its columns, because the lane hedge is gone, and the cheapest way out of the Square can change. astra_meadow_joined.py puts the drops on that joined grid and walks it from the arrival to the pier and back.22 On the layout the review named, gaps 19, 1, 1 and 17 at the brief’s offset of 4, the walk out is 114.15 tiles with the gate and 111.67 with drops, 2.49 shorter, because the outward route enters the meadow at the Square’s column 26, under the old lane, instead of column 11; the way home is 88.07 under both.224 Over the probe’s 400 sampled layouts the way home is 88.07 on every one under both models, and the walk out is shorter with drops on 114 of the 400 and longer on none; 17 of the 400 sit inside the routes brief’s bands with the gate, a meadow winding of 78 to 90 and a walk out of 110 to 120, and on 4 of those 17 the drops change the walk out, by 1.66 to 3.31 tiles, all four still inside the band, with the way home at 0.745 to 0.789 of the way out.224 Over all 160,000 gap positions, walked on the joined grid with drops, the way home is 88.07 on every one and the walk out runs from 89.73 to 134.44 tiles. Held to the routes brief’s own bands, the winding and the walk out, the drop design accepts 4,607 layouts, all at or under the 0.8 target, the way home at 0.734 to 0.800 of the way out. The gate’s 4,111 are not simply among them: walked with drops, 3,076 of the 4,111 keep their walk out, 1,035 come out shorter, by up to 5.31 tiles, and none longer; 4,103 stay inside the band and 8 fall just under 110, to 109.67; the other 504 of the 4,607 are layouts the gate walked out past 120 that the drops bring inside.224 So the two designs agree on the way home and on the target and differ on which gap positions pass, and the brief’s check 2 is written to the drop design’s own numbers, not to the gate’s. This post’s ledge counts also agree with the routes post where they overlap: Red Route 1 has 42 ledge cells in both posts’ scripts, and the hop is 32 frames in both.5176

What the data narrows in two earlier posts

Two sentences already published in this series say more than the measurements here support. I am not editing those posts; I am stating the findings once, here.

The structures post answered a question about multi-floor buildings with “Reserve per-cell elevation for terraces, ledges and bridges on the ground, where Emerald uses a transition value for stairs and a multi-level value for a bridge cell.”25 It holds where a tile is walkable at two heights, a walkway over a path. It does not hold for ledges or for most bridges, and Kiradex’s own terrace, a blocked face with stairs through it, shows that a terrace drawn that way needs none either. A ledge needs no per-cell elevation: in FireRed every ledge cell is at the transition value and 94.4% of the straight ledge cells with a cell on each side join equal elevations, and in Emerald 83.1% do; a ledge is a directed edge.1 And a bridge needs elevation only where someone passes under it: 252 of Emerald’s 702 bridge cells are multi-level, 329 of the other 450 are decks at a fixed elevation 4, ground drawn as planks, and the remaining 121 are cells stored blocked, cells at water’s height, four bridge-end stairs and one indoor cell (section 4).930 The engine dossier’s (cell, height) sketch that the post points to also needs the correction in section 1 before it can climb a stair.10

The homage post said of ledges, “The town, where people live and the player arrives, never has one.”27 That is true of Emerald, whose 7 town layouts have no ledge cell, and the homage post’s Emerald counts agree with this post’s when counted its way, corner pieces included (section 2).113 It is not true of Kanto: FireRed has ledge cells in 7 of its 19 town layouts, 139 in all, and Red in Viridian, Pewter, Fuchsia, Cerulean and Celadon, 119 cells across the five.154 The decision the homage post drew from it, no drops in Kiradex’s town, still stands in this post’s brief, but on Kiradex’s own numbers (the 0.59 tile above), not on a rule the canon does not keep.

7. The craft, as rules with numbers

Each rule below but the last is a measured fact from sections 1 to 6 with the design reading I take from it. The numbers are measured in the games each row names, Emerald and FireRed for most, all four where the row says so; the readings are mine. The last row, the fold, is different in kind: its facts are Apple’s documentation, and its rule is my proposal from section 8, which no capture has tested yet.

Element Rule Source
Levels One level is the norm, two is a feature, three is a showpiece. 50 of Emerald’s 68 outdoor layouts and 67 of FireRed’s 76 use at most one land level; FireRed never uses three. Kiradex’s Square has two and needs no third. Section 17
Cliffs Height changes across a face, not across a number. Outdoors, 99.7% (Emerald) and 99.8% (FireRed) of adjacent walkable pairs on a land level stand at one level. Draw a level change as a blocked face with a stair through it, which build 35 already does. Section 1724
Stairs A stair is mostly one or two cells and costs a step. 73 of Emerald’s 84 outdoor stairs are 1 by 1, 1 by 2 or 2 by 1; Emerald walks them at 16 frames a cell, FireRed’s rock stairs at 23. Kiradex’s flights are one tile deep; keep the walk speed on them. Section 186
The walk rule On a stair the walker belongs to no level. Emerald sets the walker’s elevation to 0 on a transition cell, which is why the next step may go onto either level; a rule that keeps the old height blocks all 114 outdoor stairs of Emerald and FireRed. Section 1310
Ledges A ledge is a one-way edge that needs no height. 83.1% (Emerald) and 94.4% (FireRed) of straight ledge cells with a cell on each side join equal stored elevations; 28 of Emerald’s 944 join two land levels and none of FireRed’s do; in FireRed every ledge cell is a transition cell. The engine reads the cell’s behavior, never its elevation, and hands the walker the landing cell’s. Model it as an edge in the walk graph, not as height. Section 2123
Direction Ledges go down or sideways, never up, and mostly south. No ledge in the maps read from four games goes up the screen; straight south is 69.5% to 93.5% of each game’s ledge cells, counting the cells each engine hops. Emerald’s 77 diagonal corner pieces are drawn and blocked, not hopped; Crystal’s corners hop. Section 215
Placement A ledge earns its place where the walk round is long. The median outdoor walk round in FireRed and Emerald is 10 to 12 cells against a hop’s 2, and half of the 549 straight outdoor ledge cells measured in Emerald have none in their map; on a map with stairs every 7 or 8 tiles a drop saves under a tile. Sections 2 and 61911
Runs Runs are about four cells. The median straight run is 4 in Emerald and in FireRed. Section 21
The hop The hop takes the time of two walking steps, at any gait. 32 frames of movement for two cells, 0.536 seconds, in Red, Crystal and Emerald (Red adds at least three frames of cleanup before the next input), 12 pixels high on a 16-pixel cell; in Emerald a runner hops in the same 32 frames, twice the time of running two cells. At Kiradex’s walk of 4 tiles a second, two tiles are 0.5 seconds. Section 9 keeps the walking half of this rule and says why Kiradex’s drop does not keep the any-gait half. Section 361254
The shadow The shadow stays on the ground. Red, Crystal and Emerald each draw one during the hop and keep it at ground level while the sprite rises; Emerald adds a three-frame landing puff. Section 336421516
Legibility A one-way edge must look one-way from both sides. The shared primary tileset’s 15 south-facing metatiles in Emerald light the surface on top and darken the lip toward its bottom rows (the secondary tilesets were not rendered); CrossCode’s team, told its heights were hard to read, said it would mark them by color. The drawing, not a sign, carries the rule. Sections 3 and 54350
Bridges Use multi-level cells only where someone walks under. 35.9% of Emerald’s bridge cells are multi-level, and they are where someone passes beneath: a surfer on three routes, a walker under Fortree’s log bridges. A deck over water nobody enters is ground. Section 49
Bridge height A bridge’s height reads below it and on it: on Route 120’s pond bridges a reflection 28 or 44 pixels down by bridge height (the code’s 12-pixel low type is unused, and the sea bridges get no offset), a plank that gives on Fortree’s log bridges, a sound only on the deck. Section 41546
Big climbs Big height changes are scenes, not tiles. Emerald’s cable car is a 9.5-second scene with its own change of weather. Section 4647
The fold The fold is real only half open. The division region is active when iPhone Duo is partially open and inactive when it is fully open, and Apple asks developers to find what sits in it and is hard to see or touch. My proposal, untested: a row nobody needs to touch, such as a wall’s face, is the only thing that belongs there. Section 8, a proposal5657

8. The Apple way: a walker that lifts, a graph with one-way edges, and the fold

The engine under 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, every material unlit and cut-out.58 Nothing this post proposes needs a new framework. It needs three changes inside code that exists, and one reading of an API the app already calls. None of it has been built or timed; each cost below is named and marked unmeasured.

Where a walker stands, and what a hop must not move

PlazaRig.place sets a walker entity’s position each frame from a ground point that advance hands it, a point on the straight line between the centers of the tile left and the tile entered: x and y rounded to whole world units, so walkers stand on whole pixels, and z from TileMap.depth(atWorldY:) of that ground point, which is 1 + (1 - y / (height × 16)) × 0.5, nearer the camera the lower on the screen a walker stands.5453 Objects such as buildings and trees are drawn at the depth of their base row less 0.001, so a walker on a row behind a building’s base is hidden by it and one on the base row stands in front.53 That one function decides who draws over whom in the whole town, which is why the walkable roof row in section 6 needs no engine change.11

The walker’s shadow is a 12-by-4 ModelEntity plane added as a child of the walker entity, placed under the feet a hair behind the figure.54 The walker entity is the figure itself: the character sheet’s frame is that entity’s own material, and the code’s comment calls the shadow “The blob under the feet, a child of the figure.”54 So anything that lifts the figure lifts the shadow with it. A hop built by adding the arc to the walker entity’s y would carry the shadow into the air, the one thing Red, Crystal and Emerald all avoid (section 3), and would also put the walker at the wrong depth if z were computed from the lifted y. So the hop has two rules that are about structure, not art: compute z from the ground point before adding any lift, as Emerald keeps its arc in y2 and its ground position in y; and keep the shadow on the ground point, either by moving the shadow’s local y down by the lift each frame or by giving the figure a child entity of its own to lift beside the shadow.1554 Neither rule holds anything still. A drop carries the walker two rows south, so the ground point, the depth taken from it and the shadow all move through the hop, as they do on any step; what must stay out of all three is the lift. The brief’s check 4 logs each of them against the ground point.

The walk itself advances a step’s progress each frame by dt × tilesPerSecond × pace ÷ length. tilesPerSecond is 4; the pace is runPace, 1.6, when the walker is running and 1 otherwise, and walk(to:) sets running for any path of 6 steps or more; the length is √2 for a diagonal step and 1 for anything else.54 So as the code stands, a drop’s step of two rows would get a length of 1 and cross in 0.25 seconds at a walk and 0.16 at a run, half the time of the two tiles it covers.4 The brief changes that one line so a drop’s length is 2 (section 9, item 4). Then a drop takes 0.5 seconds at a walk, 30 frames at 60 hertz, 0.933 of the canon’s 0.536, and 0.31 seconds at the run’s nominal 6.4 tiles a second.4 Those are nominal figures, distance over speed. advance adds each frame’s increment to a progress value and discards the overshoot when a step completes, so the rig’s own arithmetic runs a little slower than its constants: replayed in Float at 60 hertz, a straight run step is 10 frames, not 9.375, a diagonal 14, and a two-tile drop 19 frames, 0.317 seconds, against the 20 frames two run steps take; at a walk a step is 15 frames and a drop 30, the nominal figures exactly. That is the same 10-frame run step the motion post’s model of this code found, 6.00 tiles a second where the constant says 6.4.54554 If the motion post’s brief lands, a walk of 1 pixel a tick and 16 ticks a tile and a run of 2 pixels a tick and 8 ticks a tile at 60 hertz, the same rule makes a drop 32 ticks at a walk, the canon’s frame count, and 16 at a run.554

One-way edges in the walk graph

TileMap.path is a cheapest-first search over eight moves, a diagonal costing Float(2).squareRoot() and skipped unless both tiles it passes between are walkable.53 A drop is one more move: from a take-off tile, an edge to a landing tile two rows down, cost 2, and no edge back. In the code that is a dictionary from take-off to landing, read from an optional drops key in the forge’s export, and two lines in the loop that add the edge when the tile being expanded is a take-off. The search needs no other change, because a cheapest-first search already handles edges of different costs; the routes post’s gate script models its gate that way, and this post’s probe and Kiradex script model the drops that way.172111

The server is the harder half. The client sends one move message per tile stepped, ["t": "move", "tile": [tile.x, tile.y], "facing": facing].59 The server accepts a move if the destination tile is walkable, with no check that it is next to the last one; the only other checks on a move are a valid facing and a rate limit.59 So today’s server would accept a landing two tiles from the take-off without knowing a drop exists, and would equally accept a jump back up. Its own Plaza.path searches four ways, though its docstring calls it “the same walk the app takes”.59 The routes post’s brief already moves the server to the client’s eight-way graph; this brief adds the drops to that graph and asks the server to check that each move is a step or a drop, which is the parity the routes brief’s check 12 tests.17

The fold: two APIs, and one row that may sit under it

iPhone Duo folds, and when it is half open the fold crosses the view. Apple gives SwiftUI two pieces for it. GeometryProxy.reservedRegions(kind:options:layoutDirectionBehavior:) “Returns an array of reserved regions that match the selection options you specify”, and one kind of region is “An area where content splits into separate regions, such as at the fold of a hinge.” Its documentation page lists iOS 27.1 and iPadOS 27.1, marked beta, and Mac Catalyst, macOS, tvOS, visionOS and watchOS 27.1.57 View.onHingeChange(isEnabled:_:) “Adds an action to perform when the hinge context of the view hierarchy changes,” with the same platforms.60 Apple’s guide to preparing an app says when the fold matters: “a reserved region that represents the fold is active when iPhone Duo is partially open, but inactive when it is fully open.” The same page asks developers to “Identify elements or controls in your views that appear in the fold, and are difficult to see or interact with.”56 And the Human Interface Guidelines: “Avoid extreme layout changes as people fold the device.”61

Kiradex already reads both. Fold.read asks for reservedRegions(kind: .division) and takes the first active one, behind #available(iOS 27.1, *) and a compile-time check for the 27.1 SDK, with the comment “Reserved regions are in the 27.1 SDK only; a build from the 27.0 SDK the App Store takes sees no fold”.62 A HingeReads modifier counts onHingeChange callbacks and, after each, reads the region again four times, sleeping 0.1, 0.4, 1.0 and 2.5 seconds in turn, so the reads land about 0.1, 0.5, 1.5 and 4.0 seconds after the callback, because the region “arrives a few layouts after the hinge moves”.624 And the camera’s follow keeps the player at the center of the wider side of the fold, not of the view.54

For a terrace the fold adds one consideration. Half open, a band of the town lies under the fold, and the things a collector most needs to see or tap there are doors, stairs, a drop’s take-off and their own figure. A wall’s face is the one row of a terrace nobody needs to touch. On my reading that makes a terrace wall the natural thing to let the fold cover when the camera has settled, and nothing to chase while the collector walks, since the HIG asks for no extreme layout changes as the device folds. That is a proposal, and the brief’s check 8 tests it.

No iPhone Duo was at hand for this post. The fold check is a capture on the iPhone Duo simulator, whose Device Hub offers Closed, Book and Open poses; this series’ simulator post found an inactive division 40 points wide down the middle of the open display “that turns active in the Book pose.”63 Whether the hardware reports the same region at the same moment is unverified until a device is in hand.

What it costs, and what is not measured

Nothing in this section has been timed. A hop adds one quad’s offset and one shadow’s offset per frame for one walker; a drop adds one edge per take-off to the search the rig already runs to plan each walk;54 a walkable roof row is a new letter. Their frame-time cost remains unmeasured; the brief’s checks measure the behavior, not the cost. The first post’s capture rule applies to every capture the brief asks for: on the simulator, RealityKit frames are faithful only when captured from inside the test bundle.58

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

Author synthesis. What follows is my proposal, derived from sections 1 to 8 and written as a diff against what ships today, read at Kiradex commit 334fbfe on October 5, 2026 (the app’s working tree was being rewritten that day, so every line this section cites is that commit’s): build 35’s two-level town (town.json of October 3, 2026), TileMap, PlazaRig, the plaza server, and the routes post’s brief for the Meadow Walk.2017 It names and draws nothing from any Pokémon game. Where it borrows a mechanic, the rule in section 7 says from where; the look is Kiradex’s own, and the homage post’s “must not resemble” list holds: no “grass lip with a light top edge and a dark shadow line,” not the canon’s hop curve, not its sound.27 Every length is a cost on the app’s eight-way walk, in tiles, and every time names its pace: today’s code walks 4 tiles a second and runs at 1.6 times that, a nominal 6.4, on any path of 6 steps or more; the motion post’s brief, if it lands, walks 16 ticks a tile and runs 8 at 60 ticks a second, 3.75 and 7.5 tiles a second.535455 None of it has been built.

The ledge decision, and what changed since the structures research

The structures research refused ledges because free height is hard to read top-down, which is CrossCode’s warning in its developers’ own words (section 5).2650 Two things have changed since.

First, the data shows that a ledge needs no height. It is a one-way edge that usually joins two cells at the same stored elevation: 94.4% of FireRed’s ledges and 83.1% of Emerald’s straight ledge cells with a cell on each side join equal elevations, FireRed stores every ledge cell at the transition value and none of its ledges joins two land levels, and the 28 Emerald ledges that do cross a level get it from the landing cell, not from any rule of the ledge’s (section 2).12 So a drop costs the engine one directed edge, not a z axis, and the refusal’s reason, free height, does not apply to it. Second, the routes work found the one job that only something one-way can do: on a grid that can be walked both ways the shortest walk back is the shortest walk out, so a shorter way home needs an edge that goes one way.17

So: drops, yes, as directed edges; per-cell height, still no. What stays refused is everything the original reason covered: climbing, free jumping, any drop up the screen, and per-cell height before some tile is walkable at two heights.

Where they go is not the Square. The Square’s flights already stand every 7 or 8 tiles, and a drop anywhere in its wall saves at most 0.59 tile on any door trip (section 6).11 The canon’s towns are no guide either way, since Hoenn’s have no ledges and Kanto’s do (section 6); Kiradex’s own numbers decide it.15 The drops go at the plaza’s edge, in the Meadow Walk, where they replace the routes brief’s hedge gate, keep its way home of 88.07 tiles, and shorten the walk out on some layouts, so the design is held to the routes brief’s bands rather than to the gate’s exact lengths (section 6, and check 2 below).2122

1. Drops as one-way edges in the walk graph

  • Data. The forge’s export gains an optional drops key, a list of take-off and landing tile pairs. TileMap reads it into drops: [SIMD2<Int>: SIMD2<Int>], take-off to landing. An export without the key behaves exactly as today.20
  • The edge. In path, a take-off tile gets one more move: to its landing tile, two rows down, cost 2. There is no edge back. A drop is entered only by a straight step in its direction; a diagonal step that would cross it is refused, as the canon’s hop only ever goes the way the player faces (section 2).620
  • The step. path returns tiles, so a walk that uses a drop carries it as one entry, the landing tile, right after the take-off: a step of (0, 2), which is what item 4’s change to advance keys on.5354
  • The wall. The wall cell between take-off and landing stays blocked. A drop never makes a cell walkable; it adds an edge over one.
  • Direction. South only. No ledge in the four games’ maps read goes up the screen (section 7, Direction), and on all nine routes the routes post charted, the walk toward the earlier town is the shorter one. Kiradex’s Meadow Walk runs north and south with home at the south end, so south is the way home.117

Acceptance check 1, drops are one-way. A unit test on a fixture map with one drop. path returns tiles, not a cost, so the test sums the step costs of the tiles it returns, 1 for a straight step, √2 for a diagonal and 2 for a drop: from above the drop to below it, the path uses the drop and the crossing sums to 2; from below to above, it does not use the drop; and the only drop step in any returned path is the (0, 2) edge from its take-off, so from the tile diagonally above the take-off the landing costs √2 + 2, never 2√2.

2. Terrace walls and drops in the Meadow Walk

  • Terrace walls. The four hedges the routes brief lays across the meadow, at its local rows 12, 24, 36 and 48, become retaining walls drawn with the Square’s own wall-face kit (props.wall_face in the forge), each keeping its 2-tile gap as a flight of stairs (props.stair). The hedged lane and its gate are dropped.1764
  • Drops. In each wall, a 2-tile run of drops where the lane was, the meadow’s columns 22 and 23, facing south toward the Square. Two tiles is half the median straight run of four in Emerald and FireRed (section 2), and matches the lane it replaces.121
  • Their look. A low stone curb in the forge’s stone ramp, with a notched lip and a worn step-down mark on the landing tile, drawn as part of the wall face, so that the drop reads as the wall’s low place rather than as a grass edge. The curb’s top course is a step lighter than the wall’s coping so that, from the meadow side, it reads as “lower here.” This is Kiradex’s answer to section 7’s legibility rule, drawn from the town’s own stone, not from the canon’s lip.2027

Acceptance check 2, the Meadow meets the routes numbers. The routes brief’s distance check, run on the joined Square, Meadow Walk and Lakeside with drops instead of the gate, as astra_meadow_joined.py runs it (section 6): for the gap positions the forge picks, the way home from the pier to the arrival is 88.07 tiles, the walk out is inside 110 to 120, and the way home is at or under 0.8 of it. The check does not ask the drops to reproduce the gate’s lengths, because joined they do not: with the lane hedge gone the meadow is open to the Square along all 24 of its columns, and the walk out is shorter on 1,035 of the gate’s 4,111 accepted layouts. The 4,111 is the gate’s count and stays the routes post’s; the drop design’s own count, from the sweep over all 160,000 gap positions under the same bands, is 4,607 layouts, the way home 88.07 on every one and 0.734 to 0.800 of the way out. The forge picks from that set, and the check reproduces the three numbers on the built map.17224

3. The server walks the same graph

The routes brief already moves the server’s Plaza.path to the client’s eight-way, √2, no-corner-cutting search.17 This brief adds the drops to it: the server reads the same drops list from its copy of each area and adds the same one-way edges. Today’s server accepts any walkable destination with no adjacency check (section 8), so a landing two tiles from the take-off would pass, and so would a jump back up.59 With the routes brief’s parity work, each move must be either a step to a neighboring tile or a drop from a take-off to its landing.

Acceptance check 3, server parity. A server test walks a collector across a drop both ways on the same fixture as check 1: the server’s search returns the same tiles as the app’s, with the same summed step cost, and a move message north across the drop, from a landing tile to its take-off, is refused.

4. The hop

  • Time. A drop takes its two tiles’ time at the walker’s own gait. The change is one line in the rig’s step-length rule (advance, line 659 at 334fbfe): a step of (0, 2) gets a length of 2 instead of 1, and the run’s pace applies to it as to any other step (section 8). In today’s code that is 0.5 seconds at a walk and 0.31 at the nominal run; under the motion post’s brief, 32 ticks at a walk, the canon’s frame count, and 16 at a run, 2 pixels a tick, as its run moves.54554
  • The run. This is the one place the brief departs from the canon on purpose. Emerald’s hop is the same 32 frames at a run (section 3), twice what running its two cells takes, and Emerald can afford that, because its straight outdoor ledges that have a walk round stand in for a median of 12 cells (FireRed’s, 10). The Meadow’s drops stand in for no walk round at all: they replace a lane of the same length, and the way home they serve, 51 single steps and 4 drops, is always run. Held to a walking 0.5 seconds at any gait, the four drops would make that run home 0.75 seconds slower than the gate’s lane in today’s code (9.97 seconds against 9.22) and 64 ticks slower under the motion brief (536 against 472), and on 96 of the 400 sampled layouts in today’s code, and 169 under the motion brief, the way home would no longer be quicker than the way out, which is the drops’ whole job. At the gait’s pace the way home is quicker than the way out on all 400 under both, and takes the gate’s time in the nominal arithmetic, distance over speed, 9.22 seconds in today’s code. Replayed in the rig’s own Float arithmetic at 60 hertz, where each step’s overshoot is discarded (section 8), the two are close but not equal: 59 run steps through the gate are 590 frames and 51 steps and 4 drops are 586, a drop taking 19 frames where two run steps take 20. The brief does not ask for frame parity; check 4 states the drop’s time in both forms.121921544
  • Gait. walk(to:) keeps its rule, a run for a path of 6 steps or more, and a drop counts as one step in that count. Every trip a drop shortens in section 6 is 19 steps or more, and the Meadow’s way home is 55, so no walk measured here changes gait because of a drop.544
  • Arc. Kiradex’s own, not the canon’s 16-step table: a parabola peaking at 10 texels, sampled each frame and rounded to whole texels, since the rig already places walkers on whole pixels. Ten texels on a 16-texel tile is a lower arc than the canon’s 12 pixels on 16 (section 3, and the dashed curve in its figure).544
  • Frames. Four new rig frames per facing in the forge’s rig.py: crouch, lift, fall and land. The rig has no hop today.64
  • Shadow. The 12-by-4 shadow is a child of the walker entity, and the walker entity is the figure, so lifting the figure lifts it (section 8). Either place adds the lift to the entity’s y and sets the shadow’s local y to its standing value less the lift, each frame, or the figure moves into a child entity of its own that alone is lifted. Either way the shadow follows the ground point through the hop, at its usual size (section 7, The shadow).54
  • Depth. Compute z from the ground point advance hands place, before adding the lift, as Emerald keeps the arc in y2 and the ground position in y (section 3).1554
  • Landing. A two-frame puff in the forge’s stone ramp.
  • Sound. One short sound of Kiradex’s own at take-off, not derived from any game’s.

Acceptance check 4, the hop. A rig log over one drop, one line a frame, with the ground point advance hands place, the lift, the y place computes from the ground point with no lift (the ground y), the figure’s drawn world y, the shadow’s world y and the walker entity’s z. It runs twice on one fixture, once on a path short enough to walk and once on a path of 6 steps or more, and passes when, on every frame of both:

  • the figure’s drawn y minus the ground y equals the lift, which peaks at 10 texels;
  • the shadow’s world y minus the ground y equals the shadow’s standing offset, the same value it has when the walker stands still, so a shadow that rises with the figure fails on every frame the lift is above 0;
  • the walker entity’s z equals map.depth(atWorldY:) of the ground point’s y, so a z taken from the lifted y fails: on a 30-row map like the Square it misses by 0.0104 at a 10-texel peak, more than ten times the 0.001 that sorts a walker against an object’s base row;534
  • and the drop takes 30 frames at 60 hertz walking, 0.5 seconds, and 19 frames running, 0.317 seconds, which is the rig’s Float replay of a nominal 0.3125, each within one frame, in today’s code (32 and 16 ticks exactly under the motion brief).

Nothing in the check asks the ground y, the shadow or z to stay constant: the drop carries all three two rows south, as any step carries them one.

5. The walkable roof row

Give the top roof row of each building a walkable letter of its own in the forge’s swift_rows, add it to TileMap.Tile as walkable and not a trigger, and add it to the server’s WALKABLE set. The forge’s buildings.py stops listing that row among a building’s blocked cells. The depth rule already draws a walker on that row behind the building (section 6), so nothing in the engine changes.11536459 The dossier proposed ^ as the letter, unused in the exported letters; the forge’s woods pass does use ^ internally, as a placeholder it clears before export, so the forge should take a letter that appears nowhere in it.2064 The 8 walks it shortens by 0.59 tile are a side effect, not the reason; the reason is that a building with a walkable back reads as a building in a place, not a block on a board.11

Acceptance check 5, the roof row. The exported letters carry the new letter on exactly 37 cells, and a capture shows a collector on the top row of the collector’s own house with the head above the ridge and the body hidden behind it.

6. A footbridge over the pond

A north-south plank footbridge at x 4, rows 23 to 27, joining the lower street’s lawn to the park’s south lawn. The deck’s tiles are a walkable letter drawn as ground, with the rails on the east and west sides drawn as objects, so the bridge needs no half-body occlusion. It has no elevation, because nobody passes under it (section 7, Bridges). The water’s animation must skip the deck. A plank under the walker can dip one texel and spring back, Kiradex’s version of the bridge that answers the step (section 4).114620

Acceptance check 6, the bridge. path from (4, 22) to (4, 28) returns tiles whose step costs sum to 6.00, against 12.83 today; across the four water frames of the atlas, no deck tile changes; and the export has no elevation key.

7. Per-cell height: deferred, and corrected for when it comes

The (cell, height) search of the engine dossier is not needed for anything in items 1 to 6. Keep it deferred until a map has a tile walkable at two heights, a walkway over a path.18 When it comes, fix the transition rule (section 7, The walk rule): after a step, the walker’s height becomes the cell’s elevation, including 0, unless the cell entered or the cell left is multi-level; and keep a separate draw level that updates only off 0 and 15, as Emerald’s previousElevation does.3 The engine dossier’s canStep already matches Emerald’s IsElevationMismatchAt and stays as it is; only height(after:was:) changes, and it needs the cell left as well as the cell entered:1820

// Sketch: has not been compiled or run in the app.
func height(after cell: SIMD2<Int>, from here: SIMD2<Int>, was height: UInt8) -> UInt8 {
    guard let elevation else { return height }
    let there = elevation[cell.y * width + cell.x], left = elevation[here.y * width + here.x]
    return there == Self.multiLevel || left == Self.multiLevel ? height : there
}

This is a sketch. It has not been compiled or run in the app. Its logic is the rule measure_gen3_elevation.py replays as Emerald’s, which climbs all 114 outdoor stairs of Emerald and FireRed; the sketch it replaces climbs none.10

Acceptance check 7, no unused height. A forge check fails any export that carries an elevation key while no tile in it is walkable at two levels. When per-cell height is built, a unit test on a fixture with a one-cell stair between levels 3 and 4 walks from the lower level to the upper with the new rule, and fails with the old one.

8. The fold over a terrace

When the division region is active and lies across the view, the camera may settle so that the fold covers a wall row of the Meadow Walk, and never a stair, a drop’s take-off, a door or the player. That extra settle happens only when the collector stops; while the collector walks, the camera keeps today’s rule, the player at the center of the wider side of the fold, and never shifts for the wall.566154

Acceptance check 8, the fold. On the iPhone Duo simulator in Device Hub’s Book pose, where the division turns active, a capture taken from inside the test bundle with the collector standing at each stair and each drop’s take-off in the Meadow Walk shows no door, stair, drop take-off or player tile under the fold.6358 No iPhone Duo was at hand for this post; this is a simulator check, and the same capture on hardware is open until one is.

9. Names and art

The drop, the curb, the hop’s frames, its sound and the footbridge are drawn in the forge from Kiradex’s own palette and kit, and named in Kiradex’s own words.27

Acceptance check 9, names and art. Every new name passes the deny list the routes brief calls for, which does not exist yet and is the routes brief’s work to build, and a review of the drop and the bridge against the homage post’s “must not resemble” list, recorded with captures of both, finds nothing on it.1727

Not in this brief

  • Drops in the Square: they save at most 0.59 tile there (section 6).11
  • Drops up the screen, which no map read in the four games has, and sideways drops, which the meadow’s southward way home does not need.1
  • Per-cell height before some tile is walkable at two heights (item 7).
  • Bridges with elevation: no one passes under the pond bridge.9
  • Climbing and free jumping: the cost CrossCode’s team and Sea of Stars’ director describe, height that must be read with light and color, buys nothing a collecting town needs (section 5).5052
  • A cable-car scene or any other height-as-a-scene trip: nothing in the routes brief climbs far enough to need one.
  • Any game’s ledge look, hop table or sound.27

Key Takeaways

If you draw the art

  • Draw a change of level as a face the walker cannot cross, with a stair through it. Outdoors, over 99.7% of the adjacent walkable pairs on a land level in Emerald and FireRed stand at one level; height lives in the cliff face, not in the number.7
  • Make a one-way edge look one-way from both sides. The south ledges in Emerald’s shared primary tileset are bright on their top eight rows and fall to their darkest at row 13 or 14; find your own way to say “lower here,” and do not copy that lip.4327
  • Leave the shadow on the ground when anything leaves it. Red, Crystal and Emerald all do, and it is what separates a hop from a step north.364215
  • Show a bridge’s height under it and on it: a reflection pushed further down, a plank that gives, a sound only the deck makes.1546

If you build the engine

  • Model a ledge as a directed edge in the walk graph, not as height. In FireRed every ledge cell is a transition cell and 94.4% of the straight ones with a cell on each side join equal elevations; the 28 Emerald ledges that join two levels take the landing cell’s elevation like any step, so even there the ledge stores none.123
  • If you store height, set the walker to “no level” on a stair. Emerald’s rule climbs all 114 outdoor stairs of Emerald and FireRed; a rule that keeps the old height on a transition climbs none.310
  • Store per-cell height only where a tile is walkable at two heights. Only 252 of Emerald’s 702 bridge cells need it, and no ledge does.91
  • Keep the hop’s arc out of the walker’s ground position, so depth and the shadow never see it.1554
  • Make the server walk the same graph as the client, one-way edges included, and check that each move is a step or a drop.5917

If you design the loop

  • Put a ledge where the walk round is long. The median outdoor walk round in FireRed and Emerald is 10 to 12 cells against a hop’s 2; on a map with stairs every 7 or 8 tiles, a drop saves under a tile.1911
  • Point drops down the screen or sideways, and on a route, the way the walk home goes. No ledge in the maps read from Red, Crystal, Emerald or FireRed goes up the screen.15 On all nine routes the routes post charted, the walk toward the earlier town is the shorter one, and on three of the four first routes it read, every ledge faces the starting town; Crystal’s Route 29, whose ledges mostly face across the route, is the exception, and its walk home is shorter all the same.17
  • Make big climbs a scene. Emerald’s cable car is 9.5 seconds of film with its own weather, not a staircase.647

FAQ

How do 2D Pokémon games handle elevation?

In Gen 3, each map cell stores a four-bit elevation beside its metatile and collision. A walker may step only onto a cell at its own elevation, unless the walker or the cell is at 0, the transition value used for stairs, or the cell is at 15, the multi-level value used for bridges. On a stair the walker’s elevation becomes 0, so the next step may go to either level; on a bridge the walker keeps the height they arrived with. Most outdoor maps use at most one land level: 50 of Emerald’s 68 and 67 of FireRed’s 76.3137

How do ledges work in Pokémon?

In Gen 3 a ledge is a cell whose behavior names one straight direction of travel; pushing against it that way makes the player hop two cells, and no other direction crosses it. Emerald also draws corner pieces with diagonal jump behaviors, but no code reads them, and they are blocked. In Crystal the ledge is the lip the player stands on, and its corners hop either way; in Red it is a pair of tiles in a table. In FireRed every ledge cell is stored at the transition value and 94.4% join a take-off and a landing at the same elevation; in Emerald 83.1% do, and 28 of 944 join two land levels. The engine never reads a ledge’s elevation, and after the hop the walker takes the landing cell’s, so a ledge is a one-way edge that does not require a drop in height. No ledge in the maps read from Red, Crystal, Emerald or FireRed is crossed up the screen; most face south.121312353736

How long does a ledge jump take in Pokémon?

32 frames of movement, 0.536 seconds at the handhelds’ 59.73 frames a second, for two cells, in Red, Crystal and Emerald alike, and in Emerald at a walk or a run; Red then waits at least three frames more, clearing the pad’s held, pressed and released state before it reads it again, so at least 35 in all. The sprite rises 12 pixels on a 16-pixel cell while a shadow stays on the ground; Crystal’s and Emerald’s height tables are identical entry for entry.612394

How do bridges work in Pokémon Emerald, with a player walking over a surfer?

Only 252 of Emerald’s 702 bridge cells, 35.9%, carry the multi-level value 15, and those are where a surfer, or in Fortree City a walker, passes underneath, 248 of the 252 on Routes 110, 119 and 120. On a multi-level cell a walker keeps the elevation they arrived with, so someone who walked onto the deck stays up and someone who surfed in stays down, and a sixteen-entry priority table, with the hardware’s tie rule, draws the first over a Normal deck’s top layer and the second under it. Of the other 450 bridge cells, 329 are decks at a fixed elevation 4 that nothing passes under; the remaining 121 are 69 cells stored blocked, 47 open cells stored at the surf value 1, where a surfer may go and a walker on the deck may not, the four transition cells at the ends of two Route 110 bridges, and one indoor cell at 3.9307345

How do you make stairs in a top-down tile game?

Do what Emerald does: a stair is usually one or two cells joining two levels through a face, and it costs an ordinary step. 73 of Emerald’s 84 outdoor stairs are 1 by 1, 1 by 2 or 2 by 1 cells, with no stair behavior at all; FireRed slows a walk on its rock stairs to 23 frames a cell from 16. If your walk rule stores height, the stair must belong to no level, or nobody climbs it.8610

Should a top-down pixel-art game have ledges or jumping?

Ledges, where a one-way shortcut back is worth a cell: half of the 549 straight outdoor ledge cells measured in Emerald have no walk round inside their map, and for the rest a hop of 2 cells replaces a median walk round of 12, a saving of 10. Free jumping and climbing are a different design, with a cost their makers name: CrossCode’s team, told its heights were hard to read, said it would mark them with color, and Sea of Stars’ director describes levels that had to read “with the light and everything”.1945052

Mechanics, numbers and methods of operation sit outside copyright; specific tiles, sprites and sounds 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.58 This brief borrows the rule (a one-way edge, about half a second at a walk, a shadow on the ground) and draws the drop, its frames and its sound from Kiradex’s own forge, against the homage post’s list of what it must not resemble.2720


How this post was made. The research dossier behind it was compiled on October 5, 2026 from shallow clones of the four pret decompilations, measured by Python scripts saved with their outputs, seven at first and five more added in review, one of the seven rebuilt after the second-engine review found its land filter wrong, and from saved copies of Porymap’s manual, two Radical Fish Games posts, the FF6 disassembly’s field notes, the zelda3 reimplementation’s player code, one Screen Rant interview and four Apple documentation pages. For this draft I re-ran all twelve scripts in a scratch copy of the evidence folder and got their saved outputs back byte for byte, except in astra_meadow_joined.py, where one line prints the wall-clock time of its first section and the 160,000-layout sweep was run once, and a thirteenth, arith.py, prints every derived figure, re-walking two of the scripts’ graphs where a time needs a walk’s steps. Every Pokémon number in the text is a script’s output, and each note names the script. The proposal in section 9 is mine and labeled so; none of it has been built, and nothing in it has run on an iPhone Duo.

Related on this site: Pixel-Art Worlds on iPhone is the first post in this series, with the RealityKit recipe, the capture rule and the legal line; Pixel-Art Structures: Houses, Halls and Interiors on iPhone built the town this post measures, gave it its terrace in build 35, and first refused ledges; Honoring the Old Pokémon Games Without Borrowing Them narrowed that refusal and set the list the drop must not resemble; Pixel-Art Routes: Map Connections and Districts on iPhone designed the Meadow Walk whose hedge gate the drops replace; Pixel-Art Motion: Walks, Cameras and Doors on iPhone has the walk the hop’s timing sits on; Pixel-Art People: Characters and a Creator on iPhone is the collector who hops; and Xcode 27.1 Beta: Your App in the iPhone Duo Simulator covers the simulator and the Book pose the fold check runs in.

Sources


  1. Author’s measurement, October 5, 2026: measure_gen3_elevation.py in the author’s evidence folder for this post, output gen3_elevation.txt and gen3_elevation.json, sections E (ledges: every cell carrying an MB_JUMP_* behavior, by behavior, over every layout a map uses, once each, which includes Emerald’s 77 diagonal corner pieces, separated from the hoppable cells in note 13; straight run lengths; and for every straight ledge cell with a cell on each side, the elevations of the take-off cell, the ledge cell and the landing cell) and J (cells with any MB_JUMP_* behavior and their layouts by map_type, and the towns and cities with them; for FireRed these are all hoppable, and Emerald’s hoppable counts by map type are in note 13). Inputs: pret pokeemerald at 731ad5b and pokefirered at 037335f, data/maps/*/map.json, data/layouts/layouts.json, each layout’s map.bin (bits 0 to 9 metatile, 10 and 11 collision, 12 to 15 elevation) and the primary or secondary metatile_attributes.bin, decoded with the routes post’s measure_gen3_routes.py. After the second-engine review the script’s land test was rebuilt from the engine’s own water test (note 7); sections E and J do not depend on it and are unchanged, and the script was re-run for this draft with identical output for them. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  2. Author’s measurement, October 5, 2026, added after the second-engine review: astra_ledge_triples.py in the author’s evidence folder for this post, output astra_ledge_triples.txt, with the same decoder and the same three cells as section E of measure_gen3_elevation.py (the take-off behind a straight MB_JUMP_* cell, the landing beyond it). Emerald’s 944 straight ledge cells with a cell on each side: 784 with equal take-off and landing elevations, 132 with a transition cell at the take-off or the landing, and 28 whose take-off and landing both stand on a land level and differ, 22 of them (5, 0, 3) and 6 (3, 0, 5), in Lilycove City (8, among them the south ledge at (48, 9), the cell the review named), on Route 115 (10), on Route 120 (2) and in the Safari Zone’s north (2) and south (6) areas, every one with a walkable MB_NORMAL take-off and landing; FireRed’s 1,042: 984, 58 and 0. Re-run for this draft in a scratch copy with identical output. ↩↩↩↩↩↩↩↩↩

  3. pret, pokeemerald/src/event_object_movement.c at 731ad5b, read October 5, 2026: GetCollisionAtCoords (from line 4641: the cell’s collision bits first, then IsElevationMismatchAt), IsElevationMismatchAt (from line 7673), sElevationToPriority (line 7695, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 0, 2, applied from previousElevation at line 7711), ObjectEventUpdateElevation (from line 7725, called through UpdateObjectEventElevationAndPriority as a step begins and as it ends, lines 8075 and 8096), GetLedgeJumpDirection (lines 7631 to 7654), InitJumpRegular calling DoShadowFieldEffect (line 5423), sJumpY_High (line 8393), and the jump’s own coordinate and elevation updates: InitJump (from line 5400) calls ShiftObjectEventCoords as the jump starts (line 5411), UpdateJumpAnim (from line 5428) calls it again at JUMP_HALFWAY (line 5442) and ShiftStillObjectEventCoords at JUMP_FINISHED (line 5448), each raising the ground-effect trigger that makes DoGroundEffects_OnBeginStep (from line 8064) or DoGroundEffects_OnFinishStep (from line 8085) call UpdateObjectEventElevationAndPriority (line 7703), so the hop ends with ObjectEventUpdateElevation assigning the walker the landing cell’s elevation (line 7733) with no test of the take-off’s, https://github.com/pret/pokeemerald/blob/master/src/event_object_movement.c. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  4. Author’s arithmetic from the measured values in the text: arith.py beside this post’s draft, output arith.txt, reading the outputs in the author’s evidence folder for this post. It prints the frame rate, 2^24 ÷ 280,896 = 59.7275 hertz; the hop’s 32 frames as 0.5358 seconds and the cable car’s 570 as 9.543; FireRed’s rock stairs as 23 ÷ 16 = 1.4375 and 11 ÷ 8 = 1.375; the shares of outdoor layouts with at most one land level (50 of 68, 73.5%; 67 of 76, 88.2%); the cliff pairs over all adjacent pairs (170 of 61,197, 0.278%; 122 of 61,461, 0.198%) and the equal-level shares (99.72%, 99.80%); the stairs of one or two cells (73 of 84, 86.9%) and FireRed’s rock-stair cells (49 of 59, 83.1%); the ledge direction shares (Emerald, counting the cells the engine hops, south 657 of 946, 69.5%, west 17.9%, east 12.7%, beside 77 diagonal corner pieces, 1,023 cells with any jump behavior in all; FireRed 962 of 1,042, 92.3%; Red 709 of 758, 93.5%; Crystal 964 of 1,148, 84.0%, 88.5% with the down corners, which hop); Emerald’s hoppable ledge cells by map type (routes 679 on 21 layouts, underground 187, indoors 48, Lilycove 32) beside the counts with corner pieces (726, 215, 48, 34); the elevation-15 cells under a bridge behavior (252 of 523, 48.2%); Emerald’s outdoor land cells at 0 outside the stairs (2,258); the equal take-off and landing shares (784 of 944, 83.05%; 984 of 1,042, 94.43%); median runs; the walk-round shares (269 of 549, 49.0%; 299 of 880, 34.0%) and medians over the hop’s 2; Red’s five towns’ ledge cells (119); the bridge shares (252 of 702, 35.9%; 329 at 4; 121 at 0, 1 or 3; layer types 685 Normal and 17 Covered); the ledge-art row statistics (the 15 south-facing tiles’ top-eight-row range 130.1 to 204.5, darkest values 87.9 to 107.6 at row 13 or 14, top half minus bottom half 36.9 to 89.4, mean 169.4 over the top half and 112.7 over the bottom; the 18 west- and east-facing tiles’ −14.4 to 21.8); and for Kiradex, a two-tile hop at 4 tiles a second (0.5 seconds, 30 frames at 60 hertz, 0.933 of the canon’s), the arcs as 12 ÷ 16 and 10 ÷ 16, the flight spacing (7, 7, 7, 8), seconds at 4 tiles a second for the door walks (the hall 2.06, the shop 5.02), the best drop saving (0.147) and the outer-flight cost (1.208), the footbridge’s saving (6.83 tiles, 53.2%; 3.21 to 1.50 seconds), and the meadow sample (400 of 20^4 = 160,000, 0.25%). A two-tile hop at the motion post’s proposed 16 ticks a tile is 2 × 16 = 32 ticks. The lines on Emerald’s hoppable ledge cells, the bridge share at 15 and the land at 0 outside the stairs were added after the fourth review round, reading r4_corner_cells.txt; two earlier lines were relabeled as counting every cell with a jump behavior, and the rest of the output is unchanged (the earlier script and output are kept as arith.pre-r4.py and arith.pre-r4.txt). Lines added after the first review round (the earlier output is kept as arith.pre-r1.txt, and its lines are unchanged) state their speed: today’s code, with tilesPerSecond (4), runPace (1.6) and the 6-step run rule read from PlazaRig.swift, a nominal run of 6.4 tiles a second; or the motion post’s brief, 16 ticks a tile walking and 8 running, 23 and 12 for a diagonal, at 60 ticks a second. To time a walk they re-walk measure_kiradex_elevation.py’s and probe_meadow_drops.py’s graphs, imported read-only, and split each shortest cost into straight steps, diagonals and drops. They print: a (0, 2) step as the code stands, 0.25 seconds walking and 0.156 running, and with a length of 2, 0.5 and 0.3125 (30 frames at 60 hertz walking), or 32 and 16 ticks under the motion brief; the canon at a run (8 frames a cell, the hop 16 frames more than running its two cells, a saving only past a walk round of 4 cells, which 239 of Emerald’s 280 ledges with a walk round and 485 of FireRed’s 581 have); the seven arrival-to-door walks as 7 to 18 steps, all runs, the hall 1.29 seconds and the shop 3.14 at the nominal run (2.06 and 5.02 walked); the trips the 0.59-tile drops shorten, 19 to 29 steps, each saving 0.092 seconds at the nominal run with the drop at the run’s pace, and losing 0.096 with a fixed 0.5-second hop (4 ticks saved, or 12 lost, under the motion brief); the footbridge at x 4, 12 steps and 6, 2.00 seconds and 0.94 at the nominal run; the Meadow’s way home with drops, 51 single steps and 4 drops (no sampled layout has one column through all four gaps), run in 9.22 seconds with the drops at the run’s pace, the gate’s own time, or 9.97 with fixed 0.5-second hops, and in 472, 472 or 536 ticks under the motion brief; the layouts where that way home is not quicker than the way out, 96 and 169 of 400 with a fixed hop and 0 and 0 with the hop at the gait’s pace; the depth error of a z taken from a lifted y, 0.5 ÷ (30 × 16) = 0.00104 a world unit, 0.0104 at a 10-texel lift; HingeReads’ cumulative waits (0.1, 0.5, 1.5, 4.0 seconds); the wall between the flights (6, 6, 6 and 7 tiles, 2 at each end, 29 in all); and Emerald’s 2,427 outdoor land cells at 0 against its 169 stair cells. Lines added after the second-engine review (the earlier script and output are kept as arith.pre-astra.py and arith.pre-astra.txt; the stair and pair lines above moved with the census, and every other earlier line is unchanged): the land-filter reconciliation (1,851 Emerald cells on which the name filter and the engine’s test disagree, 668 of them outdoors and 552 of those land by the engine’s test; 248 + 13 = 261 at elevation 15 and 300 + 706 = 1,006 at 4; the 1,182 MB_NO_SURFACING cells the name filter had called land, none outdoors; the four stairs the engine filter adds; FireRed 0); the ledge triple classes computed from section E and checked against astra_ledge_triples.txt (Emerald 784 equal, 132 with a transition cell on one side, 28 joining two land levels; FireRed 984, 58, 0); PlazaRig.advance replayed in Float32 at 60 hertz with the overshoot discarded, 15 and 10 frames a straight step walking and running, 22 and 14 a diagonal, 30 and 19 a two-tile drop (0.500 and 0.317 seconds), the Meadow’s way home 590 frames through the gate against 586 with drops; Red’s 32 + 3 = 35 frames, 0.586 seconds; and the joined-grid figures read from astra_meadow_joined.txt. Lines added after the third close read (the earlier script and output are kept as arith.pre-cr3.py and arith.pre-cr3.txt; every earlier line is unchanged): the 132 transition-side ledge cells by what the landing stores, from section E’s triples (3 on 118, 1 on 12, 0 on 1, 5 on 1), checked against cr3_bridge_ledge_cells.txt, and the 549 outdoor cells with an open take-off as 521 + 28; the 450 bridge cells that are not multi-level as 329 + 69 + 47 + 4 + 1, against section D’s 702 and 252; 552 = 300 + 248 + 4; the nine bridge behaviors with cells against the engine’s eleven, in five families; the four changed layouts’ differences from astra_meadow_joined.json, rounded after the subtraction (1.66, 3.31, 1.66 and 2.49 tiles), beside the 1.65 that subtracting the two-decimal figures gives; and the per-row mean luminance of the 15 south-facing tiles over the top eight rows, 162.9 to 175.5. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  5. Author’s measurement, October 5, 2026: measure_gen12_ledges.py in the author’s evidence folder for this post, outputs gen12_ledges.txt and gen12_ledges.json, reusing the cell decoders of the routes post’s measure_gen12_routes.py. Red (pret pokered at d2704a6): every map whose header names the OVERWORLD tileset, 34 maps, one 8-by-8 tile per cell (the lower-left) matched against data/tilesets/ledge_tiles.asm, ledge cells by direction and run, and the 8 table entries by direction. Crystal (pret pokecrystal at 5beda23): the 167 maps the routes decoder reads, collision bytes per quadrant assumed row-major, HOP_* cells by kind and the one-sided wall cells UP_WALL, LEFT_WALL and RIGHT_WALL. Re-run for this draft with identical output. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  6. Author’s measurement, October 5, 2026: measure_jump_timing.py in the author’s evidence folder for this post, output jump_timing.txt. It reads by regular expression and replays frame by frame: Red’s PlayerJumpingYScreenCoords (16 entries, two frames each); Crystal’s .y_offsets in engine/overworld/map_objects.asm (16 ticks of two frames); Emerald’s sJumpY_High and JUMP_DISTANCE_FAR in src/event_object_movement.c (32 frames, one pixel a frame, read at timer >> 1); FireRed’s UpdateWalkSlowAnim and UpdateRunSlowAnim against the normal walk and run; and Emerald’s src/cable_car.c (the car’s per-frame motion, the weather delays and the fade at timer 570). Re-run for this draft with identical output. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  7. Author’s measurement, October 5, 2026: measure_gen3_elevation.py in the author’s evidence folder for this post, output gen3_elevation.txt, sections A (elevation histograms over every layout a map uses and over land cells of outdoor layouts; “outdoor” is map_type ROUTE, TOWN, CITY or OCEAN_ROUTE, “land” a cell with collision 0 whose elevation is not 1 and whose behavior the engine does not treat as surfable water), B (land levels, elevations other than 0, 1 and 15, per outdoor layout), C (elevation 15: layout files, cells, the layouts with the most, and the behaviors under it), F (4-adjacent walkable land cells at two different levels against pairs at one level) and K (the land classification). Inputs as note 1. The water test is the engine’s, read out of the C source by the helper engine_terrain.py: in Emerald, MetatileBehavior_IsSurfableWaterOrUnderwater (src/metatile_behavior.c line 280) returns the TILE_FLAG_SURFABLE bit of sTileBitAttributes (lines 9 to 128), 16 behaviors; in FireRed, MetatileBehavior_IsSurfable (line 204) reads sBehaviorSurfable (lines 5 to 17), 11; the bridge set is MetatileBehavior_IsBridgeOverWater (line 773), MetatileBehavior_IsFortreeBridge (line 1003) and the pond-medium edge pair of MetatileBehavior_GetBridgeType (line 788), which section K confirms is the same eleven names as the header’s. The first draft’s land test took the routes post’s name filter, which calls a behavior water when its name contains OCEAN or POND (among other words), so the bridge behaviors counted as water and MB_NO_SURFACING and MB_UNUSED_6F as land; the second-engine review caught it, and the earlier script and outputs are kept as measure_gen3_elevation.pre-astra.py, gen3_elevation.pre-astra.txt and gen3_elevation.pre-astra.json. Section K lists the 1,851 Emerald cells in used layouts on which the two tests disagree (668 outdoors, 552 of them land by the engine’s test) and FireRed’s 0. The change moved Emerald’s outdoor land at 0 from 2,423 to 2,427, at 4 from 706 to 1,006 and at 15 from 13 to 261, the equal-level pairs from 60,535 to 61,027 with the 170 cliff pairs unchanged, and the stairs from 80 to 84 (notes 8 and 10); sections B, C, D, E, I and J and every FireRed number are unchanged. The script reports C_all_layout_files_with_15: 13 of 441 for Emerald and 0 of 365 for FireRed. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  8. Author’s measurement, October 5, 2026: measure_gen3_elevation.py, section G, in the author’s evidence folder for this post: stairs as 4-connected patches of walkable land cells at elevation 0 that touch two or more land levels, with their bounding boxes, cell counts, behaviors and the level pairs they join, over every outdoor layout of Emerald and FireRed. Inputs as note 1. With the engine’s land test (note 7) Emerald has 84 stairs of 169 cells, against the first draft’s 80 of 161: the four added are two-cell transition patches at bridge ends, Route 110 at (21, 13) and (28, 91), both MB_BRIDGE_OVER_OCEAN, and Route 120 at (7, 15) and (28, 15), both MB_NORMAL, each joining levels 3 and 4; no stair was removed, and FireRed’s 30 are unchanged. ↩↩↩↩↩↩↩↩

  9. Author’s measurement, October 5, 2026: measure_gen3_elevation.py, section D, in the author’s evidence folder for this post: every cell with a bridge behavior in Emerald’s layouts, with its elevation and its metatile’s layer type; FireRed reports none. The dossier behind this post gives the layer types as 683 Normal and 17 Covered; the script’s output sums to 685 Normal and 17 Covered, 702, and this post uses the script’s figure. ↩↩↩↩↩↩↩↩↩↩↩↩

  10. Author’s measurement, October 5, 2026: measure_gen3_elevation.py, section H, in the author’s evidence folder for this post. For each of the 84 Emerald and 30 FireRed stairs of note 8, a breadth-first search over (cell, walker elevation) pairs from a cell of the stair’s lowest level, under two rules: Emerald’s (a step is refused when the walker’s elevation is not 0 and the target’s is neither 0 nor 15 and differs; after the step the walker’s elevation is the target’s unless the target or the cell left is 15) and the engine dossier’s sketch (allowed if the height is 0 or the target is 0, 15 or the same height; after the step the height is unchanged on 0 or 15). A stair counts as climbed if any cell of its highest level beside it is reached. Output H_rule_test: Emerald’s rule climbs 84 and 30, the sketch is blocked on 84 and 30 (80 and 30 before the engine’s land test); the first five failures per game are listed. ↩↩↩↩↩↩↩↩↩

  11. Author’s measurement, October 5, 2026: measure_kiradex_elevation.py in the author’s evidence folder for this post, output kiradex_elevation.txt. It opens only the Kiradex repository’s Kiradex/Resources/World/town.json (40 by 30, arrival at (19, 13), the file’s modification time printed in the output’s first line), read only, and walks it with the app’s graph: eight moves, a diagonal costing √2 and allowed only when both tiles it passes between are walkable, over TileMap.Tile.isWalkable’s letters. A drop is a one-way edge from row 10 over the wall’s row 11 to row 12, cost 2. Sections: the wall row and the walkable tiles per level; the arrival to every door and back; drop candidates and their walk round; the saving of each single drop and of runs at x 4 to 6 and 30 to 33 over the 16 trips from the four upper doors to the arrival and the three lower doors, and the walks back up; the top roof rows, their reach and the depth rule; a north-south footbridge at each pond column. Re-run for this draft with identical output, including the file’s timestamp. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  12. pret, pokeemerald/src/field_player_avatar.c at 731ad5b, read October 5, 2026: the ledge check that calls GetLedgeJumpDirection (line 746), IncrementGameStat(GAME_STAT_JUMPED_DOWN_LEDGES) and the return of COLLISION_LEDGE_JUMP (lines 701 and 702), PlayerJumpLedge (line 1032, always the far jump) and PlaySE(SE_LEDGE) (line 1034); PlayerNotOnBikeMoving (from line 608), which on COLLISION_LEDGE_JUMP calls PlayerJumpLedge and returns (lines 614 to 617) before its test of the held B button that chooses PlayerRun (lines 658 to 661), so a running player’s hop is the same jump; the ledge check runs after GetCollisionAtCoords (line 695) and returns COLLISION_LEDGE_JUMP whatever that collision was, unless a surfer is stepping ashore (lines 696 to 702), and ShouldJumpLedge (from line 744) is the only caller of GetLedgeJumpDirection, which is at lines 7631 to 7654 of src/event_object_movement.c: a table of four tests, one per straight direction, MetatileBehavior_IsJumpSouth, IsJumpNorth, IsJumpWest and IsJumpEast (src/metatile_behavior.c lines 143 to 173, each matching one behavior), and DIR_NONE otherwise, https://github.com/pret/pokeemerald/blob/master/src/field_player_avatar.c. ↩↩↩↩↩↩↩↩↩↩

  13. Author’s measurement, October 5, 2026, added after the fourth review round: r4_corner_cells.py in the author’s evidence folder for this post, output r4_corner_cells.txt, with the routes post’s Gen 3 decoder as note 1. (1) Every line of src/ and include/ in pokeemerald at 731ad5b and pokefirered at 037335f that names an MB_JUMP_* behavior, a MetatileBehavior_IsJump* function or GetLedgeJumpDirection: in Emerald, 31 lines, and the four diagonal behaviors are named only in the header (lines 65 to 68) and in sTileBitAttributes (src/metatile_behavior.c lines 56 to 59, whose flag TILE_FLAG_UNUSED is commented “Set but never read” at line 7); in FireRed, 23 lines and no diagonal name. (2) Every Emerald cell whose metatile carries a jump behavior, by behavior and collision bits: in the layouts a map uses, 657 south, 120 east, 169 west, 33 south-east and 44 south-west, every one at collision 1; over every layout file, 78 diagonal cells, all at collision 1. (3) Emerald ledge cells as cells the engine hops, the four straight behaviors: 946 (south 657, west 169, east 120, north 0), 711 outdoors; by map type, routes 679 (21 layouts), underground 187 (16), indoor 48 (4), city 32 (1), town 0, beside 726, 215, 48, 34 and 0 with the corner pieces. (4) The 23 layout files with a diagonal cell, among them Route101_Layout (one south-east). (5) FireRed: the header defines MB_JUMP_EAST to MB_JUMP_SOUTH at 0x38 to 0x3B and nothing at 0x3C to 0x3F, and none of its 10,903 metatiles and no map cell carries a value there. Re-run in a scratch copy with identical output. ↩↩↩↩↩↩↩↩↩↩↩↩

  14. pret, pokecrystal/constants/collision_constants.asm at 5beda23, read October 5, 2026: COLL_HOP_UP (line 95), COLL_HOP_UP_RIGHT and COLL_HOP_UP_LEFT (lines 99 and 100), each marked “; unused”; COLL_RIGHT_WALL, COLL_LEFT_WALL and COLL_UP_WALL (lines 101 to 103), https://github.com/pret/pokecrystal/blob/master/constants/collision_constants.asm. ↩↩

  15. pret, pokeemerald/src/field_effect_helpers.c at 731ad5b, read October 5, 2026: LoadObjectReflectionPalette and bridgeReflectionVerticalOffsets (lines 75 to 95: 12, 28 and 44 pixels for the low, medium and high pond bridges, set together with the high-bridge palette whenever MetatileBehavior_GetBridgeType returns a pond type, and the regular palette with no offset for type 0, the sea); the comment at lines 112 and 113 (“When walking on a bridge high above water (Route 120), the reflection is a solid dark blue color. This is so the sprite blends in with the dark water metatile underneath the bridge.”); UpdateShadowFieldEffect (line 249: the shadow at the linked sprite’s y plus sYOffset), https://github.com/pret/pokeemerald/blob/master/src/field_effect_helpers.c. ↩↩↩↩↩↩↩↩↩↩↩↩↩

  16. pret, pokeemerald/src/data/field_effects/field_effect_objects.h at 731ad5b (sPicTable_GroundImpactDust, three frames, and sAnim_GroundImpactDust, 8 ticks each, on a 16-by-8 sprite, lines 278 to 305), src/event_object_movement.c (GroundEffect_JumpLandingDust, line 7961, the landing effect on normal ground), src/data/object_events/object_event_graphics_info.h (the player’s shadowSize = SHADOW_SIZE_M) and graphics/field_effects/pics/shadow_medium.png (16 by 8 pixels, read from its PNG header), read October 5, 2026, https://github.com/pret/pokeemerald/blob/master/src/data/field_effects/field_effect_objects.h. ↩↩↩↩

  17. Blake Crosley, “Pixel-Art Routes: Map Connections and Districts on iPhone,” blakecrosley.com, October 5, 2026: section 1 (the walk speeds, 16 frames a cell in all three generations, and Emerald’s step tables, 8 entries for running); section 2 (the run search, 8 frames a cell with each ledge hop still 32 frames, “because the hop is the same 32-frame jump at any gait”; “Ledges shorten the way home”: on all nine measured routes whose ends meet on foot the walk toward the earlier town is shorter, the ledges of Red Route 1, FireRed Route 1 and Emerald Route 101 all face the way back to the starting town, and Crystal Route 29, whose lip cells mostly face south across the route, is the exception; Red Route 1’s 42 ledge cells; Emerald Route 101’s 13 ledge cells in three runs of four and one corner; Crystal’s one-sided walls and Route 32’s 110, 132 and 128 cells; the sideways corner hop; “The elevation question”, deferring drops to this post); section 7 (the brief: the eight-way walking graph for the app and the server with a diagonal costing √2 and refused past a blocked tile; the Meadow Walk’s four hedges at rows 12, 24, 36 and 48 with 2-tile gaps and its hedge gate; the way home of 88.07 tiles, the outward band of 110 to 120 and the 4,111 layouts inside it at 0.73 to 0.80; the server parity check 12; the deny list as work to do; the deferral of ledges), https://blakecrosley.com/blog/pixel-art-world-beyond-the-plaza. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  18. Author’s engine dossier for the structures post, Kiradex repository docs/research/structures/02-structures-craft-and-engine.md, October 3, 2026; private: section 3.4 (“Elevation and the walk rule”, “Only when a map needs a ledge, a terrace or a bridge”; the sketch of canStep(to:height:) and height(after:was:), whose comment reads “The walker’s height after the step: unchanged on a transition or a bridge.”), section 3.5 (height in the town’s ground by elevation), and section 5’s order of work, step 10, “Elevation and ledges, only when a map uses them”. ↩↩↩↩↩↩

  19. Author’s measurement, October 5, 2026: measure_gen3_elevation.py, section I, in the author’s evidence folder for this post: for every straight outdoor ledge cell with land on both sides, the fewest steps from its take-off cell to its landing cell without any ledge, four ways, on land, under Emerald’s elevation rule, inside the ledge’s own map; none where no such walk exists. People, objects, surfing, bikes and warps are not modeled. ↩↩↩↩↩↩↩↩↩↩

  20. Author’s research dossier, “Elevation, ledges and bridges: how 2D games build height, and what Kiradex should,” compiled October 5, 2026: the method and the measurement scripts, the key facts (its copy keeps the first draft’s figures, among them 1,023 ledge cells counted by behavior, 683 Normal bridge layers and a 12-pixel reflection, which the review rounds revised as the notes say), the case studies, the fifteen rules, section 4 (“The brief for Kiradex”, the author’s synthesis: the ledge decision, the terrace and drops, the hop, the roof row, the footbridge, the deferred height and its corrected rule, the walk graph, the server and the fold, the nine acceptance checks and the refusals) and section 5 (“What is measured and what is not”: the approximations, what was read rather than measured, the search for an Eastward statement that could not run, the absence of iPhone Duo hardware, and the findings against the published posts). Kiradex repository docs/research/elevation/01-elevation.md; private, with a copy in the author’s research state. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  21. Author’s measurement, October 5, 2026: probe_meadow_drops.py in the author’s evidence folder for this post, output meadow_drops.txt. The meadow alone, 24 by 60 tiles, edge to edge, with the routes brief’s walls or hedges at local rows 12, 24, 36 and 48, each with a 2-tile gap whose position, 0 to 19, is drawn for 400 layouts by Python’s random.Random(6). Gate model: column 21 a hedge from row 0 to 58, the lane in columns 22 and 23, reachable from the north edge, never left northward through the gate, open to the meadow only at row 59; outward walks start west of the hedge. Drop model: the walls span all 24 columns but the gap, and columns 22 and 23 of each wall carry drops from row r − 1 to r + 1, cost 2, south only. The app’s eight-way graph, outward from the south edge to the north, homeward north to south. The layout constants come from the routes post’s measure_meadow_gate.py. The full arrival-to-pier route is not modeled here; note 22 models it. ↩↩↩↩↩↩↩↩

  22. Author’s measurement, October 5, 2026, added after the second-engine review: astra_meadow_joined.py in the author’s evidence folder for this post, outputs astra_meadow_joined.txt and astra_meadow_joined.json. It imports the routes post’s measure_meadow_gate.py (the Square from town.json with its north fence opened along the shared edge, the Meadow Walk at offset 4, the Lakeside with the pier at the lane’s head, the eight-way walk with a diagonal costing √2 and refused past a blocked tile, and the gate model) and puts the drop design on the same joined grid: no lane hedge, the four walls at the meadow’s rows 12, 24, 36 and 48 across all 24 columns but their 2-tile gap, columns 22 and 23 of each wall one-way drops from the row above to the row below at cost 2, and no gate. Section 1, the layout the review named, gaps (19, 1, 1, 17): out 114.15432893 with the gate and 111.66904756 with drops, home 88.07106781 under both, the outward route entering the meadow at global column 11 with the gate and 26 with drops. Section 2, the probe’s 400 sampled layouts: home 88.07 on all under both; out 94.70 to 127.75 with the gate and 92.21 to 123.27 with drops, shorter with drops on 114 and longer on none; 17 inside the routes brief’s bands with the gate, 4 of them changed by the drops, gaps (19, 1, 1, 17), (19, 0, 16, 15), (6, 17, 1, 16) and (17, 1, 19, 17), all four still inside the outward band. Section 3, every gap combination (160,000, ten worker processes, 430 seconds on the author’s Mac): home 88.07 on all; out 89.73 to 134.44; 17,846 inside 110 to 120 with no winding filter; 5,912 in the winding band of 78 to 90 (the same 5,912 whether the winding is measured west of the lane hedge, as the routes post defines it, or over the drop meadow’s 24 columns, since the two values agree on every layout), 4,607 of them inside the outward band at 0.734 to 0.800; of the gate’s 4,111 accepted layouts, out unchanged on 3,076, shorter on 1,035 (by up to 5.31 tiles), longer on none, 4,103 still inside the band and 8 under 110, the shortest at 109.67. Sections 1 and 2 were re-run for this draft in a scratch copy with identical output but for the line that prints how long section 1 took; section 3 was run once. ↩↩↩↩↩↩↩↩

  23. Author’s measurement, October 5, 2026: probe_kiradex_variants.py in the author’s evidence folder for this post, output kiradex_variants.txt, using the walk of measure_kiradex_elevation.py: (a) every door-to-door walk a walkable top roof row changes; (b) the outer one-tile flights at x 3 and x 36 replaced by drops, and, as a control, removed with no drops; (c) the court’s flower beds at row 12, x 12 to 15 and 23 to 26, paved, with drops above the six whose take-off is walkable (x 12, 14, 15, 23, 24 and 26), and, as a control, paved with no drops; totals over the 16 trips down and the 16 back up. Re-run for this draft with identical output. ↩↩↩↩

  24. Kiradex source, read October 5, 2026 (private repository): scripts/forge/town.py, the module docstring (the letter list, among them “W the terrace’s wall: the upper town stands a step above the lower, and this is the face of that step, seen from the lower side (build 35)” and “/ a stair through the wall (plaza stone to the feet)”; the two levels “the width of the town with five flights through it”; “Height is drawn, not simulated: the wall’s cells are blocked and the stairs are stone, so nothing about the feet changed”), and the export Kiradex/Resources/World/town.json (40 by 30, row 11 the wall), dated October 3, 2026. ↩↩↩↩↩↩

  25. Blake Crosley, “Pixel-Art Structures: Houses, Halls and Interiors on iPhone,” blakecrosley.com, October 3, 2026: section 2 (Emerald’s elevation and the priority table; “thirteen of 441 layouts use any” multi-level cells; Route 119’s bridge from Porymap’s manual); the honest list (“The top roof row is blocked, not walkable as Emerald’s is”; “the layer would draw it correctly, the letters forbid it”; the engine dossier’s (cell, height) search “written for when a map wants one”); the October 3 evening update (the two-level town as TestFlight build 35, commit 305118e); and the FAQ answer “Reserve per-cell elevation for terraces, ledges and bridges on the ground, where Emerald uses a transition value for stairs and a multi-level value for a bridge cell”, https://blakecrosley.com/blog/pixel-art-structures-on-iphone. ↩↩↩↩↩↩

  26. Author’s research dossier for the structures post, Kiradex repository docs/research/structures/01-structures-in-the-canon.md, October 3, 2026; private: section 8.8 (“Free height”: CrossCode’s cost and its team’s warning, and “No ledges to jump, no climbing, no isometric”); the CrossCode map editor read there (height-map.service.ts in CCDirectLink’s crosscode-map-editor, each level’s wall face drawn as level.height / 16 tile rows, https://raw.githubusercontent.com/CCDirectLink/crosscode-map-editor/master/webapp/src/app/services/height-map/height-map.service.ts), not saved again for this post; and its finding of no developer statement on Eastward’s elevation. ↩↩↩↩↩

  27. Blake Crosley, “Honoring the Old Pokémon Games Without Borrowing Them,” blakecrosley.com, October 5, 2026: section 5 (Emerald’s ledge cells by map type, 726 on 21 of 41 routes, 34 in cities, 215 underground, 48 indoors, none in 7 towns; “The town, where people live and the player arrives, never has one”; the narrowing of the structures refusal, a drop that “has no z axis, only a one-way edge in the walk graph”) and the brief’s “Must not resemble” line (“a grass lip with a light top edge and a dark shadow line”, the hop animation, the sound), https://blakecrosley.com/blog/honoring-the-old-pokemon-games. ↩↩↩↩↩↩↩↩↩↩↩↩

  28. pret, shallow clones of pokered at d2704a6 (committed September 22, 2026), pokecrystal at 5beda23 (September 29, 2026), pokeemerald at 731ad5b (October 1, 2026) and pokefirered at 037335f (September 26, 2026), held in the author’s research state, https://github.com/pret. ↩

  29. Author’s measurement, October 5, 2026: r3_jump_behaviors.py in the author’s evidence folder for this post, output r3_jump_behaviors.txt. It reads the behavior enum of pokeemerald/include/constants/metatile_behaviors.h at 731ad5b (eight MB_JUMP_* values, lines 61 to 68: east, west, north, south, northeast, northwest, southeast, southwest) and every data/tilesets/*/*/metatile_attributes.bin (70 tilesets, 16,698 metatiles; the behavior is the low byte, METATILE_ATTR_BEHAVIOR_MASK 0x00FF at include/global.fieldmap.h line 39). Jump metatiles: 232 in all, 89 south, 53 east, 51 west, 20 southeast, 19 southwest, and none north, northeast or northwest; 33 in the shared primary tileset and 199 in fourteen secondary tilesets. ↩↩

  30. Author’s measurement, October 5, 2026, added after the third close read: cr3_bridge_ledge_cells.py in the author’s evidence folder for this post, output cr3_bridge_ledge_cells.txt, with the decoder of notes 1 and 7 and the engine’s bridge set from engine_terrain.py. Section 1 splits Emerald’s 702 bridge cells by collision, elevation and map: 252 at 15 (Route 110 185, Route 120 47, Route 119 16, Fortree City 4); of the 450 others, 329 open at 4 (Route 110 294, Fortree City 23, Route 120 12), 69 stored blocked (all Route 110, 68 at 0 and 1 at 3), 47 open at 1 (Route 110 46, Route 120 1), 4 open at 0 (Route 110 (21, 13), (22, 13), (28, 91) and (29, 91), the two bridge-end stairs of note 8) and 1 open at 3 (the Union Room, an indoor map); the only collision values are 0 and 1; Fortree’s 27 are 23 at 4 and 4 at 15. Section 2 takes the 944 straight ledge cells with a cell on each side (note 1) and asks whether the take-off is open: 730 of the 784 that join equal elevations, all 28 that join two land levels and 4 of the 132 with a transition cell on one side; the 549 outdoor cells with an open take-off are 521 equal and the 28, the population section I of measure_gen3_elevation.py walks round. Of the 132, the landing stores 3 on 118, 1 on 12 (all on Route 118, each landing on MB_OCEAN_WATER), 0 on 1 (Victory Road 1F) and 5 on 1 (the Safari Zone’s north area); 128 have a blocked take-off, and the 4 with an open one land on 3 in Fortree’s gym (1), Lavaridge’s gym (2) and Victory Road B2F (1). The engine’s ledge test reads only the ledge cell’s behavior (GetLedgeJumpDirection, note 3) and never the landing cell’s collision, so a blocked take-off is what keeps a walker off a ledge. Run twice for this draft, in the evidence folder and in a scratch copy, with identical output. ↩↩↩↩↩

  31. pret, pokeemerald/include/global.fieldmap.h at 731ad5b, read October 5, 2026: MAPGRID_ELEVATION_MASK 0xF000 // Bits 12-15 (line 9) and ELEVATION_TRANSITION = 0, ELEVATION_SURF = 1, ELEVATION_DEFAULT = 3, ELEVATION_MULTI_LEVEL = 15 (lines 16 to 19); and the metatile layer types (lines 50 to 52), METATILE_LAYER_TYPE_NORMAL (“Metatile uses middle and top bg layers”), METATILE_LAYER_TYPE_COVERED (“Metatile uses bottom and middle bg layers”) and METATILE_LAYER_TYPE_SPLIT, https://github.com/pret/pokeemerald/blob/master/include/global.fieldmap.h. ↩↩↩↩↩

  32. Porymap manual, “Editing Map Collisions,” saved October 5, 2026 as porymap-collisions.txt in the author’s evidence folder for this post (“Elevation is how the game determines whether or not an object is on the same level as something else”; the Transition type, which “allows the player to move between different elevations. The most common use case is for stairs”; the Multi-Level type, which “is used for bridges” and “remembers the player’s previous elevation”), https://huderlem.github.io/porymap/manual/editing-map-collisions.html. ↩↩↩

  33. pret, pokeemerald/src/metatile_behavior.c and include/metatile_behavior.h at 731ad5b, read October 5, 2026: MetatileBehavior_GetBridgeType (from line 788; its comments, MB_BRIDGE_OVER_POND_LOW “(Unused)”, the medium and high pond bridges on Route 120, the sea bridges on Routes 110 and 119; anything else returns BRIDGE_TYPE_OCEAN, which the header’s enum makes 0), https://github.com/pret/pokeemerald/blob/master/src/metatile_behavior.c. ↩↩

  34. pret, pokeemerald/include/constants/metatile_behaviors.h at 731ad5b, read October 5, 2026: the behavior list, among them MB_STAIRS_OUTSIDE_ABANDONED_SHIP (line 32, which MetatileBehavior_IsNorthArrowWarp in src/metatile_behavior.c, line 304, counts as a warp), the eight MB_JUMP_* behaviors at lines 61 to 68, and the bridge behaviors from MB_BRIDGE_OVER_OCEAN (line 117), https://github.com/pret/pokeemerald/blob/master/include/constants/metatile_behaviors.h. ↩↩↩↩

  35. pret, pokefirered/src/field_player_avatar.c at 037335f, read October 5, 2026: PlayerIsMovingOnRockStairs (line 535: going north it tests the cell stood on, line 546, and going south the cell ahead, line 549) choosing PlayerRunSlow (line 520) or PlayerWalkSlow (line 529), https://github.com/pret/pokefirered/blob/master/src/field_player_avatar.c. ↩

  36. pret, pokered/engine/overworld/ledges.asm at d2704a6, read October 5, 2026: HandleLedges (returning unless the tileset is OVERWORLD; matching facing, the tile stood on and the tile ahead against LedgeTiles; requiring the direction held in hJoyHeld; simulating two presses; LoadHoppingShadowOAM; SFX_LEDGE), LedgeHoppingShadow (gfx/overworld/shadow.1bpp) and LedgeHoppingShadowOAMBlock (one tile written four times, plain, X-flipped, Y-flipped and both), and data/tilesets/ledge_tiles.asm (the table), https://github.com/pret/pokered/blob/master/engine/overworld/ledges.asm. ↩↩↩↩↩↩↩↩↩

  37. pret, pokecrystal/engine/overworld/player_movement.asm at 5beda23, read October 5, 2026: .Normal (from line 45: .TryStep, then .TryJump at line 54 only if the step was refused), .CheckTile (from line 113, reading wPlayerTileCollision for currents and waterfalls under the player), .TryJump (from line 354: wPlayerTileCollision’s high nybble compared with HI_NYBBLE_LEDGES, the facing ANDed with .ledge_table at line 383, which maps COLL_HOP_UP and the up corners like the rest, SFX_JUMP_OVER_LEDGE), https://github.com/pret/pokecrystal/blob/master/engine/overworld/player_movement.asm. ↩↩↩↩

  38. pret, pokecrystal/home/map.asm at 5beda23, read October 5, 2026: GetMovementPermissions (from line 1511; under the comment “get coords of current tile” at line 1516 it reads wPlayerMapX and wPlayerMapY, calls GetCoordTileCollision and stores the result in wPlayerTileCollision, which macros/ram.asm’s object_struct makes the player object’s own tile-collision field), https://github.com/pret/pokecrystal/blob/master/home/map.asm. ↩

  39. pret, pokered/engine/overworld/player_animations.asm at d2704a6, read October 5, 2026: PlayerJumpingYScreenCoords (line 523), read through wPlayerJumpingYScreenCoordsIndex (from line 492); .finishedJump (lines 504 to 521: returns while wWalkCounter is not 0, then UpdateSprites, Delay3 (note 41), and clears hJoyHeld, hJoyPressed, hJoyReleased, the index and the ledge flag), https://github.com/pret/pokered/blob/master/engine/overworld/player_animations.asm. ↩↩

  40. pret, pokered/home/overworld.asm at d2704a6, read October 5, 2026: OverworldLoop (from line 41: DelayFrame at lines 42 and 44, HandleMidJump at line 48 while the ledge flag is set), the step’s walk counter of 8 (lines 264 and 265), decremented once a pass in AdvancePlayerSprite (line 1445), and _HandleMidJump in engine/overworld/player_animations.asm (from line 491: the index stored only while it stays below 16, the table read at the old index), https://github.com/pret/pokered/blob/master/home/overworld.asm. ↩

  41. pret, pokered/home/palettes.asm at d2704a6, read October 5, 2026: Delay3 (line 14, under the comment “Wait three frames to let the bg map fully update”, ld c, 3 and jp DelayFrames), https://github.com/pret/pokered/blob/master/home/palettes.asm. ↩

  42. pret, pokecrystal/engine/overworld/map_objects.asm (the jump’s .y_offsets under UpdateJumpPosition, line 1847) and pokecrystal/engine/overworld/movement.asm (JumpStep from line 748, calling SpawnShadow at line 762) at 5beda23, read October 5, 2026, https://github.com/pret/pokecrystal/blob/master/engine/overworld/movement.asm. ↩↩↩↩

  43. Author’s measurement, October 5, 2026: measure_ledge_art.py in the author’s evidence folder for this post, outputs ledge_art.txt and ledge_art.png, over pret pokeemerald at 731ad5b, data/tilesets/primary/general/ (tiles.png, the JASC palettes, metatiles.bin, metatile_attributes.bin): the 33 metatiles with an MB_JUMP_* behavior (27 straight: 9 south, 9 west, 9 east; and 6 corner pieces, 3 south-west and 3 south-east), their layer type (bits 12 to 15 of the attribute) and each pixel row’s mean luminance over the pixels the two layers draw (color 0 transparent). The render was viewed for this draft: each south-facing tile is a grass, sand or dirt surface over a brown rock lip; the tiles’ drawn entries use palettes 2, 3 and 5, within the six a primary tileset owns (the 60 entries that carry palette 0 are all the empty tile 0) (NUM_PALS_IN_PRIMARY 6, include/fieldmap.h line 8). The render is derived from copyrighted art, is for analysis only, and is not published; this post plots the numbers only. ↩↩↩↩↩↩

  44. pret, pokeemerald/src/field_camera.c and src/overworld.c at 731ad5b, read October 5, 2026: DrawMetatile (from line 245; the Covered case at line 268 puts the bottom layer on BG3 and the top on BG2, the Normal case at line 287 the bottom on BG2 and the top on BG1, “which covers object event sprites”) and sOverworldBgTemplates (from line 266 of overworld.c: BG1 at priority 1, BG2 at 2, BG3 at 3), https://github.com/pret/pokeemerald/blob/master/src/field_camera.c. ↩↩

  45. Martin Korth, GBATEK, the OBJ attribute “Priority relative to BG” (“In case that the ‘Priority relative to BG’ is the same than the priority of one of the background layers, then the OBJ becomes higher priority and is displayed on top of that BG layer”), saved October 4, 2026 as gbatek.txt in the evidence folder of the routes post, https://problemkaputt.de/gbatek.htm. A hardware reference, not pret code: the tie rule is the console’s, and the post’s draw-order sentences rest on it. ↩↩↩

  46. pret, pokeemerald/src/field_tasks.c at 731ad5b, read October 5, 2026: the Fortree bridge task (lines 505 to 562: the comment “Make sure player isn’t below bridge” at line 525, the even-elevation test, PlaySE(SE_BRIDGE_WALK) at line 532, the BUGFIX comment on bridge sections not lowered from other ground, and tBounceTime = 16 at line 561), https://github.com/pret/pokeemerald/blob/master/src/field_tasks.c. ↩↩↩↩↩

  47. pret, pokeemerald/src/cable_car.c at 731ad5b, read October 5, 2026: the fade at timer == 570 (line 455) and the weather delays of 350 and 265 frames (lines 837 and 865), https://github.com/pret/pokeemerald/blob/master/src/cable_car.c. ↩↩↩

  48. everything8215, ff6 disassembly, notes/field-ram.txt, saved October 5, 2026 as ff6-field-ram.txt in the author’s evidence folder for this post (tile properties: “tile uses up/left movement (stairs)”, “up/right movement (stairs)”, the bridge flag “not active for bridge tiles”, “passable on lower z-level”, “passable on upper z-level”, and “if both of these are set, this tile can be a transition between upper and lower”), https://github.com/everything8215/ff6/blob/main/notes/field-ram.txt. ↩

  49. snesrev, zelda3 reimplementation, src/player.c, saved October 5, 2026 as zelda3-player.txt in the author’s evidence folder for this post (Dungeon_HandleLayerChange, its line 89; the attribute read with link_is_on_lower_level ? 0x1000 : 0 in PushBlock_GetTargetTileFlag, its line 3798, and the same offset in the hammer’s splash test, its line 4478; the staircase toggle, its line 2319; the reimplementation’s tile detection was not read), https://github.com/snesrev/zelda3/blob/master/src/player.c. Reimplementation code, no prose source. ↩↩

  50. Radical Fish Games (lachsen), “CrossQuestion: Why do we use auto jump in CrossCode?”, published September 29, 2013, with the comment by lachsen of October 4, 2013, saved October 5, 2026 as crosscode-1168.txt in the author’s evidence folder for this post, https://www.radicalfishgames.com/?p=1168. ↩↩↩↩↩↩

  51. Radical Fish Games (lachsen), “Path Finding in CrossCode,” published April 28, 2013 (“jump-up-edges” and “jump-down-edges”), saved October 5, 2026 as crosscode-498.txt in the author’s evidence folder for this post, https://www.radicalfishgames.com/?p=498. ↩

  52. Screen Rant, interview with Thierry Boulanger of Sabotage Studio on Sea of Stars, August 29, 2023, saved October 5, 2026 as seaofstars-screenrant.txt in the author’s evidence folder for this post, https://screenrant.com/sea-stars-interview-thierry-boulanger/. ↩↩↩

  53. Kiradex source, Kiradex/World/TileMap.swift, read October 5, 2026 (private repository): Tile and its walkable cases and letters (lines 25 to 55); depth(atWorldY:) (line 122, 1 + (1 - y / (Float(height) * Self.tileSize)) * 0.5) and depth(ofObjectWithBase:) (line 127, the base row’s depth less 0.001); path(from:to:) (from line 325: returns [SIMD2<Int>], the tiles to step through, and no cost; eight moves, a diagonal costing Float(2).squareRoot() and skipped unless both tiles it passes between are walkable). ↩↩↩↩↩↩↩↩↩

  54. Kiradex source, Kiradex/World/PlazaRig.swift, at commit 334fbfe, read October 5, 2026 (private repository; the working tree was being rewritten that day, and these lines are the commit’s, decoded from its object store): the Walker class (line 19: its entity, the figure, and the comment on its shadow, “The blob under the feet, a child of the figure.”); tilesPerSecond 4 (line 101) and runPace 1.6 (line 122); the path search called to plan each walk (lines 528 and 608); walk(to:) setting running = steps.count >= 6 (line 614); shade (from line 389: the shadow a 12-by-4 ModelEntity plane, added as a child of the walker entity at line 394); advance (from line 652: the length √2 for a diagonal step and 1 for any other, line 659, and the progress advanced by dt × tilesPerSecond × (running ? runPace : 1) ÷ length, line 660, toward a ground point interpolated between the two tiles’ centers, line 670); animate (the frame set as the walker entity’s own material, line 716); place (from line 722: x and y rounded, z from map.depth(atWorldY:) of the ground point, line 724); and follow (from line 733: “Half open, the player is kept clear of the fold: at the centre of the wider side of it, not of the view”). ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  55. Blake Crosley, “Pixel-Art Motion: Walks, Cameras and Doors on iPhone,” blakecrosley.com, October 5, 2026: the brief’s rules, a walk of 1 pixel a tick, 16 ticks a tile, 3.75 tiles a second, and a run of 2 pixels a tick, 8 ticks a tile, keeping today’s rule that a path of 6 steps or more is a run, with a diagonal step of 23 ticks walking and 12 running; and its model of today’s code, in which the run takes 10 frames a tile at 60 hertz, 6.00 tiles a second where 4 times 1.6 would be 6.4, “because each tile’s overshoot is thrown away”, https://blakecrosley.com/blog/pixel-art-motion-on-iphone. ↩↩↩↩↩

  56. Apple Developer Documentation, “Preparing your app for iPhone Duo,” saved October 5, 2026 as apple-prepare-duo.txt in the author’s evidence folder for this post (“a reserved region that represents the fold is active when iPhone Duo is partially open, but inactive when it is fully open”; “Identify elements or controls in your views that appear in the fold, and are difficult to see or interact with.”), https://developer.apple.com/documentation/technologyoverviews/preparing-your-app-for-iphone-duo. ↩↩↩

  57. Apple Developer Documentation, GeometryProxy.reservedRegions(kind:options:layoutDirectionBehavior:), saved October 5, 2026 as apple-reservedregions.txt in the author’s evidence folder for this post (“Returns an array of reserved regions that match the selection options you specify”; the division kind, “An area where content splits into separate regions, such as at the fold of a hinge.”; availability iOS 27.1+ and iPadOS 27.1+, marked beta, Mac Catalyst, macOS, tvOS, visionOS and watchOS 27.1+), https://developer.apple.com/documentation/swiftui/geometryproxy/reservedregions(kind:options:layoutdirectionbehavior:). ↩↩

  58. Blake Crosley, “Pixel-Art Worlds on iPhone: What the 16-Bit Masters Knew,” blakecrosley.com, October 3, 2026: the RealityKit recipe (an orthographic camera at whole pixels per texel, unlit cut-out materials), the capture rule (RealityKit frames on the iPhone Duo simulator are faithful only when captured from inside the test bundle, XCUIScreen.screens[1]), and the legal FAQ with the Copyright Office’s Circular 33, https://blakecrosley.com/blog/pixel-art-world-on-iphone. ↩↩↩↩

  59. Kiradex source, read October 5, 2026 (private repository): Kiradex/World/PlazaClient.swift, moved(to:facing:) (from line 174, sending ["t": "move", "tile": [tile.x, tile.y], "facing": facing] at line 177, once per tile stepped); server/app/main.py, _tile (from line 107: a two-integer list that is walkable, with no adjacency check) and the move handler (from line 220: a valid tile and facing and player.may_move(now)); server/app/rooms.py, WALKABLE = set("gtpTBFsEH") (line 23) and Plaza.path (from line 52, breadth first over four moves; its docstring, “the same walk the app takes”). ↩↩↩↩↩↩

  60. Apple Developer Documentation, View.onHingeChange(isEnabled:_:), saved October 5, 2026 as apple-onhingechange.txt in the author’s evidence folder for this post (“Adds an action to perform when the hinge context of the view hierarchy changes.”; iOS 27.1+ and iPadOS 27.1+, marked beta, and the same other platforms), https://developer.apple.com/documentation/swiftui/view/onhingechange(isenabled:_:). ↩

  61. Apple, Human Interface Guidelines, “Designing for iPhone Duo,” saved October 5, 2026 as apple-hig-duo.txt in the author’s evidence folder for this post (“Avoid extreme layout changes as people fold the device.”), https://developer.apple.com/design/human-interface-guidelines/designing-for-iphone-duo. ↩↩

  62. Kiradex source, Kiradex/World/WorldHUD.swift, read October 5, 2026 (private repository): Fold.read (from line 154: proxy.reservedRegions(kind: .division).first(where: \.isActive)?.frame behind #if canImport(SwiftUI, _version: 8.0.85) and #available(iOS 27.1, *), with the comment “Reserved regions are in the 27.1 SDK only; a build from the 27.0 SDK the App Store takes sees no fold”; the type’s comment, “The region arrives a few layouts after the hinge moves”) and HingeReads (from line 169: onHingeChange at line 178, then a loop, lines 180 and 181, that sleeps 0.1, 0.4, 1.0 and 2.5 seconds in turn and reads after each sleep). ↩↩

  63. Blake Crosley, “Xcode 27.1 Beta: Your App in the iPhone Duo Simulator,” blakecrosley.com, September 21, 2026, corrected October 2, 2026 (Device Hub’s Closed, Book and Open poses; on the open inner display “an inactive division 40 points wide down the middle that turns active in the Book pose”), https://blakecrosley.com/blog/xcode-27-1-beta-iphone-duo-simulator. ↩↩

  64. Kiradex source, read October 5, 2026 (private repository): scripts/forge/props.py (wall_face, line 159; stair, line 202); scripts/forge/rig.py (no hop, jump or crouch frame); scripts/forge/buildings.py (the building record’s blocked cells, line 189, every opaque cell but the door); and scripts/forge/town.py (the woods pass, lines 455 to 476, writing ^ “reserved for the canopy” and clearing it to . before the rows are returned; swift_rows from line 479, the exported letters, in which ^ does not appear). ↩↩↩↩

関連記事

Pixel-Art Routes: Map Connections and Districts on iPhone

How Pokémon, Stardew and Animal Crossing build the land between towns, measured from source: routes, seams, gates, map s…

113 分で読める

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 分で読める

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 分で読める