A Pixel Town Alive When Nobody Is Online: NPCs and Ghosts

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

A pixel town feels inhabited mostly through people who stand still. In Pokémon Emerald’s 16 towns and cities, the 100 townspeople who carry no hide flag, and so are there on every visit, split 59 standing at a post, facing one way or looking around, 39 wandering a box one or two cells from where they were placed, and 2 walking in place; add the 58 that a story flag can remove, mostly team members, rivals and named characters, 54 of them standing, and the split is 113 of 158 (71.5%), 43 (27.2%) and 2. A wanderer steps for 16 frames and then waits 32, 64, 96 or 128, so it is in motion at most 11 to 33 percent of the time.1 The day is settled when the player comes back, by one function run once with the number of days elapsed, not by a clock that runs while nobody plays.23 When nobody else is there, the canon fills the town with other people’s traces in small fixed slots (Emerald’s record mixing copies 20 Secret Bases, 5 trend phrases and another player’s Old Man into your game) and lets strangers share presence without sharing words.45 I measured all of that because my own town, Kiradex World, has to answer the same question on its first quiet morning, and its server’s own code, driven on a simulated clock, answers it badly on three counts: its four collectors stop when the room is empty, they step once a second against a configured 0.7 seconds and stand still 75 percent of each walk, and, in a model of the app’s own drawing code, another collector is drawn jumping backwards when a move arrives mid-step: on 45 of the 64 moves of a run, and on 7 and 16 frames of a 40-tile walk with 30 and 80 ms of network jitter, though never on a steady walk with none.67 This is the canon measured, the modern references, live presence with its numbers, the rules for a world children can be in, and the brief.

TL;DR

  • Most of a town stands. Six in ten of the 100 people in Emerald’s towns and cities who carry no hide flag have stationary default movement types, and seven in ten of all 158 once the 58 the story can remove are counted (a story script can still walk one, as Petalburg’s gym boy walks the player to the gym); nearly all the rest wander boxes of one or two cells at the player’s own pace, 16 frames (268 ms) a cell, and wait 0.54 to 2.14 seconds between steps. Littleroot holds 6 people, Petalburg 7, Mauville 10, of whom 2, 3 and 6 carry no hide flag.18
  • A routine is a few timed points and a key; a memory is one flag a day. Stardew Valley writes a villager’s day as a string of timed points (Pierre’s regular day has 7) and picks which day applies from 22 key formats in three groups, first match wins: one special key checked for everyone, then 5 marriage formats for a married villager, who uses no others, or 16 normal ones for everyone else; talking to a villager once a day is worth +20 friendship. New Horizons gives +1 of 255 for the first conversation of the day and teaches one Reaction a day.29101112
  • Other people’s traces fill an empty town, in fixed slots, and they decay. Emerald’s record mixing carries 5,188 bytes of another player’s world; Join Avenue’s fans fill the shop slots real visitors leave empty at 75% of a visitor’s worth (Serebii’s account); Death Stranding’s structures are “destroyed by Timefall after some time”; Journey shows one stranger at a time, with no names until the credits and one chime.413145
  • Live presence is a buffer, not a send rate. Habbo’s fan-built server emulator steps every room on a 500 ms cycle; Gaffer on Games buffers “3X the packet send rate”; in a model of Kiradex’s walk at the series’ 3.75 and 7.5 tiles a second, drawing other collectors on a clock 350 ms behind the estimated server time gives 0 backwards frames and 0 starved frames at up to 80 ms of jitter, where 100 ms starves 125 to 456 of the 600 frames drawn while the sender is sending.15167
  • The rules for children have dates on them. Game Center restricts children “to sending and receiving preset messages”; Apple’s documentation says a game with a custom multiplayer feature “should disable it” when Screen Time restricts multiplayer; the amended COPPA rule, in force for compliance since April 22, 2026, requires a written data retention policy with a deletion timeframe.171819
  • Kiradex today differs from its own plan in four places. The plaza’s collectors stop when nobody is in the room, though server/app/npcs.py says “A town is never empty”; they step every 1.0 s against a configured 0.7 s; the app sends one move per tile (4 a second walking, 6.0 to 6.4 running) where the plan’s reasoning said 8 to 10 Hz; and nothing reads Game Center’s restriction flags, though the plan builds identity and parental control on Game Center.62021222324
  • What this gives Kiradex. A brief for eight townspeople with routines keyed by the app’s own day-parts on one clock per room and positions computed from that clock, the last eight visitors’ walks replayed as nameless echoes in a plain figure the server picks, kept seven days and sent with no id, a once-a-day hello that never decays, a 350 ms render buffer, a line book of six branches with 8 to 12 whole sentences each, and seven safety settings, each with a check a script, a test or a capture can pass or fail.7119

1. Townspeople, measured: Emerald, Stardew Valley and Animal Crossing

Every small social world meets the same question on its first night: what does a player see when they walk into the square and nobody else is there? The canon has three answers, and this post takes them in turn. The first is townspeople who keep their own lives, so the town is busy whether or not anyone is online. The second is traces of other people, left behind by players who are not there now. The third is live presence done well when people are there, bounded by the rules for a world children can be in. The first answer is the oldest and the best measured, because the source of one of its masters is public.

What Emerald’s people do

Pokémon Emerald was read from pret’s decompilation, a shallow clone of pokeemerald at commit 731ad5b, and counted by a script, measure_npcs.py, that reads the movement-type constants and every town and city map’s object events.1 Emerald defines 81 movement types, 0x00 to 0x50. Grouped by what the person on screen does, 24 walk a fixed loop of four legs, 17 stand and face (fixed, alternating or looking around), 16 walk, jog or run in place, 8 copy the player, 5 wander at random inside a range, 4 pace back and forth, 4 are hidden or disguised, and the last three are NONE, the player, and the berry tree, which is an object rather than a person.125

The towns use few of them. Across the 16 town and city maps there are 172 object events, and not all of them are people: 6 are item balls, 2 are moving trucks, 1 is a boat, and 5 are creatures. The script sorts them by their graphics_id and counts the 158 people on their own.18 Only 11 of the 81 movement types appear among the people. 113 of the 158 (71.5%) stand and face, 43 (27.2%) wander inside a range, and 2 (1.3%) walk in place. The commonest single types are FACE_DOWN with 32, FACE_RIGHT with 23, LOOK_AROUND with 20, FACE_UP with 19 and WANDER_AROUND with 17.18

Those 158 are not all residents. 58 of them carry a hide flag, a story flag that takes them off the map, and 41 of the 58 use a villain team’s sprite, the rival’s or a named character’s, so the 58 are mostly actors in the story’s scenes; 54 of them stand. The 100 people with no hide flag, the ones on the map on every visit, split differently: 59 stand and face, 39 wander inside a range and 2 walk in place. So the residents a player sees most of the time are six in ten standing and nearly four in ten wandering; the seven in ten of the whole count comes from adding the actors, who nearly all stand. These are default movement types, what a person does when no script is moving it; a story script can still walk a standing person, as Petalburg’s gym boy, who looks around by default and carries no hide flag, walks the player to the gym. The count describes the town at rest, not every scene in it.18

A stacked bar chart of the people among Emerald's town object events, by movement type. All 16 towns and cities, 158 people: 113 stand and face (71.5 percent), 43 wander a box (27.2 percent), 2 walk in place. The 100 with no hide flag: 59 stand (59 percent), 39 wander (39 percent), 2 walk in place. Littleroot, 6 people: 3 stand, 3 wander. Petalburg, 7: 5 stand, 2 wander. Mauville, 10: 8 stand, 2 wander.

Six in ten of the townspeople always on Emerald’s maps have a stationary default movement type, and seven in ten once the story’s removable actors are counted; the wanderers keep to boxes of one or two cells. Scripted scenes, which can walk anyone, are not counted.26

Three towns of different sizes show the same shape. The table counts people only; the left-out object events are the two trucks in Littleroot and three item balls, two in Petalburg and one in Mauville. The last column counts the people with no hide flag, by what they do.1

Town People Stand and face Wander inside a box Wander ranges (x, y) With a hide flag No hide flag (stand, wander)
Littleroot 6 3 (face up) 3 (WANDER_AROUND) (1, 2), (2, 1), (2, 1) 4 2 (0, 2)
Petalburg 7 5 (2 look around, 2 face up, 1 face down) 2 (1 around, 1 up and down) (1, 1), (0, 1) 4 3 (2, 1)
Mauville 10 8 (2 look around, 2 face up, 2 face left, 1 face right, 1 face down) 2 (left and right) (1, 1), (1, 0) 4 6 (4, 2)

A wanderer’s box is enforced one cell at a time: before a step, IsCoordOutsideObjectEventMovementRange refuses any target that lies outside the object’s range from where it was placed, so a wanderer orbits its home cell rather than traveling.27 The hide flags are the other half of the population. Four of Littleroot’s 6 people, four of Petalburg’s 7 and four of Mauville’s 10 carry a flag that removes them when the story moves on, so a town’s population is a function of the player’s progress: people leave and arrive because something happened.1

How often they move

The timing is in the same file. A wandering or looking-around townsperson waits 32, 64, 96 or 128 frames, picked at random from sMovementDelaysMedium, before its next step or turn: 0.54, 1.07, 1.61 or 2.14 seconds at the Game Boy Advance’s 59.7275 Hz, a mean of 1.34. So do the two face types that alternate between opposite directions, FACE_DOWN_AND_UP and FACE_LEFT_AND_RIGHT. The face types that alternate between two neighboring directions or among three pick from sMovementDelaysShort, 32, 48, 64 or 80 frames, a mean of 0.94 seconds, and the two rotating types wait a fixed 48 frames. A third table, sMovementDelaysLong, is marked // Unused in the source, and no movement type reads it.127

The step itself is the player’s. PlayerWalkNormal calls GetWalkNormalMovementAction, the same action a wanderer’s step uses; MOVE_SPEED_NORMAL maps to sStep1Funcs, which moves 1 pixel a frame for 16 frames, one 16-pixel cell in 268 ms, 3.73 cells a second. Running is MOVE_SPEED_FAST_1, sStep2Funcs, 8 frames a cell, 134 ms, 7.47 cells a second.127 Put the two rows together and a wanderer is in motion for 268 ms out of every step plus a wait, 0.81 to 2.41 seconds: between 11 and 33 percent of the time, per step taken. That is an upper bound. When the direction a wanderer picks is blocked, by a wall or the edge of its box, MovementType_WanderAround_Step4 sends it back to face and wait again without moving, so its real share of time in motion is lower. The rest it stands, or turns.127

A timeline chart over six seconds. Four rows of an Emerald wanderer, one per wait length: with a 32-frame wait it is in motion 33 percent of the time, 64 frames 20 percent, 96 frames 14 percent, 128 frames 11 percent. A fifth row, a Kiradex collector on a walk leg, moves for 250 ms of every 1.0 s, 25 percent.

An Emerald wanderer moves in single steps between long waits; Kiradex’s collectors, measured in section 6, move in bursts a tile long while they are supposed to be walking.26

On my reading, three details carry the effect. Nothing in the town walks faster or slower than you do, so nothing reads as a different kind of thing. The pauses are longer than the steps, so the town is stills punctuated by motion, which is why it never looks crowded with 6 to 10 people in it. And the population is written into the story through the hide flags, so the town changes because the player did something, not because a timer fired.

Emerald’s day is settled on arrival

Emerald keeps a day, but not with a clock that runs while nobody plays. It reserves 64 daily-flag slots after DAILY_FLAGS_START and uses 12 of them: nine berry gifts (a contest lobby’s, the Berry Master’s and his wife’s, five route or town givers’, the flower shop’s), the Secret Base’s daily flag, the lottery ticket, and FLAG_DAILY_APPRENTICE_LEAVES.228 When the player comes back, UpdatePerDay runs once with the number of days that have passed, and it also runs from DoTimeBasedEvents during play; it calls, in order, ClearDailyFlags, UpdateDewfordTrendPerDay, UpdateTVShowsPerDay, UpdateWeatherPerDay, UpdatePartyPokerusTime, UpdateMirageRnd, UpdateBirchState, UpdateFrontierManiac, UpdateFrontierGambler, SetShoalItemFlag and SetRandomLotteryNumber.23 The trend, the television and the weather all move by elapsed days, computed at the moment of return.3 Nothing happened while the cartridge was off; the town acts as though it had.

Stardew Valley: a schedule is a string

Stardew Valley is the modern reference for townspeople with lives. Its wiki’s Villagers page lists 6 bachelors, 6 bachelorettes, 22 villagers who cannot be married and 12 who cannot be given gifts, so 34 giftable villagers, and says “Each villager has a daily routine, so they can be located in different sections of town depending on the in-game time of the day and weather.”229

The routine is data. Each villager has a file under Content/Characters/schedules/, and each entry is one string of slash-separated points, each point <time> [location] <tileX> <tileY> [facing] [animation] [dialogue], with the time in 24-hour form without a colon and the facing 0 for up, 1 right, 2 down and 3 left.9 Abigail’s Wednesday, as the page gives it, is 1000 ArchaeologyHouse 11 9 0/1800 Town 47 87 0/2200 SeedShop 1 9 3 abigail_sleep: three points, a walk between each, and an animation at the last.9 Pierre, who keeps the general store, has 7 timed points on a regular day (6:00 AM at his counter, 7:00 AM in the aisles, 8:30 AM back at the counter, then 5:00 PM, 7:00 PM, 9:00 PM and 11:00 PM through the aisles, the kitchen, a bookcase and bed), and his page lists 6 variants of his schedule: Green Rain, the restored bus on Spring 15, the Desert Festival, rain, Friday and the regular day.230

