Skip to main content

Provably Fair - Game Event

Updated over 2 weeks ago

Instant Game Implementation

Overview

This document builds upon previously explained RNG (Random Number Generation) principles to show how individual game results are produced using random integers and floating-point numbers.


Game-by-Game Breakdown


☄️ Plinko

In Plinko, the player chooses the number of rows (between 8 and 16) and a risk profile. The number of rows determines the number of buckets: X rows produce X+1 buckets.

Each possible path the ball can take corresponds to a unique trajectory, and there are 2^X total trajectories.


The random number generator (RNG) selects an integer between 0 and 2^X – 1. This integer represents a trajectory. To find the bucket:

  1. Convert the integer to binary.

  2. Count the number of 1s in the binary representation.

  3. That count is the bucket index.

The risk profile does not affect which bucket is chosen—it only determines the payout for that bucket.
Example (8 rows):

  • Total trajectories = 2^8 = 256

  • RNG generates a number between 0 and 255

  • RNG = 0 → binary 00000000 → sum of 1s = 0 → bucket index = 0

  • RNG = 200 → binary 11001000 → sum of 1s = 3 → bucket index = 3

  • RNG = 255 → binary 11111111 → sum of 1s = 8 → bucket index = 8

Pseudocode:

generatePlinkoResult(rows, riskProfile)
{
// Generate a number between 0 and 2 ^ Rows
let bucketIndex = generateInteger(2 ^ Rows)

// Get the payout for the given bucket index.
let payout = getPayout(bucketIndex, riskProfile)

return payout
}


🎲 Dice

  • Goal: Produce a number between 0.00 and 100.00 with two decimal places

  • Approach:

    • Generate a random integer between 0 (inclusive) and 10001 (exclusive)

    • Divide the result by 100

Pseudocode:

generateDiceResult() {
let randomInteger = generateInteger(10001)
let result = randomInteger / 100
return result
}


💣 Mines

  • Goal: Reveal gems while avoiding mines

  • Approach:

    • Use RNG to randomly assign numberOfMines positions on a board

    • The rest of the tiles are considered "gems"

Pseudocode:

generateMinesBoard(edgeSize, numberOfMines) {
let totalTiles = edgeSize * edgeSize
let minesPositions = []

while minesPositions.Count < numberOfMines:
let currentPosition = generateInteger(totalTiles)
if currentPosition not in minesPositions:
minesPositions.add(currentPosition)

let board = []
for index in 0 to totalTiles - 1:
if index in minesPositions:
board.add("mine")
else:
board.add("gem")

return board
}


📈 Limbo

  • Goal: Generate a multiplier > 1 (user wins if the rolled multiplier exceeds their guess)

  • Approach:

    • Generate a random float

    • Apply a hyperbolic curve to determine payout

    • Truncate to two decimal places

Formula Explanation:

  • houseEdge = 2.0 - rtp (e.g., if RTP is 0.99, house edge is 1.01)

  • multiplier = 1.0 / ((1.0 - randomFloat) * houseEdge)

Pseudocode:

generateLimboMultiplier(rtp) {
let multiplierDecimalPlaces = 2
let randomFloat = generateDouble()
let houseEdge = 2.0 - rtp
let multiplier = 1.0 / ((1.0 - randomFloat) * houseEdge)
let roundedMultiplier = truncate(multiplier, multiplierDecimalPlaces)
return roundedMultiplier
}


🎱 Keno

  • Goal: Randomly draw a set of unique numbers from a board (usually 1–40)

  • Approach:

    • Randomly select numbers, ensuring they:

      • Are not zero

      • Are not duplicates

Pseudocode:

generateKenoDraw(boardSize, drawCount) {
let numbersDrawn = []

while numbersDrawn.Count < drawCount:
let currentDraw = generateInteger(boardSize + 1)
if currentDraw == 0 or currentDraw in numbersDrawn:
continue
numbersDrawn.add(currentDraw)

return numbersDrawn
}
Did this answer your question?