Come funziona il provably fair in Dice: Golden Ticket
Ecco come giocare a Dice: Golden Ticket su Cloudbet, e come verificare che ogni lancio ed estrazione Golden Ticket sia provably fair.
Come giocare a Dice: Golden Ticket
Dice: Golden Ticket (DGT) si gioca come il classico Dice di Cloudbet, con un livello in più: un obiettivo bonus nascosto che può pagare un moltiplicatore bonus in aggiunta alla tua vincita normale.
Gioco base: scegli Roll Over (2,00–99,99) o Roll Under (0,01–98,00), poi piazza la tua scommessa. Se il dado atterra dalla tua parte rispetto all'obiettivo, vinci in base alla quota implicata dal tuo obiettivo (un obiettivo più stretto = moltiplicatore più alto).
Il bonus Golden Ticket: a ogni round, viene impostato sul tabellone anche un secondo valore nascosto — il Golden Ticket — con un proprio moltiplicatore bonus compreso tra 3x e 200x. Se il tuo lancio di dado atterra entro ±1,75 dalla posizione del Golden Ticket, vinci la vincita bonus a quel moltiplicatore, in modo istantaneo e automatico — senza scommessa aggiuntiva richiesta, e si somma alla tua vincita normale.
Non punti direttamente al Golden Ticket — non è qualcosa su cui puoi puntare o influenzare, si trova semplicemente sempre da qualche parte sul tabellone a ogni round, e atterrarci vicino è un bonus in aggiunta alla tua giocata normale.
Cloudbet Originals Dice: Golden Ticket
Il DGT degli Originals di Cloudbet ha un RTP del 99%, un moltiplicatore massimo del dado di x6.730 e una vincita massima di 1.000.000 $.
Dice: Golden Ticket (DGT) utilizza la stessa base provably fair di ogni Cloudbet Original — consulta Come funziona il Provably Fair per i meccanismi generali (Server Seed, Client Seed, Nonce, SHAKE256, rejection sampling). Anche il campionamento del valore del dado funziona allo stesso modo del Dice normale — DGT aggiunge in più il valore e il moltiplicatore Golden Ticket. Di seguito trovi come quella sequenza diventa nello specifico il tuo risultato DGT.
Trasformare i numeri casuali in un risultato di gioco
DGT deve dimostrare che due valori sono determinati da casualità verificabile: il valore del dado e il valore del Golden Ticket.
Il processo è semplice: per prima cosa, viene campionato un numero intero compreso tra 0 e 10000 (inclusi) che sarà il valore finale del dado. Poi viene campionato un altro numero intero compreso tra 175 e 9825 (inclusi) che sarà il valore finale del Golden Ticket. Entrambi i numeri vengono divisi per 100 in modo da avere due cifre decimali ciascuno — con un intervallo da 0 a 100 (dado) e da 1,75 a 98,25 (Golden Ticket).
L'intervallo del Golden Ticket è volutamente limitato a 1,75–98,25, non 0–100, in modo che ovunque atterri, ci sia sempre un'intera "zona d'oro" larga 3,5 punti attorno a esso in cui il valore del dado può atterrare e vincere il bonus. Se l'intervallo arrivasse fino ai bordi (0 o 100), un Golden Ticket che atterra vicino a un bordo avrebbe una zona d'oro più piccola — e quote peggiori — rispetto a uno che atterra al centro.
DGT ha anche una caratteristica unica: il moltiplicatore del Golden Ticket viene generato a sua volta da un processo provably fair. In termini semplici: viene estratto un terzo numero casuale tra 0 e 1, poi convertito in un moltiplicatore tra 3 e 200 usando una distribuzione di Pareto troncata.

