RNG manipulation
Steering a game's random outcomes by changing when or how its generator advances or gets sampled.
On this page
RNG manipulation steers a game’s random outcomes by changing when or how its generator advances or gets sampled. The code read here establishes three different ways player timing can affect a result, but the atlas has not yet read a source that documents players using them.
- Call count Dragon Warrior (1986). Reading the controller calls
UpdateRandNum, advancing the same generator used by battle code1,2. - Frame count Pokémon Emerald (2004). Outside specified battle types, the VBlank handler advances the generator once per frame; after a save load it starts from 03.
- Hardware timing Pokémon Red and Blue (1996). Each generator call mixes in the hardware divider value, which changes independently of the frame count4.
#How it works
Changing the number of generator calls changes which value a later roll receives. In Dragon Warrior, each controller read advances the 16-bit state before the next battle result is read1,2. In Emerald, waiting changes how many times the fixed-seed sequence advances before a roll3. In Red and Blue, timing a call also changes the divider value mixed into the state4.
These mechanisms establish opportunities to steer outcomes; they do not show a repeatable player method or prove that a specific input produces a chosen result.
#History
Games
| Game | Year | How | Note |
|---|---|---|---|
| Yoshi's Cookie | 1992 | Frame count | the setup menu steps the generator every frame, so the time spent there picks the first board |
Every claim about this mechanic, by game (2)
References
- ^ ab
GetJoypadStatussteps the generator each time it reads the controller.Codenmikstas/dragon-warrior-disassembly · Ryan8bit, DW FormulasHow we know
805GetJoypadStatus: ⋮ 807LC60A: PHA ;Prepare to update the random number by first saving registers ⋮ 811LC60E: JSR UpdateRandNum ;($C55B)Get random number.
source_files/Bank03.asm lines 805–811 at ebe6a13 · upstream ↗ If you sit by idly while waiting to make a command, the random generator is run 60 times per second.
IV, Frequently Asked Questions · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ ab
UpdateRandNumsteps a 16-bit state as , and battle code reads its high byte,RandNumUB.Codenmikstas/dragon-warrior-disassembly · Ryan8bit, DW FormulasHow we know
668UpdateRandNum: ⋮ 673LC563: ASL RandNumLB ; 674LC565: ROL RandNumUB ; ⋮ 687LC57C: ADC #$81 ;
source_files/Bank03.asm lines 668–692 at ebe6a13 · upstream ↗ $9495 = $9495 * 771 + 0x81
III.A, Common algorithms · archived copy ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ abEmerald seeds
Randomfrom a hardware timer only when the player's naming screen closes, which also sets the trainer ID; the seeding from the real-time clock at power-on is compiled only into pret's BUGFIX build, so after loading a save the generator starts from 0, and the VBlank handler steps it once a frame outside link, Frontier, and recorded battles.Codepret/pokeemeraldHow we know
108#ifdef BUGFIX 109 SeedRngWithRtc(); // see comment at SeedRngWithRtc definition below
src/main.c lines 108–110 at 731ad5b · upstream ↗ 208void SeedRngAndSetTrainerId(void) ⋮ 210 u16 val = REG_TM1CNT_L; 211 SeedRng(val); ⋮ 228// FRLG commented this out to remove RTC, however Emerald didn't undo this! 229#ifdef BUGFIX
src/main.c lines 208–236 at 731ad5b · upstream ↗ 365 if (!gMain.inBattle || !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_RECORDED))) 366 Random();
src/main.c lines 365–366 at 731ad5b · upstream ↗ 700 if (sNamingScreen->templateNum == NAMING_SCREEN_PLAYER) 701 SeedRngAndSetTrainerId();
src/naming_screen.c lines 700–701 at 731ad5b · upstream ↗ 8COMMON_DATA u32 gRngValue = 0;src/random.c line 8 at 731ad5b · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
- ^ ab
Random_adds the hardware divider registerrDIVto the bytehRandomAddwith carry and subtracts it fromhRandomSubwith borrow; the VBlank handler calls it every frame, andRandomreturnshRandomAdd.Codepret/pokeredHow we know
1Random_:: 2; Generate a random 16-bit value. 3 ldh a, [rDIV] 4 ld b, a 5 ldh a, [hRandomAdd] 6 adc b 7 ldh [hRandomAdd], a 8 ldh a, [rDIV] 9 ld b, a 10 ldh a, [hRandomSub] 11 sbc b 12 ldh [hRandomSub], a
engine/math/random.asm lines 1–13 at af51989 · upstream ↗ 1Random:: 2; Return a random number in a. 3; For battles, use BattleRandom. ⋮ 7 farcall Random_ 8 ldh a, [hRandomAdd]
home/random.asm lines 1–8 at af51989 · upstream ↗ 37 call Randomhome/vblank.asm line 37 at af51989 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-20.
Checked by a second AI model, 2026-10-21.
Sources
Code
- nmikstas. 2023. “dragon-warrior-disassembly: NES Dragon Warrior software disassembly.” Commit ebe6a13. nmikstas/dragon-warrior-disassembly @ ebe6a13 · licence, all uses
- pret contributors. 2026. “pokeemerald: decompilation of Pokémon Emerald.” pret. Commit 731ad5b. pret/pokeemerald @ 731ad5b · licence, all uses
- pret contributors. 2026. “pokered: disassembly of Pokémon Red and Blue.” pret. Commit af51989. pret/pokered @ af51989 · licence, all uses
Secondary
- Ryan8bit. 2011. “Dragon Warrior (NES) Formulas.” GameFAQs. v1.0. original · archived · licence, all uses