The intelligence is in the keys. Which schedule runs on a given day is decided by 22 key formats in three groups, each tried in a fixed order, first match wins. One special key, GreenRain, is “checked first, regardless of marriage status.” A married villager then tries only the 5 marriage formats, from marriage_<festivalID> through a date, marriageJob and the weekday: “Married NPCs don’t use any other schedule keys. If the marriage keys don’t match, they won’t have a schedule for that day.” Every other villager tries the 16 normal formats, from <festivalID>, <season>_<dayofmonth>, <dayofmonth>_<hearts>, <dayofmonth>, bus, rain2 (a “50% chance of applying on rainy days”) and rain, then the weekday-and-hearts keys and the weekday, to <season>, spring and finally default.29 So, on my reading, one villager has many possible days, the same few points recombine into a life, and the hearts keys mean a villager who likes you keeps a different day. The page’s own note on limitations says how the day is computed: when an NPC is added to an existing save, “they generally don’t follow their schedule correctly until you’ve slept once in-game (which triggers their first day update).”9 Like Emerald’s, Stardew’s day is worked out at the day’s boundary, not advanced continuously.

Friendship is the daily memory, with a cost attached. A heart is 250 points; “talking to them once per day (+20)” is the first item on the wiki’s list of ways to raise it; a villager takes one gift a day and two a week, with a birthday gift multiplied by 8; and not talking costs points every day, 2 for most villagers and 10 after a bouquet, until the meter is full or reaches its cap, and 20 for a spouse, whose decay never stops.10 Heart events, the scripted scenes, open at heart thresholds, and “most events can be viewed anytime (with some time restrictions) or out of order.”10 The villager also acts on you while you are away: at 3 hearts Pierre “will send you a recipe in the mail,” and at any level above zero he may send 250g or more.30

Animal Crossing: the villager who knows you came by

New Horizons reduces the villager who knows you talked to them today to a single point. Friendship runs from 0 to 255 and starts at 25; the first item on Nookipedia’s list of what raises it is “+1 point” for “speaking to the villager for the first time each day”; a villager takes one gift a day; and at 150 points a villager has a 6% chance of giving you their photo with a gift, rising by 0.04% a point to 10.2% at 255.11 On my reading it is a flag rather than a meter, because the player never watches it move.

The villagers’ visible life is small and their own. Each has one of six hobbies (Education, Fashion, Fitness, Music, Nature, Play), and in New Horizons “a villager always has one hobby that doesn’t change”; villagers go after bugs and fish but “still will not catch either of them,” exercise, read, and sing along to a nearby music player, and since the 2.0 update they “invite the player to their house, ask the player for an invitation” or turn up for “a random visit.”3132 Eight personalities shape what they say, four for male villagers (lazy, jock, cranky and smug) and four for female (normal, peppy, snooty and big sister), of which “Smug and big sister were introduced in New Leaf, with the other six being present since Doubutsu no Mori.”33

Towns stayed small across the series.32

Game Villagers at the start Most villagers
Animal Crossing 6 15
Wild World 3 8
City Folk 6 10
New Leaf 5 10
New Horizons 2 (one jock and one big sister, from 83 possible) 10

Wild World also changed the pace: there “the villagers walk at a much slower pace than the player,” which City Folk kept.32 That is the opposite of Emerald’s rule, and on my reading both work for the same reason: a villager who ambles reads as a resident, and a townsperson who steps at your pace and then waits reads as one too. What breaks the effect is a person who moves at neither pace, which is the Kiradex problem in section 6.

The series’ preset expression is the Reaction, and it is itself a gift from the townspeople on a daily ration. New Horizons had 44 Reactions at 1.0.0 and 44 more by 2.0, 88 in all, and “The player can learn one Reaction per day,” some only from certain personalities or at high friendship.212

2. Other people’s traces: what fills a town when nobody is online

Townspeople keep a town busy, but they are the same people every day. The second answer is the one every studied game reached for when it worried about an empty world: fill it with traces of real people, left by players who do not need to be online now. Emerald did it with a link cable.

Record mixing: another player’s world, in fixed slots

When two Emerald players mix records, each game sends the other a fixed structure, PlayerRecordEmerald, of 11 kinds of record in 0x1444 bytes, 5,188 in all.434 The counts that matter for a sense that others were here are the slots: 20 Secret Bases, 25 television slots (5 normal and 20 more), 16 news items, 5 trend phrases, and 2 apprentices out of the 4 a game keeps.4 On my reading, that is the point of the slots: your town changed because someone else had played, with a friend’s bases, their programs and their phrase carried into your game.

The cleanest case is a single person. Mauville’s Pokémon Center holds one Old Man, who is one of five (the Bard, the Hipster, the Trader, the Storyteller and the Giddy). Which one a new game gets is chosen by (trainerId % 10) / 2, with the source’s own comment “Determine man based on the last digit of the player’s trainer ID,” and when records are mixed, ReceiveOldManData copies the partner’s Old Man over yours.435 The resident of your town is literally another player’s townsperson.

The Hipster rations vocabulary by contact. His script sets FLAG_UNLOCKED_TRENDY_SAYINGS and teaches one word if his taughtWord is false, then sets it true; the only call that sets it false again, ResetHipsterFlag by way of ResetMauvilleOldManFlag, is made from exactly one place, the end of ReceiveOldManData in record_mixing.c.35 So a Trendy Saying unlocks once each time record mixing brings the Hipster, plus once for a player who starts with him, which by the selection rule is a player whose trainer ID ends in 2 or 3. The first post in this series states the rule the same way.3635 The vocabulary grows by meeting people, not by waiting.

The trend, in arithmetic

The trend phrase, two Easy Chat words that the town of Dewford treats as the current saying, is the one trace Emerald scores. Its source comment says that a phrase which is “boring” will “lose trendiness over time until it reaches 0, at which point it will stop being boring and gain trendiness until it reaches maxTrendiness (then it becomes boring again and the cycle repeats).”37 A phrase’s peak is drawn from 30 to 127 by up to three nested Random() % 98 draws. Taking each draw as independent and uniform over its 98 values, the peak’s mean is 62.9 and 81.3% of peaks are 80 or under; its starting score is uniform between 30 and the peak, a mean of 46.5; and the score moves 5 for every elapsed day, settled in UpdatePerDay like everything else.383 Those figures are an approximation of the code, not its exact output: Random() returns 16 bits, so a remainder from 0 to 71 comes up 669 times in 65,536 and one from 72 to 97 668 times, and successive draws come from one generator, not independent dice. Weighting the remainders that way, still taking the draws as independent, moves neither figure at one decimal.3837 As a continuous rate, a peak-30 phrase rises from nothing to its peak and falls back in 12 days, a peak-64 phrase in 25.6 and a peak-127 phrase in 50.8. The game moves the score in whole days, and a score that would pass its peak or zero bounces back by the remainder, so the daily scores do not repeat on those fractional periods: ported day by day from a score of zero, rising, the exact sequence first repeats after 12, 128 and 254 days.3837 Up to 5 trends are saved, and on mixing “their own trends are replaced with their mixing partner’s, unless the phrase is the same, in which case the version with a higher trendiness value is used.”3837

A line chart of Emerald's trend score over 60 days, one point per whole day, for three peaks, each starting at 0 and moving 5 a day, bouncing back at the peak and at zero. Peak 30 rises and falls every 12 days and repeats exactly. Peak 64 rises and falls about every 25.6 days, a continuous approximation; its daily scores repeat exactly only after 128 days. Peak 127 rises and falls about every 50.8 days; its daily scores repeat after 254.

A trend is a slow zigzag sampled once a day: 81.3% of peaks are 80 or under, a rise and fall of about 32 days or less.2638

On my reading this is the right shape for a trace that has to keep a town from going stale: it rises, it falls, its life is set when it is born, and contact with another player can replace it with something fresher.

Easy Chat against the Union Room

Emerald had two ways for players to say things, and they are the two ends of the safety argument in this post. The Union Room, its local wireless lobby, shows 8 group leaders, holds 5 players per wireless group (RFU_CHILD_MAX, 4, plus one), draws 40 sprites and defines 30 activity codes. Its chat is typed: four keyboard pages (UPPER, LOWER, EMOJI, REGISTER), 15 characters a message (MAX_MESSAGE_LENGTH), and 10 registered phrases kept in the save (UNION_ROOM_KB_ROW_COUNT).439 My reading is that typed chat was tolerable there because everyone in the room was within wireless range of you.

Everything else said between players went through Easy Chat. It has 22 groups and 1,815 entries in all. Open from the start are Trainer (27, 6 of them disabled), Status (109), Battle (63), Greetings (42), People (75), Voices (63), Speech (60), Endings (69), Feelings (69), Conditions (69), Actions (78), Lifestyle (45), Hobbies (54), Time (45), Misc (42) and Adjectives (36), plus a 202-entry list of names, each of which opens only once the player has seen that species; locked are Events (29) and two move lists (154 and 200) until the game is cleared, the Trendy Saying (33) until the Hipster’s flag, and a 251-entry national name list.3840 Leaving out the 6 disabled Trainer entries, which no player can pick, that is 940 words, not counting names, open from the first hour. One switch in easy_chat.c decides which groups unlock, and a second decides each entry: a name by whether its species has been seen, any other word by its enabled field.3840 Phrases are fixed grids: a profile is 2 by 2, 4 slots; a battle opening 2 by 3, 6; mail 2 by 5, 10 slots holding up to 9 words; the trend phrase and the good saying 2 by 1; the questionnaire 2 by 2, 4 words.3840

A composable vocabulary of 940 words is expressive, and on my reading it is also a vocabulary from which a determined child can spell things. That is the trade the Kiradex brief refuses in section 7: whole sentences, never words.

Strangers’ traces in other games

Every other studied game that worried about an empty world reached for other players, most of them for the traces players leave behind. The sources differ in strength, and each paragraph names its own.

Dark Souls (FromSoftware, 2011). Wikipedia, citing its own source: “The player can see ghostly images of other players, activate bloodstains that show how other players died, and leave messages using preset phrases.”41 The Daily Telegraph gave it the “Best Integration of Online Features” award.41 Bandai Namco Europe’s page for the remaster lists “The Way of the Multiplayer (up to 6 players with dedicated servers)” among its key features and says nothing more about the layer of ghosts and messages; FromSoftware’s own description was not reached.42 The page does not say whether the ghostly images replay players who have gone or show players connected at that moment; it lists them, with the bloodstains and the messages, among the “online features” the game “integrates” into “the single-player world,” and puts “Direct multiplayer,” summoning and invasions, in the next sentence.41

Journey (thatgamecompany, 2012). Wikipedia again: “In each level, the player may come across one other player temporarily connected to their game”; the two “cannot communicate via speech or text and cannot see each other’s names until after the game’s credits”; “The only form of communication between the two is a musical chime.” The developers “felt having text or voice communication or showing usernames would allow players’ biases and preconceptions to come between them and the other player.”5 That is the safety argument in design form, made for adults.

Death Stranding (Kojima Productions, 2019). Sony’s page: “Donate valuable resources to rebuild structures in your world and others’, and offer likes in support of player structures that appear in yours.”43 Wikipedia adds that players “can leave supplies, structures, and messages that can be viewed and used by other players, although structures will eventually be destroyed by Timefall after some time,” and that “The player does not directly encounter other players in the world.”14 Traces decay, so the world does not silt up.

Splatoon (Nintendo, 2015). Players’ Miiverse posts “appear in-game as graffiti on various buildings,” per Wikipedia, citing its source. The graffiti came from posts to the game’s Miiverse community, so, on my reading, the trace depended on Nintendo’s Miiverse service rather than on the game’s own online play.44

The three later Pokémon features rest on one source, Serebii, a long-running fan site; pokemon.com’s pages for Black 2 and White 2 and for Sun and Moon do not mention Join Avenue or Festival Plaza, and no publisher page on GO’s gyms was saved, so read each of the next three paragraphs as Serebii’s account rather than the publisher’s.45

Join Avenue (Black 2 and White 2, 2012). Per Serebii, the avenue “starts off as an empty pathway,” and people arrive to open shops, which “is done automatically whenever you connect with someone,” by PassBy, infrared, the Union Room, Wi-Fi, the GTS and more. There are eight shops; “every 10th person shown to the shop, the shop will rank up,” to Rank 10, with “discounts of 1% for every rank up” to “a 40% discount”; standard visitors are worth “from 100 to 200 points”; and after the Elite Four “various fans will come and visit,” and “If you help a fan rather than another player, they will give 75% of the normal popularity points.”13 On my reading it is the cleanest statement in the canon of a fallback rule: stand-ins fill the slots real people leave empty, and they are worth a little less.

Festival Plaza (Sun and Moon, 2016). Per Serebii, the plaza “will propogate itself with players you will find online and locally” (sic), and “This is not limited to people on your friend list”; guests who want something say so, pay Festival Coins when you help, and a helped guest can be made a VIP, which makes them “more likely to appear in your plaza in the future”; plaza rank costs 6 coins at level 1, rising to 300 from level 101.46 Presence through avatars: what you interact with is another player’s avatar, and Serebii describes the people behind them as “all players that are also playing online,” who “when they see you” can “challenge you to battles or request trades.” On that account the plaza’s figures stand for players who are online themselves; with Journey, it is one of the two features in this list that the sources describe as live presence rather than a trace.46

Pokémon GO gyms (the 2017 rework). Per Serebii, a gym holds up to six defenders; each lost battle lowers a defender’s motivation and “Once their Motivation has dropped to 0, then they are removed from the Gym”; berries restore it; and a defender earns 1 coin for every 10 minutes, “capped at 50 Coins earned a day.”47 The place keeps another player’s companion on show while they are away, and it decays unless the community feeds it.

The shared pattern, on my reading of all eight: a small fixed number of slots (8 shops, 6 defenders, 1 companion, 20 bases), traces that decay or rotate (Timefall, motivation, the trend’s cycle), stand-ins worth less than people, and, apart from Festival Plaza’s battles and trade requests, no live channel between strangers beyond a preset phrase or a chime.

3. Live presence: rates, buffers and the walk past

The third answer is the one people think of first: when other players are online, show them, moving, in the same square. Two small 2D social worlds, Habbo and Club Penguin, show the two ends of grid presence. Neither company published its rates. What I have is two open-source fan servers and a fan client, written to be compatible with the original clients, so the numbers below are evidence of what those clients expected, not Sulake’s or Disney’s published figures.154849

Habbo: one step per server cycle

