[ this is a working draft ]

Randomness in Lufia II

Abstract

Avoiding RNG manipulation is hard on the SNES, even when you're not trying to manipulate anything. Two methods to deal with this issue are known, and currently, the less efficient method is implemented in the leaderboard rules, whereas the more efficient method is neither enforced nor being recognized. This text attempts to explain the basics of how RNG works in Lufia II, as well as describes the different methods and suggests a best practice, backed by recently acquired knowledge.

Original research for what's being discussed here has been done by eve___ back in 2022, and the topic resurfaced in 2025 based on recent research by manmademimic. This text is written by RealCritical.

Understanding Randomness

The term "randomness" can be interpreted in a lot of different ways. In the context of this document, it refers to an unpredictable outcome of an event with multiple outcomes that are solely determined by chance (the "unpredictable" part will be qualified lots in the span of this document). To name a few examples: When an Ancient Cave floor is generated, you open a chest within the Ancient Cave, or you hit an enemy for damage, you want the results of these to be unknown and unknowable to the player for them to qualify as being random.

Computer systems in general can use very simple methods to generate randomness for non-critical applications, such as by taking the current timestamp (which will be different for pretty much any point in time you reference it) and making fancy calculations with it to get a value that might be predictable in theory, however is practically random for non-critical applications such as games.

The SNES does not have a way to grab a variable reference number from outside of the game, which means that no such method is possible. Instead, the RNG state will be identical each time you power on the console, which makes manipulated runs easy to accomplish: Provided you execute the exact same actions in the exact same time, you will always transform this RNG state into subsequently predictable RNG states, resulting in a completely predictable stream of values. In the context described above, this does not match the definition of randomness as described above.

How the Game Sources Randomness

In Lufia 2, there are a total of 55 bytes in RAM that can together be considered the RNG state - whatever you do that warrants a random outcome will source a value from these 55 bytes, determine the outcome based on that value, and then modify the list to be able to give you a different value the next time the game requires a random outcome, also commonly referred to as advancing the RNG.

For the same reason that the original RNG state cannot be undeterministic, the algorithm to produce subsequent values based on that RNG state is deterministic. This is an unavoidable technical circumstance we'll have to deal with. The only hope you have of getting practically unpredictable values is by performing unpredictable actions in the game, not making any attempt to read, log, or understand them, and proceeding until you can conclusively say that you as a runner are unaware of the current RNG state.

On top of that, while the game in general works off of the previous RNG state, there are a few situations in which RNG isn't advanced, but instead completely generated based on a seed. This is the case for a power cycle (which means turning the console off and back on, whereas a soft reset does not reset the RAM and therefore retains the RNG state that existed before the soft reset), as well as whenever the game displays save data (on the load screen and the save screen) or saves data. There is only a single RNG state after a power cycle, and different RNG states based on a byte in the save file with the highest index that isn't empty; this byte will have a value between $00 and $6F, so there are a total of 112 different RNG states that can be generated at the stated points if save files are present.

How to Work Around the Issue

For unmanipulated speedrunning categories, this is an undesirable quality. When runners want to see unknown floors, they should be able to - as a matter of fact, they are required to avoid all kinds of manipulation by the leaderboard rules.

Disallows the use of manipulation, meaning you are not allowed to manipulate the floor layout in any predeterministic way. (...)

As has been established, it is impossible to avoid deterministic RNG generation, however the possibility of being able to predict the RNG state can be worked with. There are two methods that attempt to resolve this issue, which will be looked at in detail.

Save-File Flushing

Save-File Flushing is the practice of overwriting existing save games, with the purpose of creating a different seed for subsequent attempts. This method has been created at a point in time where it was roughly understood that save files are responsible for different RNG states, however not much beyond that.

In particular, it isn't common knowledge that only the save file with the highest index that isn't empty is relevant for the RNG state. That means that if you have two save files, overwriting save file #1 will not change your RNG state on the next load screen, because the RNG state will still be generated based on save file #2.

Also, it was previously assumed that the RNG state generated from save files would work based on multiple factors, such as individual character stats, equipment, and other things that would be saved in the save file. We now know that there are only 112 different RNG states that can be generated based on save files.

On top of that, even if none of those problems existed, this practice would have to be repeated after each attempt in order to truly avoid deterministic RNG, which isn't common practice.

There is a short description of the practice and the concessions that have to be made using it in the current leaderboard rules:

(...) This means it is highly adviced to change your Floors by flushing save files every now and then to get new Floor 1 and onwards so there is no way for you to accidentally manipulate anything. Floor 1 beelining for stairs is hard to avoid because there [are] only so many Floorlayouts you can get and they are easy to recognize quickly so that is ok (...)

It should be noted that "there are only so many floor layouts you can get" is true for any method due to RNG being represented in finite numbers, as well as there being only so many possible floor layouts, however the number of possible layouts with any sort of save-file based RNG state will be exceptionally small; to be precise, due to there being only 112 possible RNG states, you can optimistically hope to see around 112×32 floor layouts for floor 1.

Four Empty Save Files

