Dice: Golden Ticket'ta provably fair nasıl çalışır

Cloudbet'te Dice: Golden Ticket'ı nasıl oynayacağınızı ve her atışın ile Golden Ticket çekilişinin provably fair olduğunu nasıl kontrol edeceğinizi burada bulabilirsiniz.

Dice: Golden Ticket nasıl oynanır

Dice: Golden Ticket (DGT), Cloudbet'in klasik Dice oyunu gibi oynanır, ancak ekstra bir katmanla: normal kazancınızın üzerine bonus bir çarpan ödeyebilen gizli bir bonus hedefi.

Temel oyun: Roll Over (2,00–99,99) veya Roll Under (0,01–98,00) seçin, ardından bahsinizi yerleştirin. Zar, hedefinizin sizin tarafınızda kalırsa, hedefinizin ima ettiği ödemeyle kazanırsınız (daha dar bir hedef = daha büyük bir çarpan).

Golden Ticket bonusu: her turda, tahtada ikinci, gizli bir değer de belirlenir — Golden Ticket — kendi bonus çarpanı 3x ile 200x arasındadır. Zar atışınız Golden Ticket'ın konumunun ±1,75 aralığında kalırsa, bu çarpanla anında ve otomatik olarak bonus ödemeyi kazanırsınız — ekstra bahis gerekmez ve normal kazancınızla birleşir.

Golden Ticket'ı doğrudan hedeflemezsiniz — hedefleyebileceğiniz veya etkileyebileceğiniz bir şey değildir, her turda tahtada bir yerdedir ve ona yakın düşmek normal oyununuzun üzerine bir bonustur.

Cloudbet Originals Dice: Golden Ticket

Cloudbet'in kendi Originals DGT'si %99 RTP, x6.730'luk bir maksimum zar çarpanı ve 1.000.000 $'lık bir maksimum kazanca sahiptir.

Dice: Golden Ticket (DGT), her Cloudbet Original'ı gibi aynı provably fair temelini kullanır — genel mekanikler (Sunucu Çekirdeği, Müşteri Çekirdeği, Nonce, SHAKE256, reddetme örneklemesi) için Provably Fair Nasıl Çalışır sayfasına bakın. Zar değeri örneklemesi de düz Dice ile aynı şekilde çalışır — DGT bunun üzerine Golden Ticket değerini ve çarpanını ekler. Aşağıda, bu dizinin özellikle DGT sonucunuza nasıl dönüştüğü anlatılmaktadır.

Rastgele sayıları bir oyun sonucuna dönüştürmek

DGT, iki değerin doğrulanabilir rastgelelik tarafından belirlendiğini kanıtlamalıdır: zarın değeri ve Golden Ticket'ın değeri.

Süreç basittir: önce, zarın nihai değeri olacak 0 ile 10000 arasında (dahil) tam bir sayı örneklenir. Ardından, Golden Ticket'ın nihai değeri olacak 175 ile 9825 arasında (dahil) başka bir tam sayı örneklenir. Her iki sayı da ikişer ondalık basamağa sahip olacak şekilde 100'e bölünür — 0 ile 100 (zar) ve 1,75 ile 98,25 (Golden Ticket) arasında değişir.

Golden Ticket'ın aralığı bilerek 1,75–98,25 olarak tutulur, 0–100 değil, böylece nereye düşerse düşsün, etrafında zarın değerinin düşüp bonusu kazanabileceği tam 3,5 genişliğinde bir "altın bölge" her zaman bulunur. Aralık kenarlara (0 veya 100) kadar uzansaydı, bir kenara yakın düşen bir Golden Ticket, ortaya düşen birine göre daha küçük bir altın bölgeye — ve daha kötü olasılıklara — sahip olurdu.

DGT'nin ayrıca benzersiz bir özelliği vardır: Golden Ticket'ın çarpanı da provably fair bir süreçle üretilir. Basitçe anlatmak gerekirse: 0 ile 1 arasında üçüncü bir rastgele sayı çekilir, ardından kesilmiş bir Pareto dağılımı kullanılarak 3 ile 200 arasında bir çarpana dönüştürülür.

Cloudbet'in kanıtlanabilir adil sisteminin Dice: Golden Ticket'ta birbirine bağlı üç değeri — zar sonucunu, Golden Ticket konumunu ve bonus çarpanını — nasıl ürettiğini gösteren diyagram.

Teknik detaylar

SHAKE256 tarafından üretilen rastgele baytlar, 0 ile 2³²-1 arasında değişen 4 baytlık işaretsiz tam sayılara bölünür. Zar değerinin 10001 olası sonucu olduğundan (0–10000 dahil), reddetme örneklemesi P = 10001 kullanır; Golden Ticket değerinin 9651 olası sonucu vardır (175–9825 dahil), bu yüzden P'si 9651'dir. (Bu adımın neden önemli olduğu için provably fair sayfasına bakın.)

Zarın ve Golden Ticket'ın değerlerinin seçilmesi: zarın rastgele sayısının değeri elde etmek için 10001'e göre modu alınır. Aynı işlem, Golden Ticket'ın rastgele sayısı için 9651 kullanılarak yapılır, ardından sonuca 175 eklenir (böylece 175–9825 aralığında olur). Her ikisi de ardından 100'e bölünür.

Golden Ticket'ın çarpanının seçilmesi (burada biraz istatistik bilgisi işe yarar): rastgele 32 bitlik bir sayı çekilir ve olası maksimum değerine bölünür, bu da 0 ile 1 arasında düzgün dağılmış bir sayı üretir. Bu değer, kesilmiş bir Pareto dağılımına dönüştürülür (alt sınır 3, üst sınır 200, alfa 1,343 — çarpanın beklenen değerinin 9 olmasını sağlayacak şekilde seçilmiştir, bu da DGT'nin %99 RTP hedefini korur), ardından iki ondalık basamağa yuvarlanır.

Oynanış

Hem zarın hem de Golden Ticket'ın değerleri sunucu tarafında üretilir ve tur sona erene kadar gizlenir — oyun başladıktan sonra fark edilmeden değiştirilemezler. Bahsinizi yerleştirdikten sonra, seçtiğiniz eşik zarın değeriyle karşılaştırılır ve Golden Ticket'ın zarın değerine olan mesafesi, bonusu kazanıp kazanmadığınızı görmek için 1,75'lik "altın bölge"ye göre kontrol edilir.

Bağımsız doğrulama için kod

Cloudbet'teki DGT uygulamasıyla birebir aynıdır — kendi oyunlarınızı doğrulamak için Sunucu Çekirdeğinizi, Müşteri Çekirdeğinizi ve Nonce'unuzu girin. (Cloudbet'te bir oyunun Sunucu Çekirdeğini açığa çıkarmak için, zaten yeni bir Sunucu Çekirdeğine geçmiş olmanız gerekir.)

Bağımlılıklar:

npm install js-sha3

Kod:

// 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);
})();

Diğer provably fair oyun anlatımları:

  1. Provably fair Mines
  2. Provably fair Pump
  3. Provably fair Plinko
  4. Provably fair Dice
  5. Provably fair Limbo
  6. Provably fair Roulette
  7. Provably fair Keno