Arcturus Morningstar, an open-source reimplementation of Habbo’s server, runs each room on a fixed 500 ms cycle (scheduleAtFixedRate(this, 500, 500, TimeUnit.MILLISECONDS)) and calls each walking unit’s cycle once per room cycle; it marks an avatar idle at IDLE_CYCLES = 240, 120 seconds, and removes a non-owner at IDLE_CYCLES_KICK = 480, 240 seconds.15 Nitro, an open-source Habbo client, moves a room object over a fixed DEFAULT_UPDATE_INTERVAL of 500 ms: on each update from the server it takes the change to the new location and lerps by the time elapsed over 500, clamped at the end, then zeroes the change.49 That a cycle is exactly one tile is my reading of the two together (a 500 ms server period drawn as a 500 ms lerp); I did not read the server’s RoomUnit to confirm it. If the reading holds, the render is one server period behind by construction, so it never runs out of data while the server keeps pace.

Club Penguin: a destination, not a stream

Houdini, an open-source Club Penguin server by the Solero project, shows a different design. A move is one sp message carrying a destination, x and y, relayed to the room unchanged, and the client walks there itself. A safe-chat line is one ss message carrying a number, and the other kinds of preset speech travel the same way: sj for a joke, sma for a mascot’s message, sl for a stage line, sg for a tour guide’s line, se for an emote, each relayed as an id.48 The server rate-limits emotes and actions to one a second and frame changes to one every half second, and a heartbeat task checks the connected clients every 61 seconds and closes any that sent no heartbeat in that time.48 Movement is click-to-destination, not per tile, and speech is a number looked up on the other side, which on my reading is why a word filter never had to see most of what was said.

Neither world sends at the 10 to 60 updates a second of the physics demonstrations below.16 For a world where people walk from tile to tile, the step or the destination is the update.

Gaffer on Games: render behind, between two known points

The method that governs the client side is laid out in Glenn Fiedler’s “Snapshot Interpolation” (Gaffer on Games, November 30, 2014). Buffer what arrives and render between two delayed updates: “In effect, we’ve traded a small amount of added latency for smoothness.”16 His rule of thumb for the delay is “enough delay so that I can lose two packets in a row and still have something to interpolate towards”; at 2 to 5% packet loss what works best “is 3X the packet send rate. At 10 packets per-second this is 300ms,” plus a frame or two for jitter, so his demonstrations ran at 350 ms. At “30 snapshots per-second” the same protection costs 150 ms, and “60 packets per-second needs only 85ms.”16 Extrapolation, guessing ahead, “doesn’t work very well for rigid bodies because their motion is non-linear and unpredictable.”16

Kiradex’s plaza runs over WebSockets to a FastAPI server,23 and WebSockets ride on TCP, where nothing is lost but a retransmitted packet arrives late. On my reading that makes the budget for a WebSocket world jitter rather than loss, and it makes a grid walker the easy case for Fiedler’s method: a walker on a grid moves in straight lines between tile centers and stops dead, so there is nothing to extrapolate and nothing non-linear to hide.

A model of the walk past

To size the buffer for Kiradex, I simulated another collector walking past, using the logic of the app’s own rig as read on October 5. The script, measure_remote_walk.py, models two things. Today’s behavior, in the rig’s own arithmetic: a step’s progress is a 32-bit Float, advanced each frame by Float(deltaTime) times 4 tiles a second; every incoming move re-plans from the walker’s last whole tile and resets the step in progress to zero, even mid-step; a path longer than 6 tiles is a jump; and the walker is drawn on whole pixels. The rig draws every other collector at the walk’s 4 tiles a second, because only the player’s own walk is ever marked as a run. And the alternative: snapshot interpolation on a steady render clock, the estimated server time minus a delay of 100 to 350 ms, drawing between the two received updates whose stamps bracket the render clock.750 For today’s rig, the sender sends one move per completed tile at today’s measured rates: every 250 ms walking at 4 tiles a second, and every 156 ms running at 6.4, which is the run’s nominal rate (the motion post in this series models the app’s run at 6.0 tiles a second at 60 Hz, because each tile’s overshoot is dropped). For the buffer, the sender also moves at the series’ motion contract, the motion post’s brief of 16 ticks a tile walking and 8 running at 60 Hz, 3.75 and 7.5 tiles a second, which is what section 7 builds to. The network adds uniform jitter of 0, 30 or 80 ms, and frames are drawn at 60 a second for 10 seconds of walking.72122

The arithmetic matters. In 32 bits, 15 frames of 1/60 second at 4 tiles a second sum to exactly 1.0, so a step takes 15 frames, exactly the sender’s 250 ms; in 64-bit arithmetic the same sum is 0.9999999999999999, the step takes 16 frames, and a model written that way finds snap-backs on a steady walk that the rig’s own arithmetic does not produce.7

This is a model, and its assumptions are the reason to treat its numbers as a sizing guide rather than a result. It assumes a straight open road, so a path’s length is the Manhattan distance; a diagonal step, which takes √2 as long in the rig, is not modeled; jitter is uniform; every frame’s deltaTime is exactly 1/60 second, where a phone’s varies; the 32-bit operations run in the code’s order with no fused multiply-add; nothing in it was captured from two devices. So whether a steady walk with no jitter ever snaps on a phone is a question the model cannot settle: a frame time a hair off 1/60 can leave a step one rounding short of 1.0. The reset itself, which fires whenever a move arrives mid-step, is a reading of the source, not a model result. The buffer half also assumes two things its result depends on: the renderer’s estimate of the server’s clock is exact, and an update takes no time to arrive beyond its jitter. A real client has to estimate the server’s clock, and any error in that estimate, or any steady one-way delay it does not account for, comes straight out of the buffer.7

Two panels of grouped bars over six cases, walking and running, each at 0, 30 and 80 ms of jitter. Left, today's rig, with the sender at 4 tiles a second walking and a nominal 6.4 running: 0, 7 and 16 frames drawn moving backwards walking, 45 in all three running cases. Right, with a buffer, at the motion contract's 3.75 and 7.5 tiles a second, frames with nothing to draw toward out of 600: walking, 355, 400 and 456 at 100 ms behind, 0, 0 and 27 at 300 ms, 0, 0 and 6 at 325 ms, and 0 at 350 ms; running, 125, 188 and 304 at 100 ms and 0 at 300 ms and more. Every buffered run draws 0 backwards frames.

In the model, today’s rig draws a passing collector moving backwards when a move arrives mid-step, on every run and on any walk with jitter; at the motion contract’s speeds, a 350 ms buffer never does and never starves.26

Today’s rig, walking with no jitter, draws the walker cleanly: each step ends on the frame before the next move arrives, so there are 0 snap-backs, 0 jumps and 0 backwards frames in 40 tiles. Jitter breaks it. At 30 ms, 13 moves arrive mid-step and reset it, 7 of them late enough in the step to draw the walker backwards, and 1 path is long enough to jump; at 80 ms, 25 resets, 16 backwards frames and 2 jumps. Running, the sender outpaces the 4 tiles a second at which the rig draws it, so at every jitter tested 45 of the 64 moves arrive mid-step, each drawing a backwards frame, with 9 jumps. Whenever it snaps, the walker as drawn falls behind the sender by up to 5.9 to 6.7 tiles before a jump brings it forward; on the steady walk it is never a full tile behind (0.94 at most).7 A snap-back draws the walker backwards by however much of the step it had drawn, up to 14 pixels on a 16-pixel tile in these runs.750

With a buffer the walker never moves backwards: 0 backwards frames in all 60 buffered runs, four speeds by three jitters by five delays. The question is only how often the renderer has nothing to draw toward, counted over the 600 frames drawn while the sender is still sending. At the motion contract’s walk of 3.75 tiles a second, a render clock 300 ms behind starves 0, 0 and 27 frames at 0, 30 and 80 ms of jitter; 325 ms starves 0, 0 and 6; 350 ms starves none. At 100 ms behind it starves 125 to 456 frames in every case at those speeds. Running at 7.5, 300 ms and more starve 0 frames at every jitter tested. At today’s 4 and 6.4 tiles a second the same model starves 0, 0 and 7 walking at 300 ms, and none at 325 or 350.7 On my reading, a render clock 350 ms behind the estimated server time is the number, and the reason is a bound rather than a count. With one move per tile, the update a frame needs is stamped at most one step after the render clock and arrives at most the worst jitter after its stamp. At 3.75 tiles a second a step is 1/3.75 of a second, 266.7 ms, and a step plus 80 ms of jitter is 346.7 ms, so with an exact clock a delay of 350 ms starves no frame for any jitter draw up to 80 ms, with 3.3 ms to spare.7 Those 3 ms are the whole allowance for the clock estimate: an estimate running more than about 3 ms ahead of the server’s clock loses the guarantee and can starve frames. The counts above come from one jitter draw, seed 1, and 325 ms met the bar section 7.4 sets on that draw, by 4 frames, but not on every draw: re-run over seeds 1 to 200, walking at 3.75 tiles a second with 80 ms of jitter, 325 ms starved frames on all 200 and more than 10 on 8 of them, where 350 ms starved none on any.7 350 ms is also the delay Fiedler’s own demonstrations ran at. At one move per tile it is a little more than one walking step of delay, a step being 267 ms at 3.75 tiles a second, which is Fiedler’s “3X the packet send rate” turned around for a world where the packets are steps and, over TCP, arrive late rather than not at all.16

4. The craft, as rules with numbers

Each rule below is traced to a measurement or a quoted source above. Where the rule is my synthesis of several sources, the source column says which.

Element Rule Source
Who moves Of the townspeople always present, about six in ten have a stationary default movement type, standing at a post facing one way or looking around, and nearly four in ten wander a box of one or two cells around its post. Story actors who come and go mostly stand, which moves the whole count to seven in ten and one in four. Emerald’s 100 people with no hide flag: 59 stand, 39 wander, 2 walk in place; all 158: 113 and 43; ranges 1 or 2 cells1
Pace A townsperson steps at the player’s pace and then waits longer than the step took: one 268 ms step, then 0.54, 1.07, 1.61 or 2.14 s, picked at random. A slower amble also works (Wild World); a pace that is neither does not. Emerald’s shared walk action and delay table1; Wild World32
Motion share A wanderer is in motion at most 11 to 33 percent of the time, per step taken; a blocked step only faces and waits. Emerald, arithmetic on the two rows above; an upper bound127
Population Six to ten people make a town; Animal Crossing’s whole villages top out at 8 to 15. Littleroot 6 people, Petalburg 7, Mauville 10, of whom 2, 3 and 6 carry no hide flag1; Animal Crossing’s towns, 8 to 15 at most32
Change Some townspeople leave and arrive with the player’s progress, by flag. 12 of the 23 people in the three towns carry a hide flag1
Routine A day is three to seven timed points; a key chooses which day applies, in a fixed order of specificity, first match wins. Abigail’s Wednesday 3 points, Pierre’s regular day 7; 22 key formats92
The day Settle the day when the player returns, with one run that takes the number of days elapsed; never run a timer while nobody plays. UpdatePerDay3; Stardew’s first day update9
Memory Remember the first talk of the day with one flag per townsperson; keep the reward small. +1 of 255 in New Horizons11; +20 against 250 a heart in Stardew10
New words Ration new expression to one a day, or one per meeting. One Reaction a day12; one Trendy Saying per Hipster arrival35
Traces Others’ traces come in small fixed slots and decay or rotate. 20 bases and 5 trends4; 8 shops13; 6 defenders47; Timefall14; a trend’s rise and fall of 12 to about 50.8 days38
Stand-ins Stand-ins fill the slots people leave empty, and count for less. Join Avenue’s fans at 75%, Serebii’s account13
Strangers Strangers share presence, not words: no names, a chime or a preset phrase. Journey5; Dark Souls41; Game Center for children17
Speech Preset lines travel as ids and answer, not only greet; a whole sentence cannot spell anything a word list can. Club Penguin’s ss ids48; Easy Chat’s 940 open words in grids of 2 to 10 slots38
Updates One update per step on a grid; render remote walkers on a clock a little more than one walking step behind the estimated server time, and never reset a step in progress. Habbo’s 500 ms cycle and lerp (emulator and fan client)1549; the model at 3.75 and 7.5 tiles a second, assuming exact clock sync and no base latency: 350 ms behind gives 0 backwards frames and 0 starved to 80 ms of jitter7
Idle Mark a player idle after two minutes without input, and close a connection that has stopped answering its heartbeat. Arcturus: idle at 240 cycles (120 s), and an idle non-owner removed at 480 (240 s)15; Houdini closes any client that sent no heartbeat in a 61 s window48. The brief’s 240 s without a ping joins the two, my adaptation
Restrictions When Game Center reports multiplayer restricted, including friends only, the custom multiplayer goes, and on my reading that includes replays of real players’ walks: such a player gets townspeople only. Apple’s documentation for isMultiplayerGamingRestricted18; echoes as multiplayer is my reading (section 7.6)
Communication When Game Center reports personalized communication restricted, or the player underage, custom communication goes. Apple’s documentation for isPersonalizedCommunicationRestricted51
Retention Keep children’s data only as long as its written purpose needs, with the deletion timeframe in the notice. 16 CFR 312.10 as amended; compliance from April 22, 202619

5. The Apple way: Game Center’s flags, age ranges, the Guidelines and COPPA

A town that children can walk into is bounded by rules from Apple and from the US Federal Trade Commission, and most of them have dates. This section gives Apple’s and the FTC’s own words, with availability where Apple publishes it. Everything I say about what a rule means for Kiradex is a reading, labeled as one, and none of it is legal advice.

Game Center’s three restriction flags

Game Center’s local player carries three Booleans a game can read before it opens anything social. Their availability is from Apple’s documentation as saved on October 4, 2026, and each discussion is quoted verbatim.185152

Property iOS What Apple says
GKLocalPlayer.isMultiplayerGamingRestricted 13.0 “If this property is true, the local player can’t join multiplayer games. If your game uses a custom multiplayer feature, you should disable it.”
GKLocalPlayer.isPersonalizedCommunicationRestricted 14.0 “If this property or the underage property is true, the local player can’t include personalized messages on invitations or enable voice communication in multiplayer games. If your game includes any custom communication features, you should disable them.”
GKLocalPlayer.isUnderage 4.1 “If this property is true, Game Center disables some features for the local player.”

