A conversation with a friend of mine led me to a bit of a realization about random numbers. I have always known the world generation was designed to be deterministic and would use the “world seed” value to initialize the stream of random numbers needed to generate a world consistently. The other side for my use of random numbers is what happens while you are actually playing the game. This wasn’t just not planned to be deterministic, it was actually planned to not be. The approach was to simply seed the in-game random numbers using the clock on the device running the game. This would make it a different set of numbers every time you fired up the game.
In-Game RNG can control things like which way a monster moves, when they shoot at you, where that shot goes, and a bunch of things like that. If they are different every time you start the game, you have to react appropriately to what you are seeing, which seems like good game play. But what happens when TAS (tool-assisted speedrun) creators want their shot at the game?
For those that don’t understand the concept of a TAS, they are usually created by feeding the game a series of inputs, such as the button presses on a controller, at a speed that is essentially as fast as the game can take them. They are created in a long an tedious process that involves trying a button press, seeing how it unfolds frame by frame, and adjusting if needed. This has the effect of controlling the game in a way that allows things that are nearly impossible for a human playing it. (In some cases, actually impossible for a human.) You can play an entire game without taking a single hit of damage or perfectly landing jumps that the timing is usually too difficult to pull off. When accurately labelled as TAS and not being used to cheat a speedrun as though it was done by a person, they can be genuinely entertaining to watch and good fun to make.
If my random numbers are based on a signal from a clock, which is always changing and is very difficult to predict ahead of time, it can make creating a TAS close to impossible. Imagine planning out a jump where a monster isn’t in the way and then moving on to the next thing having figured out the inputs. Now imagine that on some runs through the game, the random numbers being used cause a monster to be in the way. Your TAS player assumed a clear jump path, but hit a bad guy instead. From this point on when replaying your TAS instructions, the player isn’t actually where it was expected to be because it bonked into something unexpected. This is called a desync and most of the time will stop a TAS in its tracks, or at least make them comical to watch.
I don’t want to make it impossible to make a TAS, so I needed to come up with something. I also had exactly 1 bit available in my Seed Code. This is perfect! I can use that bit to toggle between “clock based RNG source” and “world seed based RNG source.” If you want to make a TAS or to play a world as a player that is consistent, you simply flip that bit to use the world seed for the in-game random seed every time and you’ve got it. Just like that, I haven’t kicked TAS creators out in the cold if the seed code is configured to allow it.