This method requires more factors than its name can convey: All four save file slots have to be empty as the name suggests to avoid save files overwriting your RNG as explained above. That allows you to use soft resetting to carry the RNG state from previous attempts into subsequent attempts.

Of course, your first attempt will still be working off of the default RNG, which is why the best practice is to prepare a session of runs by starting a game and entering the cave, executing a few arbitrary actions such as walking around erratically with enemies with random patterns being present, opening chests, feeding capsules, or basically anything else that will advance the RNG. You can also wait around Gruberik (in the town or inside one of the houses) for a while, as NPCs moving randomly will also advance the RNG. Finally, do a soft reset, and you'll be able to start your first actual attempt. For subsequent attempts, make sure you reset using soft resets, as a hard reset would reset your RNG state to the default. In doing so, each subsequent run is exceedingly likely to have its own completely unique RNG.

This may sound like a tedious process, but it should be noted that effectively the same procedure was assumed and performed to facilitate the Save File Flushing method. Also, it would only have to be set up once per set of attempts, not after every attempt.

It isn't easy to put a number on the number of possible floors you can get with this method, but assuming you can eventually hit all possible RNG states, and also assuming that each RNG state would result in a unique floor, you'd be looking at 256^55 different floor layouts.

Being able to run on four empty saves in the first place requires either a save data with unlocked Gift mode, yet no save files present, which can be downloaded in the #resources channel on the Ancient Cave Discord server, and therefore can easily be used when running on emulator, or using a flash cart. On an original cartridge, you would have to reset your save data and play through the game in Start and Retry mode respectively without saving, which on the US cartridge can be shortened significantly by using the Any% speedrun route.

Comparing the Two Methods from a Randomness Angle

The number of possible different floor 1s is absurdly different between both methods - you can optimistically get roughly 2.54e¹³⁰ as many floors with the Four Empty Saves method than with the Save File Flushing method. 'Optimistically' means that while this is based on the numbers of different RNG states, it does not necessarily mean that there are this many different floors. Regardless, the number of different floors is bound to be larger by a hardly comprehensible amount.

Effectively, using the Save File Flushing method for more than one run is effectively manipulating the RNG, as you are ensuring that you're playing with a known RNG state. Using the Save File Flushing method in the optimal way (which is by going through the motions after every run) would still only results in a microscopic fraction of possible RNG states of what you could get using a different method.

Based on this analysis, it is very hard to argue that you are doing anything at all to actually avoid RNG manipulation by using the Save File Flushing method.

Comparing the Two Methods from a Leaderboard Angle

Based on the analysis above, but also as per the concessions phrased right in the leaderboard rules, fulfilling the requirement to avoid deterministic floor layouts is not possible with the Save File Flushing method, while it is very easily achievable with the Four Empty Saves method. In light of this knowledge, and the inherent contradiction with current leaderboard rules (and even within current leaderboard rules), a change of rules for the nonmanipulated categories is likely warranted.

Not only could a rule change implement a technically much better practice as illustrated above, it would also provide runners with an unambiguous idea of what is expected for them, which currently is not the case based on many interactions within the community. A change in favor of the Four Empty Saves method would also immediately solve the matter of legitimacy of previously seen floor 1s and related items such as floor 1 Gades Blades, yet again improving the grip on the rules that runners would have.

This does raise the question of what should be done with current runs. Because a large percentage of runs have been done without using the Four Empty Saves method, any change would almost have to be done only for future submissions, leaving currently existing runs in place, for the sake of not emptying most of the leaderboard.

Phrasing rulings around these prerequisites will also not be easy, as there is more to the Four Empty Saves method than just having four empty saves. In particular, a run isn't necessarily nonmanipulated just because it used a soft reset and doesn't have any save files present, but most sane verification methods will almost have to assume that. A precise suggestion for rulings is outside of the scope of this text.

All in all, it would neither be an easy nor simple change, but it would result in an easy and simple ruleset that is actually practical and literally interpretable, free of contradicting statements towards what is and isn't allowed, and unlike today's rules would be fit to withstand thorough examination in case a run's validity will ever depend on it.

Setting up a state of being able to run is harder with the Four Empty Saves method, as you not only have to have Gift mode unlocked, but also do so without creating save files in the process, which would not be very feasible to do for an original JP cart. However, since emulator runs for the game are allowed, there is a very accessible option for anyone who doesn't want to erase their cartridge save files, or create said save data themselves.

This concludes the analysis in itself; the rest of the document features a technical documentation of several key components mentioned or referenced above.

Detailed Explanations

Random Number Generator

The RNG State consists of a table of 55 bytes ($7E:0521 - $7E:0557), as well as a pointer byte ($7E:0559) to the currently active entry in the table. Whenever the game requires a random value, it first increases the pointer byte by 1, then references the respective byte within the table. If the pointer byte would be set to 55, it is instead set to 0, and the table of random bytes is regenerated.

Regenerating is done by bitwise XOR operations, which compares individual bits and sets them if either but not both bits are set, otherwise unsets them. This is a predictable operation if you know the input data, but is sufficient to create non-reverse-calculatable RNG states.

example code { test }