Pump'ta provably fair nasıl çalışır
Cloudbet'te Pump'ı nasıl oynayacağınızı ve her turdaki arızalı pompanın provably fair olduğunu nasıl kontrol edeceğinizi burada bulabilirsiniz.
Pump nasıl oynanır
Pump, şansınızı zorladığınız bir oyundur: her pompalamayla bir çarpanı büyüten bir şeyi (Cloudbet versiyonunda bir balon) pompalarsınız. Kazancınızı garantiye almak için istediğiniz zaman nakde çevirin — ancak çok fazla zorlarsanız balon patlar ve bahsinizi kaybedersiniz. Başlamadan önce, genellikle ne kadar ileri gidebileceğinizi çarpanın ne kadar hızlı büyüdüğüyle dengeleyen bir zorluk seviyesi seçersiniz.
Bahsinizi yerleştirdikten sonra, balonu adım adım şişirmek için Pump'a basın. Her başarılı pompalama potansiyel ödemenizi artırır. Herhangi bir pompalamadan sonra mevcut çarpanınızı toplamak için Nakde Çevir'e basabilirsiniz — ya da daha büyük bir çarpan için pompalamaya devam edebilirsiniz. Bir sonraki pompalamanız turun arızalı pompası olursa, balon anında patlar ve tur ödemesiz sona erer.
Cloudbet Originals Pump
Cloudbet'in kendi Originals Pump'ı, turun 25 pompasından kaçının "arızalı" (balonu patlatan) olduğunu kontrol eden beş zorluk seviyesine sahiptir — Kolay, Orta, Zor, Uzman ve Usta. %99 RTP'ye, 1.000.000 $'lık bir maksimum kazanca sahiptir ve 0,01 $'dan itibaren bahisleri kabul eder. Autobet Modu, bahis miktarınızı, tur başına pompalama sayısını, kâr/zarar limitlerini ve otomatik oynanacak tur sayısını yapılandırmanıza olanak tanır — manuel oynanış ("Pump SİZİN girdinizi bekler") da her zaman kullanılabilir.
Provably fair'in genel mekanikleri için — sunucu tohumu, müşteri tohumu, nonce, hashleme ve Tur İmzasının nasıl oluşturulduğu — Cloudbet'in provably fair rehberine bakın. Aşağıda, bu rastgele sayı dizisinin özellikle bir Pump turunun sonucuna nasıl dönüştüğü anlatılmaktadır.
Rastgele sayıları bir oyun düzenine dönüştürmek
Pump'ın 25 pompası, takip edebilmemiz için A'dan Y'ye kadar etiketlenmiştir:

Tüm pompalar arızasız başlar. Oyunun rastgele sayı dizisindeki ilk sayıyı kullanarak, arızasız bir pompayı indeksine göre seçer ve arızalı hale getiririz:

Bu pompa daha sonra arızasız pompalar listesinden çıkarılır, böylece bir sonraki seçim yalnızca kalanlardan yapılır:

Bu, turun zorluk seviyesinin arızalı pompa sayısına ulaşana kadar tekrarlanır (burada orta = 3 gösterilmiştir):

Tur için her arızalı pompa seçildiğinde, onları seçmek için kullanılan sayılara artık gerek yoktur — geriye kalan yalnızca hangi pompaların arızalı olduğudur:

Pompalar sırayla tek tek tetiklendiğinden (önce A, sonra B, sonra C…), yalnızca oyuncunun ulaştığı ilk arızalı pompa gerçekten önemlidir — ondan sonrakiler asla tetiklenmez. Bu yüzden düzen, yalnızca o ilgili tek pompaya basitleştirilir:

Teknik detaylar
Arızasız pompaların sayısına P diyoruz. SHAKE256'dan gelen rastgele baytlar, 4 baytlık işaretsiz tam sayılara (0 ile 2³²−1 arasında) bölünür. Hangi pompanın arızalı olacağını adil bir şekilde seçmek için, P'ye karşı reddetme örneklemesi kullanırız, ardından kalanı (+1) arızalı hale getirilecek arızasız pompanın indeksi olarak alırız. Daha fazla arızalı pompaya ihtiyaç varsa, seçilen pompa listeden çıkarılır, P bir azaltılır ve yeni bir sayı örneklenir — bu, turun arızalı pompa sayısına ulaşana kadar tekrarlanır.
Nihai arızalı pompa düzeni, tur başlamadan önce sunucu tarafında üretilir ve kaydedilir; oyuncuyla zaten paylaşılmış olan Taahhüdü bozmadan sonrasında değiştirilemez. Oyuncunun bastığı her pompa, bu önceden taahhüt edilmiş düzene göre kontrol edilir.
Kendiniz doğrulayın
Cloudbet'in Pump uygulamasıyla birebir aynı olan küçük bir Node.js programı yazdık — turunuzun sonucunu yeniden oluşturmak için Sunucu Tohumunuzu, Müşteri Tohumunuzu, Nonce'unuzu ve zorluk seviyenizi girin. (Not: Cloudbet'te bir turun Sunucu Tohumunu açığa çıkarmak için, zaten yeni bir tohum çiftine geçmiş olmanız gerekir.)
// 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
let myDifficultyLevel = 'easy'; // ✍️YOUR_INPUT✍️: Enter your difficulty level here (easy, medium, hard, expert, or master)
const usingCustomData = false; // Change this to true if you are using your own data
// These are the possible difficulty levels (and how many faulty pumps there are per difficulty level)
const faultyPumpsPerDiff = {
'easy': 1,
'medium': 3,
'hard': 5,
'expert': 9,
'master': 12
};
// 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); // shaker256 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: Generate indices of the faulty pumps
function pickUniquePositions(numOfFaultyPumps, totalPumps, rng) {
const available = Array.from({ length: totalPumps }, (_, i) => i);
const faultyPumps = [];
for (let i = 0; i < numOfFaultyPumps; ++i) {
const index = sample(available.length, rng);
faultyPumps.push(available[index]);
available.splice(index, 1); // Remove chosen pump from list of non-faulty pumps
}
return faultyPumps;
}
// Rejection sampling for fair results
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() {
const totalPumps = 25;
let difficultyLevel = 'easy';
let nonce = 1;
if (usingCustomData) { difficultyLevel = myDifficultyLevel; nonce = myNonce; }
const numOfFaultyPumps = faultyPumpsPerDiff[difficultyLevel];
const { serverSeed, commitment } = generateServerSeed();
const clientSeed = getClientSeed();
const roundSignature = createRoundSignature(serverSeed, clientSeed, nonce);
const numbersToGenerate = 12 * 2; // We have at most 12 faulty pumps, however due to rejection sampling we may need more numbers
const rng = createRandomNumberSequence(numbersToGenerate, roundSignature);
const faultyPumps = pickUniquePositions(numOfFaultyPumps, totalPumps, rng);
let firstFaultyPump = Math.min(...faultyPumps); // Select the smallest/first faulty pump
firstFaultyPump += 1; // Increment the index so that it starts with 1, 2, 3, ... instead of 0, 1, 2
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('🎯 Difficulty level:', difficultyLevel);
console.log('💣 First faulty pump (zero-indexed, i.e., 1, 2, 3, ...):', firstFaultyPump);
})();
Önce tek bağımlılığı kurun:
npm install js-sha3
