Skip to content

Instantly share code, notes, and snippets.

@PikalaxALT
Created May 10, 2017 02:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PikalaxALT/caa4fbe3e17017397da83fedce0cfda1 to your computer and use it in GitHub Desktop.
Save PikalaxALT/caa4fbe3e17017397da83fedce0cfda1 to your computer and use it in GitHub Desktop.
Brief description of how and when the RNG updates in the Pokemon Crystal overworld, with the goal of bringing RNG manipulation to gen 2 speedrunning.
The RNG update function is as follows:
* The value at 0xFF04 (rDIV) is read and added, with carry, to 0xFFE1 (hRandomAdd); the value is stored back to hRandomAdd.
* The value at rDIV is read again (it may have incremented) and subtracted, with carry, from 0xFFE2 (hRandomSub); the value is stored back to hRandomSub and returned in the accumulator.
Every time the VBlank interrupt toggles, the RNG is called. This happens once every frame.
When you turnframe or step onto a tile that can generate an encounter, the RNG is rolled a number of times for that encounter. This excludes the first 5 steps after loading the current map from a connection, warp, or battle; during this time, no wild encounters may be generated so as to prevent the player from being encounter-locked. Note that encounters are not rolled until the frame your step or turnframe finishes. The pattern is as such:
* Roll RNG and compare it with the modified encounter rate. If the rolled number is greater than the encounter rate, the routine exits here.
* If on land, roll RNG to determine whether to encounter a roaming Pokemon. This roll is used to select which roam slot to use, and is performed regardless of which map you're on and whether you share it with a roam slot. If, however, a roaming Pokemon is selected and happens to be in the same map as you, an encounter with that roaming Pokemon is queued, and the next three checks are skipped.
* Rejection sample <100 (keep rolling until the result is under 100). This is used to select an encounter slot.
* If on water, roll RNG again to select the level buff.
* If, at this point, no encounter was generated, the routine exits without a battle.
(Note: if a roaming Pokemon was selected, the encounter routine resumes here.)
* Because we need to go through all that process just to get a Pokemon and level to spawn, Repel's effect is checked now. This means that even if you have a Repel up and a level 100 Pokemon in the lead, the RNG will still advance as described.
In summary, wild Pokemon either roll RNG once and quit, or they roll RNG twice total and spit out a roaming Pokemon, or they roll RNG a total of three or more times depending on how long the rejection sampling takes.
The RNG is also called any time NPC objects are updated, depending on what NPCs are loaded. This happens once every overworld frame as long as the player is not in a menu, script, or dialogue. NPCs are updated after all player events are finished.
There are 4 types of NPCs:
* Standers stare off in a single direction. They don't move unless talked to.
* Spinners look around at random. The direction of their next facing and the amount of time between direction changes are separate RNG rolls each time the previous duration expires. Spinners have two speeds: slow (duration between 0 and 127) and fast (duration between 0 and 31).
* Wanderers walk around slowly. The direction of their next step and the amount of time between steps are separate RNG rolls each time the previous duration expires. Wanderers have one speed: slow (same as for slow spinners) and come in X, Y, and XY varieties. Their walking range is determined by their respective event headers. The new duration is rolled after the step is completed; steps usually take 8 overworld frames (30 fps). If a wanderer tries to walk outside their range or into a solid object, they will face that direction but not take a step.
* Revolvers (not to be confused with spinners) spin around in place, either clockwise or counterclockwise. Their patterns are constant and do not call RNG.
In summary, standers and revolvers don't roll the RNG, whereas spinners and wanderers each roll the RNG twice per action. All these RNG rolls use hRandomAdd instead of hRandomSub.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment