What is Provably Fair?
Thunder Chicken is a casino game set on an iconic Counter-Strike map. A lone chicken spawns at Bombsite B with one mission: reach Bombsite A alive. Along the way, coins are scattered across the route, with each one collected pushing the multiplier higher. The site is quiet and the path looks clear, but on this map, no position is ever truly safe. One wrong move can result in a sudden, brutally graphic death in the over-the-top style of Happy Tree Friends. Like all Thunderpick Originals, Thunder Chicken uses a cryptographic provably fair system, which means you can independently verify that the outcome of every round was determined before you placed your bet and that neither you nor Thunderpick could manipulate the result.
How It Works
The fairness of every Thunder Chicken round is guaranteed by a three-component seed system:
1. Server Seed
Before the round begins, the server generates a secret server seed and immediately commits to it by showing you its SHA-256 hash. This hash is a cryptographic fingerprint. It proves the server’s seed was fixed before you played, without revealing the seed itself.
2. Client Seed
By default your client seed is randomly assigned, but you can replace it with any string of your choice at any time before a new round begins. This gives you direct input into the outcome, ensuring that neither the server nor any third party can unilaterally determine the result.
3. Nonce
Each bet you place increments a nonce (game counter) by one. The combination of server seed + client seed + nonce produces a unique, verifiable outcome for every single round.
Step-by-Step Verification
| Step | What happens |
| Before your bet | The server generates a server seed and shows you its SHA-256 hash as a commitment. |
| During your bet | Your client seed and nonce are combined with the server seed to determine tile placement. |
| After the round | You can reveal and verify that its SHA-256 hash matches what was shown before the game. |
| Independent check | Using the script below, you can reproduce the exact death positions yourself. |
The Algorithm
The entire track is generated the moment you place your bet every step the chicken takes simply reveals the pre-committed layout. The layout is generated in two stages:
Stage 1 — Random Number Generation
The system computes HMAC-SHA256(key: serverSeed, message: “clientSeed:nonce:round”) for multiple rounds (⌈20/8⌉ = 3 rounds). Each 32-byte hash yields 8 floating-point numbers in [0, 1) by splitting the hash into 4-byte groups and applying positional byte weighting:
value = byte[0]/256 + byte[1]/256² + byte[2]/256³ + byte[3]/256⁴
This produces 24 random numbers of which 20 are used. One for each step on the 20-step track.
Stage 2 — Fisher-Yates Shuffle
The number of deaths is set by the Volatility level you chose: Low = 1, Medium = 3, High = 5, Hardcore = 10. The 20-element array (deaths first, then coins) is shuffled using the Fisher-Yates algorithm driven by the 20 random numbers. Starting with death placed at positions [0 … deathCount-1] and coins at [deathCount … 19], the shuffle iterates backwards from index 19 to 0, swapping each tile with a uniformly chosen earlier or equal position. This guarantees a perfectly uniform random permutation, identical to the servers implementation.
Verify Your Round
Paste the script below into RunJS, fill in your four values from the game history, and run it. The printed 20-step track must match exactly what you played.
// ============================================================
// PROVABLY FAIR VERIFICATION — Thunder Chicken
// Verify that your game result was not manipulated.
//
// HOW IT WORKS:
// 1. Before the game starts, the server commits to a secret
// “server seed” (you see its SHA-256 hash up front).
// 2. You supply a “client seed” and a “nonce” (bet number).
// 3. After the game, you can reveal server seed by rotating seed pair
// 4. Paste this script into https://runjs.app/play and fill in
// your four values below, then run it.
//
// If the output matches what you played, the game was fair.
// ============================================================
// ── INPUTS ──────────────────────────────────────────────────
// Replace these four values with the ones from your game.
const serverSeed = “b145e4b9fd253d00dbd0bbd28b4450d5940b7dc6f913b4cf68f793d442e9cb0c”;
const clientSeed = “amvpv6m5rqbjde5i”;
const nonce = 53; // your bet / round number
const volatilityLevel = “Low”; // paste level from list: Low | Medium | High | Hardcore
const deathsPerVolatility = { Low: 1, Medium: 3, High: 5, Hardcore: 10 };
const numberOfDeaths = deathsPerVolatility[volatilityLevel];
// ── STEP 1: Generate random numbers from the seeds ──────────
const randomNumbers = await generateRandomNumbers(serverSeed, clientSeed, nonce);
// ── STEP 2: Shuffle tiles using the random numbers ──────────
const path = shuffleTiles(numberOfDeaths, randomNumbers);
// ── STEP 3: Print all 20 tiles on a single line ─────────────
console.log(“=== Path layout (20 tiles) ===\n”);
console.log(path.join(” “));
// ── ALGORITHM ───────────────────────────────────────────────
/**
* Returns an array of 20 random numbers in [0, 1) derived from
* HMAC-SHA256(key: serverSeed, message: “clientSeed:nonce:round”).
*
* One HMAC-SHA256 hash produces 32 bytes → 8 floats (4 bytes each).
* For 20 tiles we need ⌈20/8⌉ = 3 rounds of hashing.
*/
async function generateRandomNumbers(serverSeed, clientSeed, nonce) {
const normalizedSeed = serverSeed.toUpperCase().replaceAll(” “, “”);
const keyBytes = new TextEncoder().encode(normalizedSeed);
const messageBase = `${clientSeed}:${nonce}:`;
const cryptoKey = await crypto.subtle.importKey(
“raw”,
keyBytes,
{ name: “HMAC”, hash: “SHA-256” },
false,
[“sign”]
);
const randomNumbers = new Array(20);
const hashRoundsNeeded = Math.ceil(randomNumbers.length / 8); // 8 floats per hash
let tileIndex = 0;
for (let round = 0; round < hashRoundsNeeded; round++) {
// Message changes each round so each hash is unique.
const messageBytes = new TextEncoder().encode(messageBase + round);
const hashBuffer = await crypto.subtle.sign(“HMAC”, cryptoKey, messageBytes);
const hashBytes = new Uint8Array(hashBuffer);
// Split the 32-byte hash into groups of 4 bytes.
// Convert each group to a float in [0, 1) using positional weighting:
// value = byte0/256 + byte1/256² + byte2/256³ + byte3/256⁴
// This gives ~32 bits of precision, identical to the server’s calculation.
for (let byteOffset = 0; byteOffset < hashBytes.length; byteOffset += 4) {
randomNumbers[tileIndex] =
hashBytes[byteOffset + 0] / 256 +
hashBytes[byteOffset + 1] / (256 ** 2) +
hashBytes[byteOffset + 2] / (256 ** 3) +
hashBytes[byteOffset + 3] / (256 ** 4);
tileIndex++;
if (tileIndex === randomNumbers.length)
break; // all tiles filled — stop early
}
}
return randomNumbers;
}
/**
* Places deathCount deaths on a 20-tile path using a
* Fisher-Yates shuffle driven by randomNumbers.
*
* Fisher-Yates works backwards: for each position i (from 19 down to 0),
* pick a random position j in [0, i] and swap tiles[i] with tiles[j].
* This produces a perfectly uniform random permutation.
*/
function shuffleTiles(deathCount, randomNumbers) {
// Start with an ordered list: deaths first, then safe tiles.
const tiles = [
…Array(deathCount).fill(“DEATH”),
…Array(20 – deathCount).fill(“OK”),
];
// Fisher-Yates shuffle — identical to the server’s implementation.
for (let i = 19; i >= 0; i–) {
const j = Math.floor(randomNumbers[i] * (i + 1));
[tiles[i], tiles[j]] = [tiles[j], tiles[i]];
}
return tiles;
}
}
▶ Open in RunJS — paste the code, replace the four input values with your own, and run.
Where to Find Your Values
All these parameters can be checked for each Wager in the Provably Fair expandable menu, which can be accessed in the following way:
Open “Profile menu” -> “My bets”:

Switch to Casino tab and choose Thunder Chicken wager

Expand Provably Fair menu:

In the menu User is able to find Hash prepared from Server Seed, Client Seed, and Nonce. To rotate seeds you can use the “Rotate your seed pair” feature:

Here, not only the currently used pair of seeds are displayed, but also the User is already informed about the next Server Seed (of course in Hashed form) and can Edit client seed.

After given pair of Seeds is rotated, the not-hashed Server Seed from previous pair is revealed to Player:

In the result, players have access to all parameters, which allows them to check if a given Wager was actually randomly generated.
Thunder Chicken uses the same provably fair infrastructure as all Thunderpick Originals. The algorithm is open, auditable, and reproducible by anyone with a browser.
Always practice Responsible Gambling and check out our latest promo offers and boosts. T&Cs apply. 18+ to play.