A Link to the Past

Random Number Generator

The Random Number Generator or RNG in A Link to the Past is a weak algorithm used to generate pseudo-random numbers for events. It's also colloquial used, especially in its abbreviated "RNG" form, to refer to any random or seemingly random event.

Basic overview

The game frequently uses a subroutine in the game's code to generate a "random" number. This subroutine is called and its resulting number used when the game wants to create a variable event. This can be things like what attack an enemy gives, how long an enemy walks for, in what direction an enemy walks, etc. This number isn't truly random, and its calculation is based on just a few values that can be known in theory. In practice however, RNG is unpredictable and can't be manipulated for real-time gameplay.

Not all variable events are the result of the game using the RNG subroutine. Many seemingly random situations are due to frame rule, which are events scheduled within certain intervals of the frame counter. For example, most cannonball shooter rooms are on a 32 frame cycle that doesn't involve RNG at all. If the player could know what frame they load the room on, the results would be entirely predictable. But of course for real-time play, this isn't possible, and game behaviors that rely on frame rules are effectively "random" from the point of view of the player. This difference can still be meaningful though, especially when it comes to practicing and deeply understanding certain enemy behaviors.

RNG is significant to ALttP speedrunning. Most runs contain a few places where significant time can be lost to the game randomly giving the player bad patterns to deal with. A big example of this is the first Agahnim fight, where his RNG blue ball attacks cost the player multiple seconds every time they happen. In addition to these big, notable instances of RNG, there are many instances of small RNG throughout an ALttP run. Maybe RNG caused an enemy to walk right into Link's movement path instead of left away from him. These types of things can cost the player small amounts of time, but their larger impact is felt in forcing the player to react to emergent situations. It's frequently not enough to know one method for a room in ALttP, and learning to adjust to the many instances of micro-RNG is important for improving at the game.

Sources

There's a complete list of RNG calls on kan's blog. Anything not listed there technically isn't RNG. This page also gives probabilities for different events.

Source code analysis

This section goes into very technical detail. The information is presented with the assumption that the reader has at least basic knowledge of hexadecimal, bitwise operations, SNES memory, and/or SNES assembly.

0DBA71  LDA.w $2137     ; This is a software latch that causes address $213C to update with the horizontal dot position of the scanning beam
0DBA74  LDA.w $213C     ; This loads the horizontal dot position of the scanning beam into the A register
0DBA77  ADC.b $1A       ; Add in the current value of the frame counter
0DBA79  ADC.w $0FA1     ; Add in the previously generated RNG value
0DBA7C  STA.w $0FA1     ; Save the generated value to the RNG cache
0DBA7F  RTL             ; exit

The carry flag is never cleared before or during the routine, so an additional +1 may occur if the sum exceeds 255 at any point. After a reset, the RNG cache ($0FA1) is always set to 0. The RNG cache is also reset to 0 after a save and quit because it's near the sprite arrays, which are all cleared.

Analysis

From a mathematical standpoint, the function is not a strong function, even if the fact that it can only generate 256 values is ignored. It is, however, unpredictable enough in real-time that it will seem random enough. Even in a TAS environment, the nature of the horizontal pixel counter makes generating a specific value difficult; however, an understanding of how the number is generated makes creating a different value or generation time trivial without losing even a single frame.

In essence, the use of the horizontal pixel counter means that, in general, more work for the CPU means the function is called later, and the RNG values generated are different. The use of the frame counter means that waiting 1 or more frames may generate a different value, even without intermediate RNG calls.

All these conditions present a problem with multiple values per frame. As a simple example, imagine there is an enemy that moves in a random direction when it's spawned, either up or down. If the sprite generates an even number, it will move up; for odd, it will move down. Let's say that Link enters an area walking by holding , and the RNG generates the values $13, $F7, and $5A. In this instance, enemies A and B move down, while enemy C moves up. Now imagine that Link enters the same area walking by holding . This provides the CPU slightly more work on that frame. Let's imagine it doesn't add a lag frame, but it does delay the first RNG call. Let's say it took 3 extra horizontal pixels for the first call. Nothing else changed this frame, so the work between each call is the same. Now the values are $16, $FA, and $5D. Now enemies A and B move up, while enemy C moves down. If we continue this example but imagine a change of only one variable (e.g. the RNG value is different, but the movement was the same), we'll notice that enemies A and B always move in the same direction, and enemy C always moves in the opposite direction of those 2. For a more random generation, the expected result is that every value is independent. From our understanding of the function, though, such a set of results is impossible.

tl; dr

The RNG routine is hard for a human to predict, but it's still not very good. The values are absolutely impossible to manipulate in real time.

Last updated September 21, 2026 by joshRTA