The first flag’s page adds the detail that matters most: the value comes from Screen Time, which lets a parent allow multiplayer games with everyone, with friends only, or with no one, and “when you configure the setting to friends only, this property returns true for restricted.”18 So a child allowed to play only with friends still reads as restricted, and a game with its own plaza is told to turn it off. The second flag’s page has two sentences that differ in reach. The first names what Game Center itself blocks, personalized messages on invitations and voice; the second asks the game to disable “any custom communication features” of its own, with no exception for preset ones. On my reading a menu of whole preset sentences is a custom communication feature, and the brief treats it as one.51

Game Center for children, and Screen Time

Apple’s Game Center privacy page sets the rule Kiradex already adopted for everyone: “when communicating with other players in Game Center, children cannot send or receive user-inputted text. They are restricted to sending and receiving preset messages. In-game voice chat is disabled for children.”17 It also says “Children’s accounts never make real names visible to friends,” and that a parent can use Screen Time to block “multiplayer functionality, the ability to add friends, and the ability to connect with friends playing the same game.”17 Apple’s Screen Time support page lists the Game Center restrictions by name, among them “Connect with Friends” and “Private Messaging,” each “Allowed or Blocked.”53

Declared Age Range

On June 11, 2025, Apple announced that a Child Account “is required for children under 13,” and that “App developers will be able to request this information through the new Declared Age Range API,” with parents choosing to share a child’s age range “always, for each app request, or never,” “in a way that does not reveal the child’s birth date.”54 The same announcement said age ratings would be “expanded to five categories” by the end of that year, with 13+, 16+ and 18+ for adolescents.54 Kiradex’s world plan names the API as the switch for its junior rules and records the October 2 decision: under 13 by the declared range, no plaza at all; 13 to 15, the plaza with junior rules; 16 and up, or not declared, the full plaza.23 I did not fetch the API’s own reference page for this post, so its minimum iOS version is not stated here.

The App Review Guidelines

Three guidelines bound a social plaza, quoted from the version Apple dates “Last Updated: June 8, 2026.”55

  • 1.2, user-generated content. Apps “with user-generated content or social networking services must include” a method for filtering objectionable material, “A mechanism to report offensive content and timely responses to concerns,” “The ability to block abusive users from the service,” and “Published contact information so users can easily reach you.” Apps that end up “used primarily for pornographic content, Chatroulette-style experiences, random or anonymous chat” and the rest of that list “do not belong on the App Store and may be removed without notice.”55
  • 1.3, the Kids Category. Apps in it “must not include links out of the app, purchasing opportunities, or other distractions to kids unless reserved for a designated area behind a parental gate,” and “should not include third-party analytics or third-party advertising,” with narrow exceptions.55
  • 5.1.4, kids. Apps that “collect, transmit, or have the capability to share personal information (e.g. name, address, email, location, photos, videos, drawings, the ability to chat, other personal data, or persistent identifiers used in combination with any of the above) from a minor must include a privacy policy and must comply with all applicable children’s privacy statutes,” and “the parental gate requirement for the Kid’s Category is generally not the same as securing parental consent” under those statutes.55

Kiradex’s plan takes the second of the two paths its design document draws from the Guidelines: outside the Kids Category, rated 9+ or 12+ (the rating is not yet chosen), under 5.1.4.23 On my reading “the ability to chat” in 5.1.4’s list means a preset-line plaza still needs the privacy policy, whatever else it avoids.

COPPA as amended

The FTC’s amended Children’s Online Privacy Protection Rule was published in the Federal Register on April 22, 2025 (document 2025-05904, 90 FR 16918). It “is effective June 23, 2025,” and “Except with respect to § 312.11(d)(1), (d)(4), and (g), regulated entities have until April 22, 2026 to comply.”19 The FTC’s January 16, 2025 release, on a 5-0 vote, summarized the change: separate verifiable parental consent to disclose children’s information to third parties “related to targeted advertising or other purposes,” and retention “for as long as reasonably necessary to fulfill a specific purpose,” so that “operators cannot retain the information indefinitely.”56

Three passages of the rule text bear on a plaza that remembers anything.

  • Retention, § 312.10. “Personal information collected online from a child may not be retained indefinitely. At a minimum, the operator must establish, implement, and maintain a written data retention policy that sets forth the purposes for which children’s personal information is collected, the business need for retaining such information, and a timeframe for deletion of such information.” The policy goes in the online notice.19
  • Persistent identifiers, § 312.2. Personal information includes “A persistent identifier that can be used to recognize a user over time and across different websites or online services,” such as “a customer number held in a cookie, an Internet Protocol (IP) address, a processor or device serial number, or unique device identifier.”19
  • Internal operations, § 312.5(c)(7). Consent is not required “Where an operator collects a persistent identifier and no other personal information and such identifier is used for the sole purpose of providing support for the internal operations of the website or online service,” with notice.19

The amended § 312.8 also requires a written information security program for children’s data.19 My reading of what this means for a plaza that replays visitors’ walks is in the brief, labeled; WORLD.md section 3 asks for a lawyer to read the final design, and the October 2 decisions put that off until the app has traction, so the reading stands until then.23

What it costs

Nothing in this section was measured on a device. Reading three Booleans on GKLocalPlayer after authentication is not timed here; neither is the memory or CPU of a 350 ms render buffer for up to 39 other collectors in a room of 40.21 On my reading neither can matter beside a frame’s drawing, but that is a reading, and the brief’s checks are behavior, not timings.

6. The case study: Kiradex’s plaza, measured on its own code

Kiradex World is the pixel town inside Kiradex, my card-collecting app: a 40-by-30 plaza drawn in 16-pixel tiles, served by a small FastAPI and WebSocket server that keeps presence in memory and stores nothing, apart from what its web server logs by default (section 7.6, setting 6).212357 I read the server and the app’s world code on October 5 from the working tree, without changing anything, and drove the server’s own classes on a simulated clock with two scripts, so the numbers in this section are the code’s behavior rather than my reading of it.21620 The repository is private, so files are named by path. These are differences between the plan in docs/WORLD.md, the code’s own docstrings and what the code does; none of them is a defect anyone hid, and the plan already lists part of the fourth as not yet built.

What is there

The server holds 23 preset lines, 14 for players (indices 0 to 13) and 9 for the town’s own collectors (14 to 22); rooms of 40; a limit of 8 moves a second and one line every 2.0 seconds per player; a town clock that ticks every 0.5 s (TICK_SECONDS in server/app/main.py); a 60-second cooldown on showing a card to the same collector; and arrival at tile (19, 13) of the 40-by-30 plaza.2120 Four scripted collectors live on the server so that everyone in a room sees the same ones: Moss, Prism, Comet and Dawn, each with 4 waypoints on loops of 18, 22, 30 and 32 tiles, a kind of card each would like to be shown (vintage, holo, any, Japanese) and 2 or 3 lines each. server/app/npcs.py sets STEP_SECONDS = 0.7, pauses each collector at a waypoint for a uniform 3 to 8 seconds, and has it say a line every uniform 20 to 40 seconds, the first after 8 to 20.2120

That is the right instinct, on my reading: townspeople on the server rather than in each phone, lines on a slow clock, and a want each, so a collection has somewhere to matter. Measured, three things undercut it, and a fourth is a gap between plan and code.

1. The walk is stop-start

measure_npc_cadence.py imports server/app/npcs.py and rooms.py, builds the plaza and the four collectors, and advances them on the real 0.5 s tick for one simulated hour.6 Every one of the 6,253 intervals between steps within a leg is exactly 1.0 second, not 0.7: a step fires on the first tick at or after its next_move, so 0.7 seconds rounds up to two ticks. That is 1.0 tile a second against the 1.43 the constant implies. Pauses before a leg average 6.75 seconds (4.5 to 9.0, over 1,202 of them), and lines average 30.7 seconds apart across 465 intervals between one collector’s consecutive lines (469 lines in the hour).6

The client draws any step in 250 ms: PlazaRig.swift sets tilesPerSecond to 4 at line 101.50 So a collector walking at a tile a second is drawn in motion for 25 percent of each leg and standing still for the other 75 percent, between every pair of tiles.6 Emerald’s wanderers step at the player’s pace and then wait; Kiradex’s collectors move at the player’s pace in bursts one tile long while they are supposed to be walking, which reads, on my reading, as neither a resident’s amble nor a walk (the bottom row of the timeline figure in section 1).

2. Another collector walking past snaps back

When the server relays another collector’s move, PlazaRig.move(other:to:facing:) (lines 526 to 542 of PlazaRig.swift) plans a path from the walker’s last whole tile, sets the walker’s steps to that path and sets progress = 0 on every message, even when a step is half drawn; a path longer than 6 tiles is a jump.50 The model in section 3, in the rig’s own 32-bit arithmetic, puts numbers on it. A steady walk with no jitter never snaps, because each step ends just before the next move arrives. With 30 or 80 ms of jitter, a 40-tile walk is reset mid-step 13 or 25 times, 7 or 16 of them drawn backwards. Running, the rig draws the walker at the walk’s 4 tiles a second, so 45 of 64 moves arrive mid-step at every jitter tested, with 9 jumps; and whenever it snaps, the drawn walker falls up to 5.9 to 6.7 tiles behind the sender.7 Pixel-Art Motion, an earlier post in this series, reads the same snap-back from the code for the player’s own second tap mid-step; the rule its brief sets, never reset a step in progress, is the rule this brief applies to other collectors.22

3. The town stops when it is empty

The module docstring of server/app/npcs.py says of the collectors: “A town is never empty, and it has somewhere for a collection to matter.”20 Room.tick in server/app/rooms.py says otherwise in its own docstring, “A room with nobody in it stands still,” and does it: when the room has no players it returns at once, so the collectors freeze wherever they were.206 The script measures what the first arrival then sees: driving fresh collectors to 10,000 simulated seconds in one tick produces four lines at once, one from each collector, standing where it stood; nothing happened in between.6 And because the server stores nothing, the first collector in on a quiet morning sees the same four people and no sign that anyone else was ever there. A search of Kiradex/ and server/app/ finds nothing that records a visit or a daily conversation.24

4. Rates, and Game Center’s flags

Two differences are between docs/WORLD.md and the code. The plan’s section 5 keeps, as the reasoning that led to the server, a design in which clients send position and heading at 8 to 10 Hz.23 The app sends one move per completed tile instead: today 4 a second walking, and 6.4 running at the run’s nominal rate (6.0 at 60 Hz in the motion post’s model of the code), under the server’s 8-a-second limit either way; the series’ motion contract, 16 ticks a tile walking and 8 running at 60 Hz, would make them 3.75 and 7.5, still under it (section 7.4).2122 On my reading per-tile is the better design for a grid, and the brief keeps it; the plan’s line is the one to update.

The plan’s section 3 builds identity on Game Center so that “a child’s Game Center is controlled by the parent in Screen Time (multiplayer on/off, adding friends on/off, sharing the friend list with games on/off).”23 Nothing in Kiradex/ or server/app/ reads GKLocalPlayer.isMultiplayerGamingRestricted, isUnderage or isPersonalizedCommunicationRestricted, or calls the Declared Age Range API.24 Section 5 of the plan already lists “junior mode by Declared Age Range” among the things not yet built.23 The Game Center flags are the part it does not list: Screen Time’s multiplayer setting governs Game Center’s own multiplayer, and Apple’s documentation asks a game with “a custom multiplayer feature” to disable it itself, so until the app reads the flag a parent’s setting does not reach the plaza.18

The client reconnects after a dropped socket with a backoff of min(30, 2^attempts) seconds (PlazaClient.swift line 165), and hiding a collector is on the device, by id.215023 Both stay as they are in the brief, which adds one use of the hide list: it travels with each request for the plaza’s echoes, so the server can leave out the walks of collectors this player has hidden (section 7.2).

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

The brief keeps what the plaza has (the server’s own collectors, preset lines only, one move per tile, presence in memory) and adds the three answers in the order the canon gives them: townspeople whose lives do not stop, traces of people who were there, and presence drawn without snapping. Every item has a check a script, a test or a capture can pass or fail. Tile coordinates are the plaza’s, x to the right and y down.21

The line on borrowing is the one the first post in this series draws for patents and for expression: no creature, no Pokémon place name, no franchise word used as a feature’s name, and nothing that aims and throws to capture, shows a capture likelihood, sends a companion to fight or boards anything to ride.36 Every element below is townspeople walking, standing and saying whole preset sentences, and pale replays of other collectors’ walks. The games’ systems are named above as facts about published works; Kiradex’s features get Kiradex’s own names here: townspeople, echoes, today’s hello, the line book and the quiet plaza. docs/WORLD.md section 3 already calls every live collector who is not a friend a passer-by; that wording stays, and the replays are called echoes so the two are never confused.23 The legal notes are readings, not advice.