Dettagli tecnici
I byte casuali generati da SHAKE256 vengono suddivisi in numeri interi senza segno di 4 byte, compresi tra 0 e 2³²-1. Poiché il valore del dado ha 10001 esiti possibili (0–10000 inclusi), il rejection sampling usa P = 10001; il valore del Golden Ticket ha 9651 esiti possibili (175–9825 inclusi), quindi il suo P = 9651. (Vedi la pagina sul provably fair per capire perché questo passaggio è importante.)
Selezione dei valori del dado e del Golden Ticket: il numero casuale del dado viene preso modulo 10001 per ottenere il suo valore. Lo stesso viene fatto per il numero casuale del Golden Ticket usando 9651, poi il risultato viene incrementato di 175 (così varia da 175 a 9825). Entrambi vengono poi divisi per 100.
Selezione del moltiplicatore del Golden Ticket (qui aiuta una certa familiarità con la statistica): viene estratto un numero casuale a 32 bit e diviso per il suo valore massimo possibile, ottenendo un numero distribuito uniformemente tra 0 e 1. Quel valore viene trasformato in una distribuzione di Pareto troncata (limite inferiore 3, limite superiore 200, alpha 1,343 — scelti in modo che il valore atteso del moltiplicatore sia 9, il che rispetta l'obiettivo di RTP del 99% di DGT), poi arrotondato a due cifre decimali.
Il gioco
Sia il valore del dado che quello del Golden Ticket vengono generati lato server e nascosti fino alla fine del round — non possono essere cambiati senza essere rilevati una volta iniziata la partita. Dopo aver piazzato la scommessa, la soglia da te scelta viene confrontata con il valore del dado, e la distanza del Golden Ticket dal valore del dado viene verificata rispetto alla "zona d'oro" di 1,75 per vedere se vinci il bonus.
Codice per la verifica indipendente
Fedele all'implementazione di DGT su Cloudbet — inserisci il tuo Server Seed, Client Seed e Nonce per verificare le tue partite. (Per rivelare il Server Seed di una partita su Cloudbet, devi essere già passato a un nuovo Server Seed.)
Dipendenze:
npm install js-sha3
Il codice:
// If you are running this yourself, then you can input your own data here
// You can then compare:
// 1) Cloudbet's provided Commitment to the Commitment outputted here. This proves that the Server Seed was not altered during gameplay.
// 2) Cloudbet's provided game outcome to the game outcome outputted here. This proves that your game's outcome was determined solely by the pre-game seeds and was not altered afterwards.
let myServerSeed = 'your_server_seed'; // ✍️YOUR_INPUT✍️: Enter your (unhashed) Server Seed here
let myClientSeed = 'your_client_seed'; // ✍️YOUR_INPUT✍️: Enter your Client Seed here
let myNonce = 1; // ✍️YOUR_INPUT✍️: Enter your Nonce here
const usingCustomData = false; // Change this to true if you are using your own data
// Load libraries
const crypto = require('crypto');
const { sha3_256, shake256 } = require('js-sha3');
// Step 1: Generate a Server Seed and Commitment
// And generate a Client Seed - either by player input or by the player's browser
function generateServerSeed() {
let seed = crypto.randomBytes(32).toString('hex');
if (usingCustomData) { seed = myServerSeed; }
const commitment = sha3_256(seed);
return { 'serverSeed': seed, 'commitment': commitment };
}
function getClientSeed() {
let seed = crypto.randomBytes(32).toString('hex');
if (usingCustomData) { seed = myClientSeed; }
return seed;
}
// Step 2: Create a Round Signature with SHA3 using a Server Seed, Client Seed and Nonce
function createRoundSignature(serverSeed, clientSeed, nonce) {
return sha3_256(`${serverSeed}:${clientSeed}:${nonce}`);
}
// Step 3: Create a SHAKE256 stream generator from a Round Signature.
// To simplify this example program, this function doesn't create a stream, but instead a sequence of custom length.
function* createRandomNumberSequence(numbersToGenerate, roundSignature) {
const numOfBytes = 4 * numbersToGenerate; // 4 bytes (32 bits) per random number we generate
const byteStream = shake256.create(8 * numOfBytes); // shake takes bits as input
byteStream.update(roundSignature); // Use the Round Signature to seed the generator
const buf = Buffer.from(byteStream.digest()); // The Buffer class lets us package every 4 bytes into one 32-bit integer
for (let i = 0; i < numbersToGenerate; i++) {
yield buf.readUInt32BE(i * 4); // Read buf in 4-byte steps
}
throw new Error("No more numbers in the random number sequence! Fix: make 'numbersToGenerate' larger.");
}
// Step 4: Draw from the random number sequence to calculate the game result
function getGameResult(rng) {
// Dice
// Ranges from 0 to 100, with two decimal places
const diceMinValue = 0;
const diceMaxValue = 10000;
let diceValue = sampleFromRange(diceMinValue, diceMaxValue, rng);
diceValue = diceValue / 100; // Now the value ranges from 0 to 100
// Golden Ticket
// Ranges from 1.75 to 98.25 due to fairness
// (If it landed on 99, for example, then the chance of the dice landing near
// it would be smaller than the guarantee of 3.5%)
const gtMinValue = 175;
const gtMaxValue = 9825;
let goldenTicketValue = sampleFromRange(gtMinValue, gtMaxValue, rng);
goldenTicketValue = goldenTicketValue / 100;
// Golden Ticket Multiplier
const multiplier = getRandomNumberTruncatedPareto(rng); // Complicated maths, can be ignored ;)
return { diceValue, goldenTicketValue, multiplier };
}
// Sample a number using the truncated Pareto distribution
function getRandomNumberTruncatedPareto(rng) {
// Get a uniformly distributed number between 0 and 1
let randomInt32 = rng.next().value;
const fraction = randomInt32 / 0xFFFFFFFF;
// Truncated Pareto distribution. The expected value is 9.00
const m0 = 3;
const m1 = 200;
const alpha = 1.343;
const r = Math.pow(m0 / m1, alpha);
const inner = 1 - fraction * (1 - r);
let randomNumber = m0 / Math.pow(inner, 1 / alpha);
randomNumber = Math.round(randomNumber * 100) / 100; // Round to 2 decimal places
return randomNumber;
}
// Sample a number between 'min' to 'max' (inclusive) using Rejection Sampling
function sampleFromRange(min, max, rng) {
const P = max - min + 1;
const maxAcceptable = Math.floor(0x100000000 / P) * P;
// Rejection sampling
let rand;
do {
rand = rng.next().value;
} while (rand >= maxAcceptable);
// Modulo operation
const sampled_number = rand % P;
return sampled_number + min;
}
// Example usage
(function main() {
let nonce = 1;
if (usingCustomData) { nonce = myNonce; }
const { serverSeed, commitment } = generateServerSeed();
const clientSeed = getClientSeed();
const roundSignature = createRoundSignature(serverSeed, clientSeed, nonce);
const numbersToGenerate = 3 * 2; // We need 3 random numbers, however due to rejection sampling we may need more
const rng = createRandomNumberSequence(numbersToGenerate, roundSignature);
const { diceValue, goldenTicketValue, multiplier } = getGameResult(rng);
console.log('📝 Commitment (shown before the game):', commitment);
console.log('🔒 Server Seed (revealed after the game):', serverSeed);
console.log('🎲 Client Seed:', clientSeed);
console.log('🔢 Nonce:', nonce);
console.log('🔁 Round Signature (can be verified after the game):', roundSignature);
console.log('🎯 Dice landed on:', diceValue);
console.log('🎫 Golden ticket landed on:', goldenTicketValue);
console.log('⭐ Multiplier:', multiplier);
})();
