Random Number Generation in DiceGem Games
Abstract. Every shuffle, roll and spin on DiceGem comes from one small, deterministic generator that is seeded from the browser's cryptographic random source. This paper describes the seed, the generator, how its output becomes cards and dice, the size of the remaining bias, and the tests that keep game rules from using any other source of chance.
Summary
- A game session starts from 16 bytes (128 bits) taken from the browser’s cryptographic random source.
- The seed is hashed into the state of sfc32, a small, fast generator, and every random event in the game is drawn from that state in order.
- The rules of a game cannot use any other source of chance or time: a lint rule blocks them, and the tests replay hundreds of games per title to prove that the same seed and the same moves always give the same result.
1. Seed
When you start a game, the page calls crypto.getRandomValues for 16 random bytes and writes them as a
32-character hexadecimal string. That string is the seed of the session. In daily challenges everyone gets the
same seed on purpose, so everyone plays the same deal.
The seed is turned into the generator’s starting state with cyrb128, a hash that mixes the text into four 32-bit words. Different seeds give unrelated starting states.
2. Generator
The generator is sfc32 (Small Fast Chaotic, 32-bit variant) by Chris Doty-Humphrey, the author of the PractRand test suite. Its whole state is four 32-bit unsigned integers, and each step mixes them with additions, shifts and rotations plus a counter. The counter means the generator cannot fall into a short cycle.
We chose it for three reasons:
- Small, plain state. Four numbers fit in the game’s saved state as plain JSON. A game can be saved, resumed or replayed without any hidden generator object.
- Speed. Card and slot games draw many numbers per round, and bots in our tests play hundreds of games.
- Statistical quality. sfc32 is a well-studied generator that holds up in standard statistical test batteries, far beyond what a game needs.
sfc32 is not a cryptographic generator: someone who knew its full state could compute every future draw. The state is part of the game’s internal data and is never included in what the game shows you (see section 5). Credits on DiceGem are virtual and have no cash value, so there is nothing to gain by predicting a draw.
3. From numbers to cards and dice
Each step of sfc32 gives a 32-bit integer k. It becomes:
- A fraction in [0, 1): k / 2³².
- A whole number below n (a die face, a roulette pocket, a card position): floor(n · k / 2³²).
- A shuffle: the Fisher-Yates algorithm, which swaps each position with a random position at or before it. If every whole number it draws is uniform, every order of the deck is equally likely.
The second step has a very small bias: 2³² is not a multiple of n, so some results get one more of the 2³² possible inputs than others. The probability of every result stays within 1 / 2³² (about 0.00000002%) of the exact 1 / n. For a 52-card deck the difference is far below anything a player or a test could ever measure.
One limit is worth stating. A deck of 52 cards has 52! orders, about 8.1 × 10⁶⁷. A 128-bit seed can lead to at most 2¹²⁸ different sessions, about 3.4 × 10³⁸. So not every possible order of a shuffled deck can appear as the first deal of a session. This is true of every game that uses a seeded generator. It has no practical effect, because nobody can tell which orders are reachable without knowing the seed.
4. Determinism and replay
A game’s rules are a pure function: they take the current state and a move and return the next state. The generator’s four numbers are part of that state, so the rules never ask the outside world for anything.
- Lint rule. In every game’s rules and bot code,
Math.random,Date, timers and network calls are rejected by the linter before the code can be committed. - Replay test. Every game’s tests play several hundred games with bots, then play each game again from the same seed with the same moves and require the exact same final state. Any hidden source of chance makes this test fail.
- Fresh state check. The tests also confirm that setting up a game twice from the same seed gives identical states.
This is why an exact figure is possible for every casino-style bet: the odds are a property of the rules alone. The exact return-to-player paper explains how those figures are computed.
5. What the game shows you
The game keeps two things apart: its full internal state, and the observation it shows each player. The observation never contains the generator state, the cards left in the deck or other players’ hidden cards. The same bot tests check every observation for a leaked generator state and fail if one appears.
Our games run in your browser, so the code that deals the cards runs on your device. We do not claim that the internal state is impossible to inspect with developer tools; we make sure it is never displayed, and the virtual credits make inspecting it pointless.
6. Where to check
- The return of every bet and the method behind it: fairness and return to player.
- The same figures as CSV and JSON: open data.
- Questions about this paper: contact us.