7.1 Townspeople with routines

  • Population. Grow the plaza’s own collectors from 4 to 8, each with a post.21 The split follows Emerald’s always-present people, 59 of 100 standing and 41 not (39 wandering, 2 walking in place), which at eight rounds to five standing and three moving. Five stand at posts and turn: the shop counter, the hall door, the fountain and two stalls. Two wander a box of 2 cells around a post, as Emerald’s wanderers do. The third that moves is not from Emerald’s split, whose 158 townspeople all stand, wander a box or walk in place, with none on a route: it is one of today’s four loops of waypoints, kept, walking a round between posts, so today’s four loops become one.121 The four new collectors are drawn by the app’s own figure system, with handles from the app’s own word lists, as the four today are.20
  • Waits. A collector at a post turns, and a wanderer steps, after a wait of 1, 2, 3 or 4 ticks of the server’s 0.5 s clock, picked at random: 0.5, 1.0, 1.5 or 2.0 seconds, Emerald’s 0.54, 1.07, 1.61 and 2.14 to the nearest tick. A wait in whole ticks is not rounded again by the tick, which is the fault section 6 measured in the step.16
  • The room’s clock. Every room runs on one clock: the server’s time in UTC, read in the room’s own time zone, one IANA zone per room in the server’s configuration. The server sends both on arrival, in welcome and in the quiet plaza’s response ({"zone": "<IANA name>", "clock": <server ms>}), and while the plaza is open the app takes its day-part from them rather than from the phone, so everyone in a room sees the same townspeople under the same light. Today Daylight.now takes the hour from Calendar.current, the phone’s own calendar and zone, and the server keeps only a monotonic clock and names no zone.50 Which zone a room uses, and which room a collector is sent to, is configuration this brief leaves open; one zone for every room is the simplest start. Outside the plaza the phone’s clock stays the collector’s.
  • Routines. Each townsperson’s day is 3 to 7 timed points written as one string in the server’s data, chosen by a key tried in order: a date, a weekday, a day-part, then the default, every one read on the room’s clock.9 The day-parts are the app’s own, from Daylight.Phase in Kiradex/World/Daylight.swift: morning from 6 to 9, day from 9 to 17, evening from 17 to 20, and night otherwise.50 At night on the room’s clock, the five at posts and the two wanderers go indoors through their own doors, as Pierre’s Friday in Stardew Valley ends, from the saloon (“Returns home to sleep.”), and the walker on the kept loop shortens its round.30
  • The pace. Fix the stop-start walk with one of two changes. Preferred: the server sends a leg once, {"t": "walk", "id": ..., "path": [...], "at": <server ms>}, and the client walks it from at at the player’s walk under the series’ motion contract, 16 ticks a tile at 60 Hz, 3.75 tiles a second (4 in today’s rig).22 Minimum: a server step interval that is a whole number of ticks, STEP_SECONDS = 0.5, with the client drawing a townsperson’s step over the same 0.5 seconds, 2 tiles a second, a resident’s amble rather than the player’s walk.632
  • Time when the room is empty. A townsperson’s tile is a pure function of the room’s clock: the route, the day-part and a seed, computed when asked, not advanced by Room.tick. The seed is one global value in the server’s configuration, not one per room or zone, so two rooms with the same zone show the same townspeople on the same tiles. The first collector in at 07:40 by the room’s clock sees Moss where Moss would be at 07:40, and so does a collector who joins the same room from a phone set to another zone.63

Checks. (a) The pace, by design. For the preferred leg, a client test feeds a scripted walk with a straight path of 5 tiles and an at stamp, logs the townsperson’s position on every tick, as the motion brief’s -motionLog logs the player’s, and asserts that it sets off on the tick at falls on by the client’s estimate of the room’s clock, visits the path’s tiles in order, moves exactly 1 pixel on every tick and never backwards, takes 16 ticks a tile and stands on the last tile 80 ticks after at; a server test asserts that each leg is sent once, whole, with its stamp. For the minimum fallback, a server test drives the townspeople for one simulated hour on the 0.5 s tick and asserts that every within-leg step interval equals the configured one; today measure_npc_cadence.py finds 1.0 s against a configured 0.7 s. For either, a server test asserts that every wait is a whole number of ticks.622 (b) A test opens two rooms with the same zone 600 seconds apart, both on the one global seed, and asserts identical townspeople tiles at the same server time; a client test with the phone’s zone set to a different one from the room’s asserts that the plaza’s day-part follows the room’s clock. (c) A test sets the server’s clock to a UTC instant that is 03:00 in the room’s zone and asserts that the five at posts and the two wanderers are not on the plaza map and the walker on the kept loop is. (d) A server test counts the eight by kind and finds 5 at posts, 2 wandering and 1 on the kept loop.

7.2 Echoes: the last eight walks

  • Mechanic. The plaza keeps the last 8 visits.413 A visit is the path walked, as tile-and-time pairs, from arrival to the first door taken or 60 seconds, whichever is shorter; the walker’s figure is not kept. When a room holds fewer than 8 live collectors, echoes fill the gap: each replays its walk at its own pace and fades at the door it took. An echo has no name plate, holds up no card, has no tap target and says nothing. It is a walk, not a person.5
  • Appearance. An echo’s figure is never derived from the walker’s figure. The server gives each one of four plain figures, the manifest’s default pieces in four plain dyes, made by the forge for echoes and drawn pale (one of the forge’s dye ramps at a fixed alpha). Which of the four is picked by a keyed hash of the walk’s own salt, under the server’s secret, which the server keeps and never sends, so two walks by the same collector get unrelated figures. A collector can wear default pieces too, so a walker who happens to wear one of the four may match their echo by chance, and the match carries nothing: the figure says nothing about who walked.58
  • Decay. An echo is dropped after 7 days or when 8 newer visits arrive, whichever comes first.14
  • Who sees echoes. Collectors in the live plaza, whenever it holds fewer than 8 of them. Nobody whose isMultiplayerGamingRestricted is true: their quiet plaza is townspeople only, because on my reading an echo is part of the plaza’s multiplayer (7.6, setting 1).18
  • Hiding. Hiding a collector hides their echoes too, and the server does the filtering. Each stored walk carries a random salt and a tag: a keyed hash (an HMAC) of the walker’s id and that salt, under a secret only the server holds, so two walks by the same collector carry unrelated tags. A request for echoes carries the ids the requester has hidden; the server recomputes the tag of each hidden id for each stored walk, leaves out the walks that match, and drops the list when the request is answered, or, on a live connection, when the socket closes. What reaches a client is a plain figure, the path and the hour: no id, no tag, no salt and nothing taken from the walker’s figure. That removes the identifier and the appearance, which today travel together in every arrival (Player.public() in server/app/rooms.py sends the id, the handle and the figure in one object, and server/app/main.py broadcasts it to the room). It does not remove the walk. A path, its pace and its hour can point to a collector for someone who was in the plaza that hour or knows where a friend always goes, and a client that was in the room for that same walk received each tile with the walker’s id in moved. Echoes are unnamed, not anonymous.2320
  • What it stores, and the COPPA reading. No handle, no Game Center id, no device id, no figure of the walker’s, no region and no time finer than the hour: the tiles, step times relative to the walk’s start, the hour, the salt, which also picks the plain figure, and the tag that applies a hide. Reading, not advice: the tag is derived from a persistent identifier, so I treat it as one. It stays on the server, is never sent, and is used for the sole purpose of applying a hide, which I read as the internal-operations use § 312.5(c)(7) describes, with notice. The walk as sent, with no identifier and a figure the server picked, I read as outside the rule’s definition of personal information. The weak point in that reading is that a walk is behavior, and someone who saw the plaza at that hour may tie it to a collector; the hour-only time, the 60-second cap and the seven days narrow that, and do not close it. The hidden ids a request carries are used for that request and are neither logged nor kept. The written retention policy in the privacy notice says 7 days, as § 312.10 asks.19 This changes the server from storing nothing to storing walks for a week, and the reading is one for the lawyer the plan defers until there is traction.23
  • Who is recorded. Nobody under 13: by the October 2 decision they have no plaza at all.23 Nobody whose isMultiplayerGamingRestricted is true (they have no live plaza to walk in, setting 1), nobody whose isUnderage is true, which setting 2 already treats as a child signal, and nobody aged 13 to 15 by the declared range, which is the first of the junior rules the plan leaves to be written.185223
  • Must not resemble. A bloodstain, a replayed death, a summoning sign, a wall of players’ posts. An echo is never a creature and never fights.4144

Checks. (a) A server test records 10 visits and asserts that 8 are kept with the oldest dropped, and that none survives a clock advanced by 7 days. (b) A schema test asserts that a stored walk has exactly the fields path, hour, salt and tag, with no handle, id or figure string in it, and that the echoes a client receives have exactly the fields figure, path and hour: no hash, tag, salt or id field. It asserts that the echo’s figure string is the one of the four that the keyed hash of the walk’s salt picks, the same whatever the walker wore, and, for a walker wearing a figure outside the plain four, that it is not the walker’s. (c) A UI test with no live peers shows up to 8 echoes, and none responds to a tap. (d) A test with the multiplayer-restricted flag, one with isUnderage, and one with the 13-to-15 band, asserts that the server records no visit from that client. (e) A server test stores walks by two collectors, requests echoes with one of them hidden, finds that collector’s walks left out, and then finds the hidden id nowhere in the server’s state.

7.3 Today’s hello

  • Mechanic. Each townsperson remembers whether you talked to them today.1110 The first talk of the local day picks a greeting line (“Back again!” and its kind, written for Kiradex and added after index 22 in server/app/lines.py); later talks the same day pick an ordinary line.21 Every third day on which you have talked to the same townsperson moves them one step on a hidden ladder of regulars, counted from your first talk and never reset, and at each step they say one new line. No meter is shown.
  • No decay. Nothing is lost for missing a day, or a month. Stardew’s friendship decays for every day you do not talk; this one never does, because PEGI rates “daily quests, log-in streak or event-based rewards that expire after a while” at PEGI 7, and PEGI 12 where “players are punished by losing rewards or game status when they do not return in time.”105958
  • Where it lives. On the device: one dictionary of townsperson id to the last local date talked and the count of days talked, in the collector’s profile, so the server stays without per-player storage.

Checks. (a) A unit test talks to one townsperson twice on 2026-10-05 and once on 2026-10-06 and gets two first-of-day greetings and one ordinary line. (b) A unit test sets the device date backwards and forwards and finds no step on the ladder ever removed. (c) A search of server/app finds no per-player store added for this feature. (d) A unit test with first talks on three days weeks apart finds the townsperson one step up the ladder.

7.4 Presence without snapping

  • Send. One move per completed tile, as today. Today’s baseline is 4 a second walking and 6.0 to 6.4 running (the run as modeled at 60 Hz and at its nominal rate); under the series’ motion contract, the motion brief’s 16 ticks a tile walking and 8 running at 60 Hz, it is 3.75 and 7.5, and that contract is the one this brief builds to. Both are under the 8-a-second limit.2122 The server adds its own millisecond stamp to every moved it relays.
  • Render. Each client keeps an estimate of the server’s clock from the stamps it receives, and draws each other collector on a render clock 350 ms behind that estimate: linear between the two received stamps that bracket the render clock, with the walk cycle driven by distance walked. Never reset a step in progress. When the buffer runs dry, hold on the last tile; a grid walker stops dead, so nothing is extrapolated. Jump only when a walker is more than 6 tiles or 2 seconds behind.716 The 350 ms comes from a bound, checked in a model that assumed an exact clock estimate and no one-way delay beyond jitter (section 3): at the motion contract’s walk of 3.75 tiles a second a step is 266.7 ms, a step plus 80 ms of jitter is 346.7 ms, and a delay at least that long starves no frame for any jitter draw. That leaves about 3 ms for the clock estimate’s error; an estimate further ahead of the server’s clock than that can starve frames. 325 ms passed check (a) on the model’s first jitter draw, with 6 starved frames at 80 ms, but failed it on 8 of 200 draws; 350 ms starved none on any.7 It is a starting value for a capture on devices to confirm, not a result.
  • Idle. Mark a collector idle after 120 seconds without input, shown by the rig’s existing doze idle cycle, as Arcturus marks an avatar idle at 240 cycles of 500 ms.1550 Close the socket after 240 seconds without a ping. That rule is my adaptation of two sources: the ping check is Houdini’s, which closes any client that sent no heartbeat during a 61-second window, and the 240 seconds is the length after which Arcturus removes an idle non-owner, though Arcturus counts cycles without an action, not missing pings.4815

Checks. (a) Port the new logic into measure_remote_walk.py, with the render clock taken from the client’s estimate of the server’s clock rather than the sender’s own clock, and, with the sender at 3.75 and 7.5 tiles a second, require 0 backwards frames in all six cases, 0 starved frames at 0 and 30 ms of jitter, and at most 10 starved frames of the 600 drawn while the sender is sending at 80 ms. The model with an exact clock gives 0 starved frames in all six at 350 ms, on each of 200 jitter draws.7 (b) A UI test with a scripted peer walking right across the plaza captures no frame in which the peer’s x decreases. (c) A server test asserts that every relayed moved carries a stamp. (d) A server test advances the clock 241 seconds with no ping and asserts the socket is closed.

7.5 The line book

  • Shape. Six branches, each 8 to 12 lines at launch, 48 to 72 in all, every line two taps away (branch, then line): Hellos, Answers (a favorite era, how long you have collected, which set), Collecting, Trading (arranging a trade, never pricing one), Cheers, and Goodbyes. Today there are 14 player lines in one list.21 Emotes stay a separate row. A player for whom Game Center reports communication restricted, or who is underage, does not get the line book at all (7.6, setting 2).
  • Growth. Up to 30 more lines unlocked by play, at most one a day, from the regulars’ ladder in 7.3 and from levels.1235 The server holds the list and can retire a line within the hour, as it already sends the list on arrival.20
  • Against the canon. Easy Chat opens 940 words and composes them into grids of 2 to 10 slots; New Horizons has 88 Reactions; Emerald’s Union Room took 15 typed characters.38124 Kiradex’s lines are whole sentences, never composed from words, so no sequence of choices can spell a name, a number or a place.
  • Must not resemble. Easy Chat’s group structure or its word grid, the Trendy Saying list, or any franchise word.40

A schematic of the proposed line book: a root node with six branches, Hellos, Answers, Collecting, Trading, Cheers and Goodbyes, each with eight filled line slots and four open ones, 8 to 12 lines a branch. Notes below: today 14 player lines in one list; Emerald's Easy Chat 940 open words in grids of 2 to 10 slots; Emerald's Union Room typed messages of 15 characters and 10 registered phrases.

The proposed line book: the one figure in this post that is a proposal rather than a measurement.26

Checks. (a) A test over lines.py asserts 6 branches with 8 to 12 lines each at launch, and that every line is at most 2 taps from the root. (b) A test asserts that no line contains a digit or a free slot. (c) A test reads pret’s Easy Chat word lists and finds no line equal to an entry and no entry of two or more words inside a line. (d) A unit test unlocks a line on each of two consecutive days and refuses a second unlock on the same day.

