Roulette'te provably fair nasıl çalışır

Cloudbet'te Roulette'i nasıl oynayacağınızı ve her çevirmenin provably fair olduğunu nasıl kontrol edeceğinizi burada bulabilirsiniz.

Roulette nasıl oynanır

Roulette, dönen bir topun numaralı bir çark üzerinde nereye düşeceğine bahis yaptığınız klasik bir kumarhane oyunudur. Sayı masasına bir veya daha fazla bahis yerleştirirsiniz, ardından çark döner ve top bırakılır. Numaralı bir cebe yerleştiğinde, bu kazanan sayı olur — onu kapsayan bahisler ödeme yapar, diğer her şey kaybeder.

Bahis yerleştirme

Sonuca birkaç farklı şekilde bahis yapabilirsiniz ve aynı turda birden fazla bahsi birleştirmekte özgürsünüz. İç bahisler (belirli sayılara) daha fazla öder ama tutturması daha zordur; dış bahisler (daha geniş gruplara) daha az öder ama daha sık tutar:

  1. Straight-up / Tek Sayı (35:1): tek bir kesin sayıya bahis (0–36 veya Amerikan Roulette'inde 00).
  2. Split (17:1): iki bitişik sayı.
  3. Street (11:1): art arda üç sayı.
  4. Corner (8:1): bir köşede buluşan dört sayı.
  5. First Four / Top Line (Avrupa'da 8:1 / Amerikan'da 6:1): 0'ı (ve Amerikan'da 00'ı), 1, 2, 3'ü kapsar.
  6. Six Line (5:1): iki bitişik sıra, altı sayı.
  7. Column (2:1): üç dikey sütundan biri.
  8. Dozens (2:1): 1–12, 13–24 veya 25–36.
  9. Kırmızı/Siyah, Tek/Çift, Yüksek/Düşük (her biri 1:1).

Avrupa'ya karşı Amerikan Roulette

Cloudbet her iki versiyonu da sunar. Avrupa Roulette'inin tek bir sıfırı vardır (37 olası sonuç, %97,30 RTP); Amerikan Roulette ikinci bir "00" cebi ekler (38 olası sonuç, %97 RTP), bu da kumarhane avantajını biraz artırır. Hangi versiyonu oynadığınız, bahsinizi yerleştirmeden önce açıkça gösterilmelidir. Her ikisi de önceden belirlenmiş fiş değerleri ve çevirme sayılarıyla sürekli çevirmeler için bir Otomatik Oynat modu içerir.

Bahisleriniz yerleştirildikten ve tur sonuçlandıktan sonra, kazanan bahisler oranlarına göre otomatik olarak ödenir ve masa bir sonraki tur için sıfırlanır.

Bu sayfa, Roulette'in provably fair bir rastgele sayı dizisini bir kazanan sayıya nasıl dönüştürdüğünü ele alır. Bu rastgele dizinin ilk etapta nasıl üretildiği — sunucu tohumu, müşteri tohumu, nonce, hashleme, SHAKE256 — için Cloudbet'in provable fairness açıklayıcısına bakın.

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

Roulette için, provably fair sistem kazanan sayının sonradan seçilmediğini, doğrulanabilir rastgelelikle seçildiğini kanıtlamalıdır.

Süreç basittir: Avrupa Roulette'inde, rastgele sayı dizisinden 0 ile 36 arasında tam bir sayı örneklenir — bu, kazanan sayıdır. Amerikan Roulette'inde, örneklenen sayı 0 ile 37 arasında değişebilir; "37" çift sıfıra, "00"a eşlenir; 0 ile 36 arasındaki sonuçlar olduğu gibi alınır.

Kazanan sayı nasıl seçilir

SHAKE256 tarafından üretilen rastgele baytlar (provable fairness sayfamıza bakın), 0 ile 2³²−1 arasında değişen 4 baytlık işaretsiz tam sayılara bölünür. Roulette'in kazanan sayısı 37 (Avrupa) veya 38 (Amerikan) olası sonuçtan seçilir — bu yüzden aşağıdaki adımlarda P, 37 veya 38'dir.

Bu P sonuç arasından adil bir şekilde bir kazanan sayı seçmek için reddetme örneklemesi uygularız (Provably fair nasıl çalışır sayfasına bakın), ardından ortaya çıkan sayının P'ye göre modunu alırız — kalan, kazanan sayı olur (Amerikan Roulette için "37", "00" olarak gösterilir).

Cloudbet'in kanıtlanabilir adil Roulette sisteminin, kazanan sayıyı belirlemek için rejection sampling ve bir modulo işlemini nasıl kullandığını gösteren akış şeması.

Üretildikten sonra, kazanan sayı kaydedilir ve sunucu tarafında gizlenir — tur başladıktan sonra fark edilmeden değiştirilemez veya değişiklik yapılamaz. Bahsinizi yerleştirdikten sonra, turu sonuçlandırmak için bu önceden belirlenmiş sayıyla karşılaştırılır.

Kendi Roulette sonuçlarınızı doğrulayın

Cloudbet'in Roulette uygulamasıyla (hem Avrupa hem de Amerikan) birebir aynı küçük bir Node.js programı yazdık. Sonucunuzu yeniden oluşturmak için Sunucu Tohumunuzu, Müşteri Tohumunuzu ve Nonce'unuzu girin. (Hatırlatma: Cloudbet'te bir turun Sunucu Tohumunu açığa çıkarmak için, zaten yeni bir tohum çiftine 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.
const Version = Object.freeze({ AMERICAN: "american", EUROPEAN: "european" }); // Here the possible versions are listed
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
let myRouletteVersion = Version.AMERICAN;   // ✍️YOUR_INPUT✍️: Enter your roulette version (either Version.AMERICAN or Version.EUROPEAN)
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(rouletteVersion, rng) {
  let numOfOutcomes = 0;
  if (rouletteVersion === Version.EUROPEAN) {
    numOfOutcomes = 37;
  } else if (rouletteVersion === Version.AMERICAN) {
    numOfOutcomes = 38;
  }

  let result = String(sample(numOfOutcomes, rng))

  // Convert the result '37' to '00'
  if (result === '37') {
    result = '00';
  }
  return result;
}
// Sample a number from P number of outcomes using Rejection Sampling
function sample(P, rng) {
  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;
}

// Example usage
(function main() {
  let nonce = 1;
  let rouletteVersion = Version.AMERICAN;
  if (usingCustomData) { nonce = myNonce; rouletteVersion = myRouletteVersion; }

  const { serverSeed, commitment } = generateServerSeed();
  const clientSeed = getClientSeed();

  const roundSignature = createRoundSignature(serverSeed, clientSeed, nonce);
  const numbersToGenerate = 1 * 2; // We need 1 random number, but there is an improbable case we'll need two
  const rng = createRandomNumberSequence(numbersToGenerate, roundSignature);

  const value = getGameResult(rouletteVersion, 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(`🎯 Winning Number (in the ${rouletteVersion} version):`, value);
})();

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 Dice: Golden Ticket
  6. Provably fair Limbo
  7. Provably fair Keno