Generating Random Numbers for Instant Games
Overview
The process for generating random numbers in instant games involves two main steps:
Generate a 512-bit (64-byte) random array using:
RandomBytes = HMACSHA512(Active_Server_Seed, Active_Client_Seed:Nonce:Cursor)
Extract the needed value—either an integer or a floating point number—from the generated bytes.
📌 Note: This process differs from how random numbers are generated for scheduled games.
Generating Random Bytes
The core function is generateRandomBytes(). Here is the pseudocode:
byte[] byteGenerator(serverSeed, clientSeed, nonce, cursor) {
// 1. Create an HMAC512 hasher with server seed as the key
let hasher = HMAC512(serverSeed)
// 2. Format the message as: clientSeed:nonce:cursor
let message = clientSeed:nonce:cursor
// 3. Hash the message
let randomBytes = hasher.Hash(message)
// 4. Increment the cursor
cursor = cursor + 1
// 5. Return the random bytes
return randomBytes
}These randomBytes are then passed into either:
generateDouble()→ for floating point numbersNextPositiveInt32()→ for integers
Generating Floating Point Numbers
Floating Point Structure (IEEE 754 - 64-bit double):
1 bit: Sign (positive/negative)
11 bits: Exponent
52 bits: Mantissa/Fraction
The mantissa controls the precision for values between 0 and 1.
Algorithm
Generate 7 random bytes
Combine into a 56-bit number
Mask to keep the lowest 52 bits
Divide by
2^52→ Gives a uniform value between 0 (inclusive) and 1 (exclusive)
Pseudocode:
double generateDouble() {
bytes = generateRandomBytes(7)
bits = 0
for each byte in bytes:
bits = (bits << 8) OR byte
masked = bits AND (2^52 - 1)
randomDouble = masked / 2^52
return randomDouble
}✅ This ensures maximum precision and equal probability for all outcomes in the range [0, 1).
Generating Integers
Unlike some operators who derive integers from floats (which can cause bias), this method directly generates uniform integers, ensuring fairness and accuracy.
Why This Matters:
Mapping floats to integers (e.g.,
floor(float * N)) introduces rounding issuesThis method uses rejection sampling to avoid bias
How It Works:
Draw a 32-bit random unsigned integer (
value)Define a rejection limit:
limit = MAX_UINT32 - (MAX_UINT32 % maxExclusive)
If
value < limit, use:result = value % maxExclusive
If not, discard and draw new bytes
🛑 Rejection Sampling ensures perfectly uniform results in [0, maxExclusive)
Pseudocode:
int NextPositiveInt32(maxExclusive) {
if maxExclusive not provided:
maxExclusive = MAX_UINT32
limit = MAX_UINT32 - (MAX_UINT32 mod maxExclusive)
byteCount = HashingBitSize / 8
loop forever:
bytes = GenerateNextBytes(byteCount)
for i from 0 to bytes.length - 4 step 4:
value = convert 4 bytes at i to unsigned int
if value < limit:
return value % maxExclusive
}
Overview
We will refer to the concept of a “Scheduled Event” to mean the lifetime of one round, i.e.:
the time from which the event starts and the player can place bets (this is called the preamble),
the time the player can cash out or play (this is called in-play),
and the time the event closes (i.e., bets get settled and the event is declared as closed).
The process by which random numbers are generated in scheduled games (e.g., slide, crash) is very similar to instant games, but has two key differences:
1. Client Seed Collection
The client seed is captured by choosing the bet with the highest dollarised stake value.
The highest bidding player's client seed is then used as the client seed.
We refer to this as the Active_Client_Seed.
This ensures that the player always has full influence over the seed decision, removing the risk of tampering.
2. Server Seed Generation
Every event generates a new server seed.
We refer to this as the Active_Server_Seed.
This seed is kept secret during the lifetime of the event but is made public at the time of event closure. While the server seed is only made public at the time of event closure, players are still able to verify that the server seed was not tampered with by using the server hash, which is shared at the beginning of the event.
Random Number Generation Formula
The formula used to generate the random bytes is as follows:
Generate a random 512-bit (64-byte) array using the formula:
RandomBytes = HMACSHA512(Active_Server_Seed, Active_Client_Seed)
Extract the random number according to whether an integer or a float is needed.
Please note that the way floats and integers are generated is identical to the method used in Instant Games.