7.6 Safety settings, each with a check

  1. Game Center’s restriction turns other collectors off, live and replayed. When GKLocalPlayer.local.isMultiplayerGamingRestricted is true, friends-only included, the plaza opens as the quiet plaza: townspeople only, with no echoes and no WebSocket. The townspeople and the room’s clock come in one request that carries no account id, no device id and no hidden ids; the server uses the request’s IP address only to answer it, and the plaza server does not log it; the host’s own edge request logs are not verified here (setting 6).18 Reading: the page says “If your game uses a custom multiplayer feature, you should disable it,” and an echo is a replay of a real collector’s walk, a trace of another player of the kind section 2 surveys, and one a viewer may recognize (7.2). Wikipedia describes Dark Souls’ ghostly images of other players under the game’s Multiplayer heading, without saying whether they are recordings or players connected at the time. That source is mixed: the text under the heading says the game “integrates online features into the single-player world” and gives “Direct multiplayer” as cooperative summoning and invasions, apart from the ghosts. The brief takes the conservative side anyway: on my reading echoes are part of the plaza’s custom multiplayer feature, and a player whose parent restricted multiplayer sees none.1841 What would let echoes back for this player is App Review, or Apple in writing, reading a replayed walk in a plain figure, with no identifier attached, as something other than multiplayer; this brief does not assume it. Check: a UI test with the flag stubbed true asserts that no WebSocket is opened, that no echo is drawn and that the plaza says it is quiet; a server test calls the quiet plaza’s route and finds no echo in the response and no IP address in the server’s log.
  2. Custom communication off. When isPersonalizedCommunicationRestricted or isUnderage is true, the default is emotes only: the line book is hidden, no say is sent, other collectors’ lines are not drawn for this player, and there is never voice, an invitation message or a typed field.5152 Reading: the page says “If your game includes any custom communication features, you should disable them,” and a line book of preset sentences is a custom communication feature. That Game Center allows children preset messages in its own features does not exempt a game’s own.5117 I keep emotes because a wave or a nod carries nothing a child could use to reach anyone, but an emote is communication of a kind (Wikipedia’s account of Journey calls its chime “The only form of communication between the two”), and this is the weakest step in the reading: if App Review reads emotes as a custom communication feature too, they go and the plaza is presence only for this player.5 Keeping the lines for this player would be an exception that needs Apple’s agreement in writing; this brief does not take it. Check: a search of Kiradex/World for TextField, TextEditor and UITextField returns nothing, and a UI test with each flag stubbed true shows the emote row, no line book, sends no say, and draws no other collector’s line.
  3. Age bands by Declared Age Range, as decided on October 2. Under 13: no plaza, a generated handle only. 13 to 15: the plaza with junior rules, the first of which is that their walks are never recorded. 16 and up, or not declared: the full plaza.2354 Check: a unit test of the mode table across the three bands and the three Game Center flags.
  4. Report and hide reach the echoes. Hiding a collector hides their live figure and, filtered on the server for each request as in 7.2, their echoes; reporting stays on every collector’s panel.55 An echo wears a plain figure and has no panel, so a player cannot pick out a hidden collector’s echo to hide it; the server’s filter does that. A hide reaches walks stored before and after it; it cannot reach what another player saw live or recognizes in a walk. Check: the server test in 7.2(e), and a UI test that hides a scripted peer, replays their recorded walk, and asserts that it is not drawn.
  5. No random pairing, no anonymous chat. Strangers only ever share the plaza; nothing pairs two strangers into a private space.55 Check: a test over the handlers in server/app/main.py finds no message that opens a channel between two collectors who are not Game Center friends.
  6. Retention in writing. The privacy notice gains the written data retention policy: presence in memory only; echoes 7 days, each with a keyed hash of the walker’s id that stays on the server, is used only to apply hides and is never sent; the hidden ids a request carries, not kept; a connection’s IP address used only to answer it and route the reply, which I read as support for internal operations under § 312.5(c)(7), and not logged by the plaza server; reports logged by reason and room.19 Today the server starts uvicorn 0.37.0 with its defaults (server/Procfile, --proxy-headers), and on reading uvicorn’s own code those defaults write the client’s forwarded address to the log for every HTTP request (the access log is on unless turned off) and for every accepted WebSocket (an INFO line on uvicorn.error); the brief starts it with --no-access-log --log-level warning.57 Check: the notice’s URL is reachable from Settings, the server test in 7.2(a) holds the 7 days, and a test that opens a WebSocket and calls the quiet plaza’s route under the production start command finds no IP address in the captured log. The host’s edge request logs are outside that test and unverified here: whether they record the client’s address, and for how long, is to confirm with the host before the notice is written.
  7. No third-party analytics or advertising in the world.55 Check: a dependency audit of the app target lists no analytics or advertising SDK.

What to refuse

  • A play timer of our own. Screen Time already limits time in an app, and Club Penguin’s server counted a child’s allowed minutes down and disconnected at zero; the platform’s limit is the one a parent already knows.1748
  • Follower counts, and any count of who likes whom; the plan already rules them out.23
  • A visitor list with names, a page of who came by. An echo is unnamed on purpose: it carries no id and nothing taken from the walker’s figure. It is not anonymous: someone who was in the plaza that hour, or who knows a friend’s habits, may still recognize a walk, which is why an echo carries the hour and no finer time, and why there is no list to read echoes from.
  • An echo you can tap, talk to or follow.
  • A meter on today’s hello, or anything lost for not coming back.59

Not in this brief

  • Rooms people decorate. Furniture, caps and visiting other collectors’ rooms belong to a forthcoming post in this series.
  • New lines’ wording. The brief fixes the line book’s shape; the sentences are written for Kiradex and localized separately.
  • Group play. Trades, show-and-tell and the exchange screen the plan lists as not yet built are outside this brief.23
  • Anything from the games measured. No creature, place name, mark, tile or sound from Pokémon, Stardew Valley, Animal Crossing, Dark Souls, Journey, Death Stranding, Splatoon, Habbo or Club Penguin.
  • Timings on a device. The checks are behavior, captures and a model; nothing here promises a frame time.

Key Takeaways

If you draw the art

  • Draw more people standing than walking. Six in ten of the townspeople always on Emerald’s maps stand at a post, most facing one way and some looking around (seven in ten once the story’s actors are counted); give each standing figure a facing and a look-around, and save the walk cycles for the nearly four in ten who wander.1
  • Make an echo of another player’s walk read as a trace, not a person: pale, nameless, holding nothing, fading at a door. Nothing in its drawing should invite a tap.5

If you build the engine

  • Settle the town’s day on arrival, with one run that takes the number of days elapsed, and compute a townsperson’s tile from one clock that everyone in the room shares, not from each phone’s; a server loop that returns when the room is empty freezes the town, as Kiradex’s measured.36
  • Make the server’s step interval a whole number of ticks and draw each step over the interval it was given; a 0.7 s step on a 0.5 s tick lands every 1.0 s and is drawn in 0.25 s, a walk that stands still 75 percent of the time.6
  • Send one update per tile, stamp it on the server, and draw other walkers on a clock 350 ms behind the estimated server time without ever resetting a step in progress; in the model, at the series’ 3.75 and 7.5 tiles a second and with an exact clock estimate, that is 0 backwards and 0 starved frames at up to 80 ms of jitter.7
  • Read isMultiplayerGamingRestricted, isPersonalizedCommunicationRestricted and isUnderage before opening a socket; friends-only reads as restricted, and on my reading a restricted player should not see replays of other players either.185152

If you design the loop

  • Keep others’ traces in a few fixed slots that decay: eight walks for seven days is enough to say someone was here. Apply hides on the server, send a trace with no id and in a plain figure rather than the walker’s own, and say plainly that a walk can still be recognized by someone who saw it.414
  • Remember today’s hello with one flag and never take anything back for a missed day; PEGI rates expiring streaks.59
  • Give strangers sentences, not words: a line book of whole sentences cannot be made to spell anything, and Game Center already holds children to preset messages. When Game Center says communication is restricted, take the line book away too.381751

FAQ

How do you make a game town feel alive with no other players online?

Give it townspeople with their own routines and traces of people who were there. In Pokémon Emerald’s 16 towns and cities, 59 of the 100 townspeople who carry no hide flag stand at posts, 39 wander boxes of one or two cells and 2 walk in place (71.5%, 27.2% and 1.3% of all 158, counting the story actors a flag can remove, who mostly stand), stepping at the player’s pace and waiting 0.54 to 2.14 seconds between steps; Stardew Valley’s villagers keep days of a few timed points chosen by 22 key formats; and Emerald’s record mixing copies another player’s bases, trend phrases and resident into your town.124

How often should NPCs move in a top-down pixel game?

In Emerald a wanderer takes one 16-frame step (268 ms, the same action as the player’s walk) and then waits 32, 64, 96 or 128 frames, so it is in motion at most 11 to 33 percent of the time, per step taken, and less when a step it picks is blocked; most townspeople have a default movement type that never steps, though a story script can still walk one. Animal Crossing’s Wild World went the other way and slowed its villagers below the player’s pace. What reads badly is a pace that is neither: Kiradex’s collectors move at the player’s speed in one-tile bursts with 0.75-second stops between tiles.1326

What is record mixing in Pokémon Emerald?

A link-cable exchange in which each game sends the other a fixed structure of 11 kinds of record in 5,188 bytes, among them 20 Secret Bases, 25 television slots, 16 news items and 5 trend phrases. The partner’s Mauville Old Man replaces yours, and the Hipster’s arrival is the only thing that lets him teach another Trendy Saying.435

How much interpolation delay does a 2D multiplayer game need?

Glenn Fiedler’s rule is enough to survive two lost packets, about three send intervals, plus a frame or two for jitter.16 Over WebSockets, which run on TCP, nothing is lost and a late packet is retransmitted, so on my reading the budget is jitter rather than lost packets, and a buffer of a little more than one interval can do. For a grid world that sends one update per tile, a model of Kiradex’s walk at the series’ 3.75 tiles a second walking and 7.5 running found that a render clock 350 ms behind the estimated server time gives 0 backwards frames and 0 starved frames at up to 80 ms of jitter; on one jitter draw, 300 ms starves 27 of 600 frames walking at 80 ms and 325 ms 6, while 100 ms starves 125 to 456 in every case, and over 200 draws 350 ms starves none on any. The 350 ms rests on a bound: a 266.7 ms step at 3.75 tiles a second plus 80 ms of jitter is 346.7 ms. It is a model with a straight road, uniform jitter, an exact clock estimate and no base latency, not a device capture.7

Can children use chat in an iOS game?

Game Center says children “cannot send or receive user-inputted text” and are “restricted to sending and receiving preset messages,” with voice chat disabled. Apple’s documentation tells a game with “any custom communication features” to disable them when isPersonalizedCommunicationRestricted or isUnderage is true, and Guideline 1.2 requires filtering, reporting, blocking and published contact details for user-generated content. That sentence does not exempt preset messages, so on my reading a game’s own preset lines go when either flag is true, even though Game Center allows children preset messages in its own features; Kiradex’s brief keeps only emotes for that player, and that reading is mine, not Apple’s text.175155

Does COPPA allow storing other players’ movements to replay as ghosts?

I am not a lawyer, and this is a reading, not advice. The amended rule counts “A persistent identifier that can be used to recognize a user over time” as personal information, lets an operator use a persistent identifier alone “for the sole purpose of providing support for the internal operations” with notice, and since April 22, 2026 requires a written retention policy with a deletion timeframe. Kiradex’s design stores a walk with no handle, no account id, no device id and not the walker’s figure, plus a keyed hash of the walker’s id that stays on the server, is used only to apply other players’ hides and is never sent; the echo is drawn in one of four plain figures the server picks, and both are kept seven days and named in that policy. I treat the hash as a persistent identifier used for internal operations, and the walk as sent as outside the definition, but a walk is behavior that someone who saw the plaza at that hour might tie to a collector, so echoes are unnamed rather than anonymous, and a lawyer should check the final design.19

Related on this site: Pixel-Art Worlds on iPhone is the first guide in this series, with the tile systems and the plaza this post’s town lives in, and its legal FAQ draws the patent line the brief follows; Pixel-Art People built the collectors and the forge whose plain figures the echoes wear, and quotes the PEGI rule that keeps today’s hello from decaying; Pixel-Art Structures built the doors the townspeople go home through at night; Pixel-Art Motion measures the handhelds’ walks, models the app’s own, and sets the never-reset-a-step rule the brief applies to other collectors; and iPhone Duo for Developers covers the device the plaza is drawn for.

