By June Light, Director, Mathematics
What makes a good Random Number Generator?
Random Number Generators (RNG s) are one of the core pieces of every game. Their implementation into a gaming application is the difficult part. There are two types of RNGs: physical and software based RNGs. Physical or “True” RNGs achieve their randomness from unpredictable environmental properties such as white noise, the photoelectric effect, radioactive decay, or from a simple ball blower. Software RNGs are also called Pseudorandom RNGs (PRNGs) because they utilize an algorithm to generate a sequence of numbers whose properties closely mirror the properties of random number sequences. The pros and cons of each option must be considered when determining which is the right choice for its intended application.
A good RNG is unpredictable and provides statistically independent outcomes that conform to a proper random distribution. Using physical RNGs in an application will provide statistically random outcomes if the application they are used in doesn’t need a plethora of outcomes quickly. Electronic games utilize RNG outcomes too quickly for physical RNGs to be a viable option. PRNGs are used extensively in electronic games for this reason. There are many known good PRNGs that are free such as KISS, Mersenne Twister, Fast MT, WELL, and Knuth.
Many jurisdictions that allow online gaming require cryptographically strong RNGs. The Java class SecureRandom(), the urandom() file in linux, and Mircosoft’s RNGCryptoServiceProvider class are considered cryptographically strong RNGs. Like with “True” RNGs these cannot produce RNG outcomes fast enough for typical gaming applications. Cryptographically strong RNGs can be created from known good PRNGs by adding functionality to meet the online requirements.
When implementing a PRNG into a gaming application there are a few things to keep in mind:
- The RNG should be “Thread Safe”
- Only one instance of the RNG is used for game results
- Scaling the RNG without introducing a bias
- Cycling the RNG in the background
- Seeding the RNG using an uncontrollable event
The overall implementation of the PRNG should be kept thread safe. The algorithm could be violated if two (2) threads of code call the PRNG simultaneously. The consequences of violating the PRNG are difficult to predict. The PRNG could jump to another part of its cycle which could short cycle the RNG and reduce the number of possible outcomes to an unacceptable level. The PRNG could return the same outcome for both calls and if they are to be used for game results that could award a player too much or too little of prize skewing the overall RTP of the game. The PRNG could be corrupted and unable to recover. Maintaining the PRNG in a thread safe manner will keep the RNG operating as intended.
Using multiple PRNGs for game results can affect the overall randomness of the application. More is not always better. Using one PRNG for game outcomes allows all the overall application to conform to a proper random distribution. The PRNG can also be used for random graphics and sounds as long as the period of the PRNG is large enough. For example, the period of a Mersenne Twister is 219937-1.
Most gaming technical requirements necessitate the RNG be scaled without a bias. Unmodified PRNGs outcomes are typically in the range of 0-232-1 which requires the outcomes to be scaled down to the range of reel strip lengths, number of bingo balls, the total weights used in many bonus games, etc. If the PRNG outcome is not reduced properly the implementation will produce more small or high valued outcomes. A good scaling method will:
- Remove the natural decimal point feature of most PRNGs
- Determine the highest multiple of the required range
- Get the next PRNG outcome
- Check to see if the outcome is scaled within the maximum range and reject it if it does not.
Background cycling of a PRNG is required by most gaming jurisdictions. The purpose is to prevent the player from predicting the next outcome. There is a possibility that the player will be able to predict the next outcome if they know many of the previous outcomes in sequence. Background cycling prevents the player from knowing all of the outcomes. This is usually accomplished in a separate thread which does nothing but call the RNG in a timing sequence that cannot be predicted by the player.
Seeding a PRNG is one of the most important steps. The seed sets the beginning point of the PRNG and all outcomes after are based on the initial seed. Most jurisdictions require the seed to be something that the player cannot know. The seed must also be different in every gaming application so they do not sync up. A good seed will utilize a combination of uncontrollable events like the boot up time in milliseconds and the number of seconds since a particular epoch with the MAC address of the mother board or some variation therein.
Starting with a good RNG is important for any gaming application. Implementing the RNG into the application properly is straight forward if one knows the expectations.