Sources


  1. Author’s measurement, measure_npcs.py in the author’s evidence folder for this post, revised and re-run October 5, 2026, output saved as measure_npcs.out. Inputs: pret’s pokeemerald decompilation, a shallow clone at commit 731ad5b (master, October 1, 2026): include/constants/event_object_movement.h (the 81 movement types), the 16 town and city data/maps/*/map.json files (object events, graphics ids, movement types, ranges, hide flags), and src/event_object_movement.c (the step tables, the three delay tables timed at 59.7275 Hz, which movement type sets which delay, and MovementType_WanderAround_Step4). The revision sorts object events by graphics_id into people, objects (6 ITEM_BALL, 2 TRUCK, 1 MR_BRINEYS_BOAT) and creatures (5), and stops if a graphics id it has not classified appears; the VAR_0 and VAR_3 events, whose sprite comes from a variable, are counted as people because every one of them carries a rival’s hide flag. The earlier version counted all 172 object events as townspeople; it and its output are kept beside it with an .r1 suffix, and the revision’s output repeats the earlier lines unchanged. The first revision and its output are kept with an .r2 suffix; the current script, a second revision, splits the 158 people by the hide flag in their object event: the 58 with one (54 stand, 4 wander; 41 of them use a villain team’s, the rival’s or a named character’s sprite, by a fixed list of graphics ids in the script) and the 100 with none (59 stand, 39 wander, 2 walk in place), and recounts the three towns’ people with no hide flag (Littleroot 2, Petalburg 3, Mauville 6); its output repeats every earlier line unchanged. A person with no hide flag is on the map at every load; calling the 58 story actors is my reading of their sprites and flag names, not a field in the data. The motion shares (11 to 33 percent) are arithmetic on the step and delay rows, 16 frames over 16 plus 32 to 128, per step taken: an upper bound, since a wanderer whose chosen direction is blocked faces and waits again without moving. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  2. Author’s measurement, measure_daily.py in the same folder, re-run October 5, 2026, output identical to measure_daily.out. Inputs: pret pokeemerald 731ad5b include/constants/flags.h and src/clock.c; the saved Stardew Valley Wiki pages “Villagers” (oldid 191346, edited February 26, 2026), “Pierre” and “Modding:Schedule data” (the 22 key formats counted from the page’s tables); and Nookipedia’s “Reaction” page (the New Horizons counts by version). ↩↩↩↩↩↩↩↩↩↩↩

  3. pret, pokeemerald/src/clock.c (DoTimeBasedEvents, and UpdatePerDay, which runs once with daysSince, the days since it last ran), commit 731ad5b; DoTimeBasedEvents is also called on map loads in src/overworld.c and by a periodic field task in src/field_tasks.c, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/clock.c. ↩↩↩↩↩↩↩

  4. Author’s measurement, measure_record_mixing.py in the same folder, re-run October 5, 2026, output identical to measure_record_mixing.out. Inputs: pret pokeemerald 731ad5b src/record_mixing.c (struct PlayerRecordEmerald, its 11 members and its 0x1444-byte size), include/constants/global.h and the related headers (SECRET_BASES_COUNT, TV_SHOWS_COUNT, POKE_NEWS_COUNT, SAVED_TRENDS_COUNT, APPRENTICE_COUNT), src/mauville_old_man.c (the five Old Men and the selection rule), and src/union_room_chat.c, include/union_room.h and include/constants/global.h (the Union Room’s leaders, group size, sprites, activity codes, keyboard pages, MAX_MESSAGE_LENGTH and UNION_ROOM_KB_ROW_COUNT). ↩↩↩↩↩↩↩↩↩↩↩↩

  5. Wikipedia, “Journey (2012 video game),” sections Gameplay and Development, each statement citing its own source, saved October 4, 2026, https://en.wikipedia.org/wiki/Journey_(2012_video_game). thatgamecompany’s own Journey page was also saved and holds navigation only. ↩↩↩↩↩↩↩

  6. Author’s measurement, measure_npc_cadence.py in the same folder, revised and re-run October 5, 2026, output saved as measure_npc_cadence.out; the revision only adds a count of every said message (469 in the hour), beside the 465 intervals between one collector’s consecutive lines that the mean of 30.7 seconds is taken over, and its other lines are unchanged (the previous version is kept with a .pre-astra suffix). It imports the Kiradex server’s own app.npcs (STEP_SECONDS, make_all) and app.rooms (Plaza) from the working tree read on October 5, 2026 (files and hashes in note 20), reads TICK_SECONDS from server/app/main.py, and advances four collectors with seed 1 on an ideal 0.5 s clock for 3,600 simulated seconds, logging every moved and said message. Intervals of 1.5 s or less between consecutive steps are counted as within a leg; longer gaps are pauses. The empty-room test checks Room.tick for its early return and calls advance(10000.0) once on fresh collectors. The 25 and 75 percent figures divide the client’s 250 ms step (PlazaRig.tilesPerSecond = 4) by the measured 1.0 s interval. This run supersedes the 0.7 s and 36 percent that measure_kiradex.py derives from the constant alone. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  7. Author’s model, measure_remote_walk.py in the same folder, revised and re-run October 5, 2026, output saved as measure_remote_walk.out; the previous version, which did the rig’s arithmetic in 64-bit floats, and its output are kept with a .pre-f32 suffix. The revision does every operation the rig does in Float in 32 bits (NumPy float32), in the code’s order: progress is a Float (PlazaRig.swift line 29), update receives Float(event.deltaTime) (PlazaStage.swift line 149), and advance() adds dt * tilesPerSecond * (running ? runPace : 1) / length (line 660), with running set only on the player (line 614); positions are (Float(x) + 0.5) * 16 (TileMap.swift line 235) and are drawn at from + (to - from) * progress, rounded to whole pixels, ties away from zero (lines 670 and 726). It prints the check that 15 frames of 1/60 second sum to exactly 1.0 in 32 bits and to 0.9999999999999999 in 64. It reimplements PlazaRig.move(other:to:facing:) as read on October 5 (path from the walker’s last whole tile; progress = 0 on every message; a jump when the path is empty or longer than 6 steps) and counts a snap-back as a reset while steps remain and progress exceeds 0.05, a backwards frame as a drawn pixel position smaller than the frame before, and lag from the drawn pixel position. Separately it models snapshot interpolation on a steady render clock, rt = now - delay for delays of 100, 250, 300, 325 and 350 ms, where now is the sender’s clock, so the rule modeled is the estimated server time minus the delay, not the newest update minus the delay; this half is a proposed renderer, not the rig, and runs in 64-bit floats. Assumptions: every frame’s deltaTime exactly 1/60 second; no fused multiply-add; perfect clock sync between sender and renderer; no base one-way latency, so an update arrives at its stamp plus jitter; a straight open road (path length is the Manhattan distance; diagonal steps, which take √2 as long in the rig, are not modeled); a sender that emits one move per completed tile, at today’s 4 tiles a second walking and the run’s nominal 6.4 for both halves, and for the buffer also at the series’ motion contract, 3.75 and 7.5 tiles a second; uniform jitter of 0 to J ms for J of 0, 30 and 80; 60 frames a second; seed 1. The rig runs 12 simulated seconds per case (10 of sending and 2 to settle) and each buffered run 660 frames (11 seconds), counting starved frames only over the 600 drawn while the sender is still sending. A second script, measure_remote_walk_seeds.py in the same folder, run October 5, 2026, output saved as measure_remote_walk_seeds.out, loads the same interpolation function from measure_remote_walk.py’s source, asserts that seed 1 reproduces its 27, 6 and 0 starved frames, and re-runs the buffer at 3.75 and 7.5 tiles a second over seeds 1 to 200: at 80 ms of jitter, walking, 325 ms starves frames on all 200 seeds and more than 10 on 8, 350 ms none on any, and every other case at 325 and 350 ms none. It prints the bound behind the 350 ms: a step at 3.75 tiles a second is 266.67 ms, plus 80 ms of jitter 346.67 ms, leaving 3.33 ms. It also offsets the render clock as a clock estimate running ahead of the server’s; in this model, whose frames and steps line up on the 1/60 s grid, 10 ms ahead still starved none on 200 seeds and 25 ms ahead behaves as 325 ms, so the 3 ms in the text is the bound’s guarantee, not the point where this model starts to starve. It is a model, not a capture from two devices. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  8. pret, pokeemerald/data/maps/, the 16 town and city map.json files, among them LittlerootTown, PetalburgCity and MauvilleCity, and data/maps/PetalburgCity/scripts.inc (the gym boy, LOCALID_GYM_BOY, MOVEMENT_TYPE_LOOK_AROUND with no hide flag in map.json, walked to the gym by the PetalburgCity_Movement_BoyWalkToGym movements), commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/tree/master/data/maps. ↩↩↩↩

  9. Stardew Valley Wiki, “Modding:Schedule data,” saved October 4, 2026, https://stardewvalleywiki.com/Modding:Schedule_data. The schedule format, Abigail’s raw data as of game version 1.5.1, the key formats and their order, and the “Limitations” note. ↩↩↩↩↩↩↩↩

  10. Stardew Valley Wiki, “Friendship,” saved October 4, 2026, https://stardewvalleywiki.com/Friendship. Points per heart, the ways friendship rises and falls, the decay table, gifts, the birthday multiplier and heart events. ↩↩↩↩↩↩

  11. Nookipedia, “Friendship,” the New Horizons section, saved October 4, 2026, https://nookipedia.com/wiki/Friendship. ↩↩↩↩

  12. Nookipedia, “Reaction,” the New Horizons section, saved October 4, 2026, https://nookipedia.com/wiki/Reaction. The counts by version are from measure_daily.py (note 2). ↩↩↩↩↩

  13. Serebii.net, “Join Avenue,” Pokémon Black 2 and White 2 section, saved October 4, 2026, https://www.serebii.net/black2white2/joinavenue.shtml. A fan site and the only source used for this feature. ↩↩↩↩↩

  14. Wikipedia, “Death Stranding,” Gameplay section, citing its own sources, saved October 4, 2026, https://en.wikipedia.org/wiki/Death_Stranding. ↩↩↩↩↩

  15. Krews, Arcturus Morningstar, an open-source emulator of Habbo’s server written by fans, src/main/java/com/eu/habbo/habbohotel/rooms/Room.java (IDLE_CYCLES = 240, IDLE_CYCLES_KICK = 480, scheduleAtFixedRate(this, 500, 500, TimeUnit.MILLISECONDS)), saved October 5, 2026, https://git.krews.org/krews/Morningstar/-/blob/master/src/main/java/com/eu/habbo/habbohotel/rooms/Room.java. Emulator constants, not Sulake’s published figures; RoomUnit was not read. ↩↩↩↩↩↩↩

  16. Glenn Fiedler, “Snapshot Interpolation,” Gaffer on Games, November 30, 2014, saved October 4, 2026, https://gafferongames.com/post/snapshot_interpolation/. ↩↩↩↩↩↩↩↩

  17. Apple, “Game Center & Privacy,” section “Children in Game Center” and the friends section, saved October 4, 2026, https://www.apple.com/legal/privacy/data/en/game-center/. ↩↩↩↩↩↩↩↩

  18. Apple Developer Documentation, GKLocalPlayer.isMultiplayerGamingRestricted (iOS 13.0+), the documentation JSON saved October 4, 2026, https://developer.apple.com/documentation/gamekit/gklocalplayer/ismultiplayergamingrestricted. The quotations are the Discussion text with the inline reference to true rendered as the word, flattened by sources/extract_gk.py in the draft folder. ↩↩↩↩↩↩↩↩↩↩↩↩

  19. Federal Trade Commission, “Children’s Online Privacy Protection Rule,” final rule, Federal Register, April 22, 2025, document 2025-05904, 90 FR 16918, saved October 4, 2026, https://www.federalregister.gov/documents/2025/04/22/2025-05904/childrens-online-privacy-protection-rule. The DATES section and the amended 16 CFR 312.2 (definition of personal information), 312.5(c)(7), 312.8 and 312.10. Every statement in this post about what the rule means for Kiradex is the author’s reading, not legal advice. ↩↩↩↩↩↩↩↩↩↩↩

  20. Author’s read of the Kiradex repository (private), working tree on October 5, 2026, read-only, no git commands run; files identified by the first eight hex digits of their SHA-256: server/app/main.py (87c6cc9f; TICK_SECONDS = 0.5, SHOW_EVERY_SECONDS, the message handlers, among them the moved relay at line 223 that carries the walker’s id and tile), server/app/npcs.py (d84f12a5; the module docstring, STEP_SECONDS = 0.7, the four definitions and their routes, wants and lines), server/app/rooms.py (dcd66866; Player.public() at line 115, which returns the id, handle and figure in one object, broadcast to the room on arrival at main.py line 203; CAPACITY, MOVES_PER_SECOND, SAY_EVERY_SECONDS, Plaza, and Room.tick with its docstring and early return), server/app/lines.py (391f5391; the 23 lines and the docstring saying the server sends the list on arrival). ↩↩↩↩↩↩↩↩↩↩↩

  21. Author’s measurement, measure_kiradex.py in the same folder, re-run October 5, 2026, output identical to measure_kiradex.out. It imports app.lines, app.rooms and app.npcs from the working tree in note 20 and reads PlazaRig.swift and PlazaClient.swift (note 50) for the client’s constants: preset line counts, room capacity, rate limits, tick, cooldown, plaza size and arrival, the four collectors’ routes and loop lengths, the walk and run speeds, the 6-step jump threshold and the reconnect backoff. Its derived 0.7 s and 36 percent are superseded by note 6. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  22. Blake Crosley, “Pixel-Art Motion: Walks, Cameras and Doors on iPhone,” blakecrosley.com, October 5, 2026, https://blakecrosley.com/blog/pixel-art-motion-on-iphone. Its note 6 models the app’s walk at an exact 60 Hz: the run takes 10 frames a tile, 6.00 tiles a second, against the 6.4 that 4 tiles a second times the run’s 1.6 implies, and 6.32 at 120 Hz; its section on the current code reads the snap-back on a second tap mid-step from walk(to:), and its brief sets the rule that a step in progress is never reset; its brief’s item 1 sets the walk at 16 ticks a tile and the run at 8 at 60 Hz, 3.75 and 7.5 tiles a second, the series’ motion contract, and its checks log the player’s position on every tick with a -motionLog launch argument. ↩↩↩↩↩↩↩

  23. Kiradex, docs/WORLD.md (“Kiradex World: research and plan”), working tree on October 5, 2026 (SHA-256 c7714bc1), read-only: section 2 (the Kids Category and 5.1.4 path, rated 9+ or 12+), section 3 (Game Center identity, Screen Time controls, no follower counts, preset lines, the lawyer’s reading), section 5 (the server as built on October 2: FastAPI and WebSockets, presence only, nothing stored, eight moves a second, hide on the device, “Not yet” including junior mode by Declared Age Range; and the reasoning that led to it, with clients sending position and heading at 8 to 10 Hz), and “Decisions taken (Blake, October 2, 2026)” items 6 (rating and age bands) and 8 (no lawyer until there is traction). ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  24. Author’s search of Kiradex/ and server/app/ in the Kiradex working tree, October 5, 2026, for isMultiplayerGamingRestricted, isUnderage, isPersonalizedCommunicationRestricted, the Declared Age Range API, and any store of visits or daily conversations: no matches. ↩↩↩

  25. pret, pokeemerald/include/constants/event_object_movement.h, commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/include/constants/event_object_movement.h. ↩

  26. The figures were drawn by figures/make_figures.py, kept beside the post’s draft, October 5, 2026, from the saved outputs of measure_npcs.py, measure_npc_cadence.py, measure_chat_trend.py, measure_record_mixing.py, measure_kiradex.py and measure_remote_walk.py; each value is parsed from those files and asserted against an expected value before it is drawn: the research dossier’s, except for the town-population figure, which now plots people only from the revised measure_npcs.py, with a row for the 100 people with no hide flag, and the line book’s 940 open words from the revised measure_chat_trend.py. After the second-engine review the trend figure plots the game’s own integer-day scores from the revised measure_chat_trend.py (one point per elapsed day, not a continuous triangle wave), and the remote-walk figure plots the revised measure_remote_walk.py: today’s rig in its own 32-bit arithmetic, and the buffer at the motion contract’s 3.75 and 7.5 tiles a second with delays of 100, 300, 325 and 350 ms. The line-book figure is a schematic of the brief’s proposal, with its comparison numbers parsed the same way. No game art, sprite or map render is used. ↩↩↩↩↩

  27. pret, pokeemerald/src/event_object_movement.c (IsCoordOutsideObjectEventMovementRange, sMovementDelaysMedium, sMovementDelaysShort, sMovementDelaysLong with its // Unused comment, the fixed 48-frame wait of the two rotating types, MovementType_WanderAround_Step4, GetWalkNormalMovementAction, the sStep tables), commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/event_object_movement.c. ↩↩↩↩↩

  28. pret, pokeemerald/include/constants/flags.h (DAILY_FLAGS_START and the 12 daily flags), commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/include/constants/flags.h. ↩

  29. Stardew Valley Wiki, “Villagers,” oldid 191346, edited February 26, 2026, saved October 4, 2026, https://stardewvalleywiki.com/Villagers. The 34 giftable villagers is a count of the page’s lists (6 bachelors, 6 bachelorettes, 22 non-marriage candidates); the wiki’s “Friendship” page counts a different set of 28 starting townspeople. ↩

  30. Stardew Valley Wiki, “Pierre,” saved October 4, 2026, https://stardewvalleywiki.com/Pierre. The regular schedule, the six schedule variants, and the mail at any heart level and at three hearts. ↩↩↩

  31. Nookipedia, “Hobby,” saved October 4, 2026, https://nookipedia.com/wiki/Hobby. ↩

  32. Nookipedia, “Villager,” the per-game sections, saved October 4, 2026, https://nookipedia.com/wiki/Villager. ↩↩↩↩↩↩↩

  33. Nookipedia, “Villager,” Personalities section, saved October 4, 2026, https://nookipedia.com/wiki/Villager#Personalities. ↩

  34. pret, pokeemerald/src/record_mixing.c (struct PlayerRecordEmerald, ReceiveOldManData, ReceiveDewfordTrendData), commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/record_mixing.c. ↩

  35. pret, pokeemerald/src/mauville_old_man.c (the selection switch ((trainerId % 10) / 2) and its comment, ResetHipsterFlag, ResetMauvilleOldManFlag, SetHipsterTaughtWord), pokeemerald/src/record_mixing.c (the one call to ResetMauvilleOldManFlag, at the end of ReceiveOldManData), and pokeemerald/data/scripts/mauville_man.inc (setflag FLAG_UNLOCKED_TRENDY_SAYINGS, special HasHipsterTaughtWord) and pokeemerald/data/maps/MauvilleCity_PokemonCenter_1F/map.json (the object event whose script is MauvilleCity_PokemonCenter_1F_EventScript_MauvilleOldMan), commit 731ad5b, read by the author on October 4 and 5, 2026, https://github.com/pret/pokeemerald/blob/master/src/mauville_old_man.c. That the Hipster starts in games whose trainer ID ends in 2 or 3 is the author’s arithmetic on the switch. ↩↩↩↩↩↩

  36. Blake Crosley, “Pixel-Art Worlds on iPhone: What the 16-Bit Masters Knew,” blakecrosley.com, October 3, 2026 (legal FAQ updated October 4, 2026), https://blakecrosley.com/blog/pixel-art-world-on-iphone. It states the Trendy Saying rule as one each time record mixing brings the Hipster, and its legal FAQ names the three patents asserted against Palworld’s developer (aiming and throwing a capture item, a capture-likelihood indicator, boarding a rideable character) with its own sources. ↩↩

  37. pret, pokeemerald/src/dewford_trend.c (the header comment on trendiness and maxTrendiness and on saving trends), commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/dewford_trend.c. ↩↩↩↩

  38. Author’s measurement, measure_chat_trend.py in the same folder, revised and re-run October 5, 2026, output saved as measure_chat_trend.out. The revision subtracts entries marked .enabled = FALSE from the open words (946 entries, 940 enabled), prints the Trainer group’s numEnabledWords line from easy_chat_groups.h (“Excludes Red, Green, Flame, Gold, Leaf, and Silver”), and prints the per-entry rule in IsEasyChatIndexAndGroupUnlocked, under which a name in the 202-entry list opens only when its species has been seen; the earlier version and its output are kept with an .r1 suffix. Inputs: pret pokeemerald 731ad5b src/data/easy_chat/ (group sizes, disabled entries, numEnabledWords), src/easy_chat.c (the group unlock switch, the per-entry rule and the phrase grids), include/constants/global.h (MAIL_WORDS_COUNT, NUM_QUESTIONNAIRE_WORDS, SAVED_TRENDS_COUNT), and src/dewford_trend.c (SeedTrendRng and the daily step). A second revision, after the second-engine review (the previous version and its output kept with a .pre-astra suffix), labels the peak distribution an independent-uniform approximation: it is computed from the three nested Random() % 98 draws, each taken as an independent uniform draw over 0 to 97. It adds the same distribution with the 16-bit modulo weights (Random() in src/random.c returns the high 16 bits, so residues 0 to 71 occur 669 times in 65,536 and 72 to 97 668 times), which gives a mean of 62.89 and 81.34% at 80 or under against 62.90 and 81.33%, still assuming independent draws; and it ports UpdateDewfordTrendPerDay with one elapsed day per call, from a score of 0 rising, which first returns to that state after 12, 128 and 254 days for peaks 30, 64 and 127 (the same cycle length from every reachable starting state). The rise-and-fall lengths of 12, 25.6 and 50.8 days are twice the peak divided by 5, a continuous approximation. ↩↩↩↩↩↩↩↩↩↩↩↩

  39. pret, pokeemerald/src/union_room_chat.c, pokeemerald/include/union_room.h and pokeemerald/include/constants/global.h, commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/union_room_chat.c. The reading of why typed chat was tolerable there is the author’s. ↩

  40. pret, pokeemerald/src/easy_chat.c and pokeemerald/src/data/easy_chat/, commit 731ad5b, accessed October 4, 2026, https://github.com/pret/pokeemerald/blob/master/src/easy_chat.c and https://github.com/pret/pokeemerald/tree/master/src/data/easy_chat. ↩↩↩↩

  41. Wikipedia, “Dark Souls (video game),” sections Multiplayer (citing its source [5]) and Awards, saved October 4, 2026, https://en.wikipedia.org/wiki/Dark_Souls_(video_game). ↩↩↩↩↩↩

  42. Bandai Namco Entertainment Europe, “Dark Souls Remastered,” Key features, saved October 5, 2026, https://en.bandainamcoent.eu/dark-souls/dark-souls-remastered. Bandai Namco America’s page saved as a script shell with 127 bytes of text; FromSoftware’s own description was not reached. ↩

  43. PlayStation, “Death Stranding,” section “Unique social strand gameplay,” saved October 4, 2026, https://www.playstation.com/en-us/games/death-stranding/. ↩

  44. Wikipedia, “Splatoon (video game),” Gameplay and Multiplayer sections, citing its own sources, saved October 4, 2026, https://en.wikipedia.org/wiki/Splatoon_(video_game). Nintendo’s own Splatoon pages were not fetched. ↩↩

  45. The Pokémon Company International, pokemon.com game pages for “Pokémon Black Version 2 and Pokémon White Version 2” and “Pokémon Sun and Pokémon Moon,” saved October 4, 2026, https://www.pokemon.com/us/pokemon-video-games/pokemon-black-version-2-and-pokemon-white-version-2 and https://www.pokemon.com/us/pokemon-video-games/pokemon-sun-and-pokemon-moon; neither mentions Join Avenue or Festival Plaza. Bulbapedia was not tried. ↩

  46. Serebii.net, “Festival Plaza,” Pokémon Sun and Moon section, saved October 4, 2026, https://www.serebii.net/sunmoon/festivalplaza.shtml. A fan site and the only source used for this feature. ↩↩

  47. Serebii.net, “Gyms,” Pokémon GO section, saved October 4, 2026, https://www.serebii.net/pokemongo/gyms.shtml. A fan site and the only source used for this feature. ↩↩

  48. Solero, Houdini, an open-source Club Penguin server emulator written by fans, houdini/handlers/play/player.py (the sp, ss, sj, sma, sl, sg and se handlers, their cooldowns, server_heartbeat, which takes the time, sleeps 61 seconds and closes every client whose last heartbeat is older than that time (if penguin.heartbeat < timer: await penguin.close(), read from the saved HTML; the saved text extraction garbles that line), and server_egg_timer, which counts a player’s allowed minutes down every minute, warns at 7 and 5, and disconnects at zero), saved October 4, 2026, https://github.com/solero/houdini/blob/master/houdini/handlers/play/player.py. Evidence of what the original client expected, not Disney’s published behavior. ↩↩↩↩↩↩↩

  49. billsonnn, Nitro renderer, an open-source Habbo client written by fans, src/nitro/room/object/logic/MovingObjectLogic.ts (DEFAULT_UPDATE_INTERVAL = 500 and the lerp in update), saved October 4, 2026, https://github.com/billsonnn/nitro-renderer/blob/main/src/nitro/room/object/logic/MovingObjectLogic.ts. ↩↩↩

  50. Author’s read of the Kiradex repository (private), working tree on October 5, 2026, read-only: Kiradex/World/PlazaRig.swift (SHA-256 819cd8d6; progress as a Float at line 29, tilesPerSecond at line 101, move(other:to:facing:) at lines 526 to 542, running set only on the player at line 614, advance() at lines 652 to 672, place() and its pixel rounding at lines 722 to 727, the idleEmotes list with doze), Kiradex/World/TileMap.swift (db4272c2; tileSize of 16 at line 60 and centre at line 235), Kiradex/World/PlazaClient.swift (5c491933; the reconnect delay at line 165), Kiradex/World/PlazaStage.swift (8b4850af; the daylight phase applied to the plaza, and rig.update(Float(event.deltaTime)) at line 149) and Kiradex/World/Daylight.swift (536350dc; Daylight.Phase and its hour ranges, and Daylight.now, which takes the hour from Calendar.current, the device’s own calendar and zone). The server’s clocks were searched the same day: server/app/main.py and server/app/rooms.py use time.monotonic() and nothing in server/app names a time zone. ↩↩↩↩↩↩↩↩↩

  51. Apple Developer Documentation, GKLocalPlayer.isPersonalizedCommunicationRestricted (iOS 14.0+), the documentation JSON saved October 4, 2026, https://developer.apple.com/documentation/gamekit/gklocalplayer/ispersonalizedcommunicationrestricted. Flattened for quotation as in note 18. That a game’s own preset lines are among the “custom communication features” the page asks a game to disable, and that emotes are not, are the author’s readings. ↩↩↩↩↩↩↩↩

  52. Apple Developer Documentation, GKLocalPlayer.isUnderage (iOS 4.1+), the documentation JSON saved October 4, 2026, https://developer.apple.com/documentation/gamekit/gklocalplayer/isunderage. Flattened for quotation as in note 18. ↩↩↩↩

  53. Apple Support, “Set up parental controls to manage your child’s iPhone or iPad,” section “Set restrictions for Game Center,” saved October 4, 2026, https://support.apple.com/en-us/105121. ↩

  54. Apple Newsroom, “Apple expands tools to help parents protect kids and teens online,” June 11, 2025, saved October 4, 2026, https://www.apple.com/newsroom/2025/06/apple-expands-tools-to-help-parents-protect-kids-and-teens-online/. ↩↩↩

  55. Apple, “App Review Guidelines,” last updated June 8, 2026, guidelines 1.2, 1.3 and 5.1.4, saved October 4, 2026, https://developer.apple.com/app-store/review/guidelines/. ↩↩↩↩↩↩↩↩

  56. Federal Trade Commission, “FTC Finalizes Changes to Children’s Privacy Rule Limiting Companies’ Ability to Monetize Kids’ Data,” press release, January 16, 2025, saved October 4, 2026, https://www.ftc.gov/news-events/news/press-releases/2025/01/ftc-finalizes-changes-childrens-privacy-rule-limiting-companies-ability-monetize-kids-data. ↩

  57. Author’s read of the Kiradex server’s start command and of the web server it runs, October 5, 2026, read-only: server/Procfile (SHA-256 2e883a7e) and server/railway.toml (17f8a3ba) start uvicorn app.main:app with --proxy-headers --forwarded-allow-ips='*' and no logging options; server/requirements.txt (71c30c3b) pins uvicorn[standard]==0.37.0. In that version as installed in the server’s environment, uvicorn/config.py (379e9baf) defaults access_log to true; uvicorn/protocols/http/httptools_impl.py (b6e4010a) and h11_impl.py (e1bf8ab3) log get_client_addr(self.scope) for each request when it is; and uvicorn/protocols/websockets/websockets_impl.py (029977b2) logs '%s - "WebSocket %s" [accepted]' with the client address at INFO on the uvicorn.error logger, which --log-level warning silences. A reading of the code; no server was run and no deployed log was seen. ↩↩

  58. Blake Crosley, “Pixel-Art People: Characters and a Creator on iPhone,” blakecrosley.com, October 3, 2026, section 4 (PEGI’s rules) and sections 6 and 7 (the figure string, the manifest and the forge that draws every figure), https://blakecrosley.com/blog/pixel-art-characters-on-iphone. ↩↩↩

  59. PEGI, “What do the labels mean?,” accessed October 3, 2026, https://pegi.info/what-do-the-labels-mean, as quoted in the characters post (note 58); not re-fetched for this post. ↩↩↩

Artigos relacionados

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

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

80 min de leitura

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…

110 min de leitura

Prepare Your App for iPhone Duo: A Worked Example

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

64 min de leitura