Game
遊戲事件是將隨機生成的浮動翻譯為與遊戲特定相關的結果。這包括從擲骰子的結果到一副牌中的卡片順序,甚至是礦井遊戲中每個炸彈的位置。
以下是我們如何將浮動翻譯成我們平台上每個不同遊戲的事件的詳細說明。
希洛
在標準撲克牌中,有52種獨特的可能結果。當在我們的平台上玩二十一點、Hilo和百家樂時,我們在生成遊戲事件時使用無限數量的牌組,因此每次發牌的概率始終相同。為了計算這一點,我們將每個隨機生成的浮動乘以52,然後根據以下索引將該結果轉換為特定的牌:
// Index of 0 to 51 : ♦2 to ♣A
const CARDS = [
♦2, ♥2, ♠2, ♣2, ♦3, ♥3, ♠3, ♣3, ♦4, ♥4,
♠4, ♣4, ♦5, ♥5, ♠5, ♣5, ♦6, ♥6, ♠6, ♣6,
♦7, ♥7, ♠7, ♣7, ♦8, ♥8, ♠8, ♣8, ♦9, ♥9,
♠9, ♣9, ♦10, ♥10, ♠10, ♣10, ♦J, ♥J, ♠J,
♣J, ♦Q, ♥Q, ♠Q, ♣Q, ♦K, ♥K, ♠K, ♣K, ♦A,
♥A, ♠A, ♣A
];
// Game event translation
const card = CARDS[Math.floor(float * 52)];
這些遊戲中唯一的區別因素是,在Hilo和二十一點中,有一個光標為13,以生成52個可能的遊戲事件,以應對需要發放大量牌的情況,而在百家樂中,我們只需要生成6個遊戲事件,以覆蓋最多的可玩牌。
鑽石
當玩寶石時,有7種可能的結果,以寶石的形式呈現。為此,我們在將每個生成的浮動值轉換為相應的寶石之前,將其乘以7,並使用以下索引:
// Index of 0 to 51 : ♦2 to ♣A
const CARDS = [
♦2, ♥2, ♠2, ♣2, ♦3, ♥3, ♠3, ♣3, ♦4, ♥4,
♠4, ♣4, ♦5, ♥5, ♠5, ♣5, ♦6, ♥6, ♠6, ♣6,
♦7, ♥7, ♠7, ♣7, ♦8, ♥8, ♠8, ♣8, ♦9, ♥9,
♠9, ♣9, ♦10, ♥10, ♠10, ♣10, ♦J, ♥J, ♠J,
♣J, ♦Q, ♥Q, ♠Q, ♣Q, ♦K, ♥K, ♠K, ♣K, ♦A,
♥A, ♠A, ♣A
];
// Game event translation
const card = CARDS[Math.floor(float * 52)];
骰子
在我們的骰子版本中,我們涵蓋了00.00到100.00的可能擲骰範圍,擁有10,001種可能的結果。遊戲事件的翻譯是通過將浮動值乘以可能結果的數量,然後除以100,以確保所得數字符合我們所聲明的骰子範圍。
// Game event translation
const roll = (float * 10001) / 100;
硬幣翻轉
當玩硬幣翻轉時,有2種可能的結果,以硬幣的形式呈現。為此,我們在將每個生成的浮動值轉換為相應的寶石之前,將其乘以2,並使用以下索引:
// Index of 0 & 1 : batman & joker
const COINS = [ 0, 1 ];
// Game event translation
const coin = COINS[Math.floor(float * 2)];
林波
当涉及到Limbo時,我們使用一個兩步驟的過程。首先,我們將浮動值乘以最大可能的倍增器和賭場邊際。然後,為了生成具有 機率分布 我們將最大可能的倍增器除以第一步的結果,以創建以崩潰點形式呈現的遊戲事件。
// Game event translation with houseEdge of 0.99 (1%)
const floatPoint = 1e8 / (float * 1e8) * houseEdge;
// Crash point rounded down to required denominator
const crashPoint = Math.floor(floatPoint * 100) / 100;
// Consolidate all crash points below 1
const result = Math.max(crashPoint, 1);
Plinko
對於任何Plinko遊戲,生成的結果基於下落球的路徑。遊戲事件確定下落球在下落過程中每個級別的方向。玩家可以選擇8到16個釘子,這決定了生成從上到下的完整路徑所需的遊戲事件數量。由於只有兩個可能的方向(左或右),因此翻譯是通過將每個浮動值乘以2來完成的,映射到以下索引:
// Index of 0 to 1 : left to right
const DIRECTIONS = [ left, right ];
// Game event translation
const direction = CARDS[Math.floor(float * 2)];
Keno
傳統的Keno遊戲要求選擇10個可能的遊戲事件,形式為在棋盤上的擊中。
// Index of 0 to 39 : 1 to 40
const SQUARES = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40
];
const hit = SQUARES[Math.floor(float * 40)];
Fisher-Yates 洗牌實現用於防止生成重複的可能命中。
地雷
一個礦山遊戲由 24 個獨立的遊戲事件生成,以礦井的形式出現在棋盤上。每個浮動值乘以棋盤上仍然剩餘的可能唯一瓦片的數量。這是通過在使用相應浮動生成的每個遊戲事件結果的迭代中,將剩餘瓦片的數量減去 1 來完成的。礦山的位置是從左到右、從上到下繪製的網格位置。
Fisher-Yates 洗牌實現用於防止生成重複的可能命中。根據所選設置,使用 1 到 24 個遊戲事件結果。
輪盤
遊戲事件編號是通過將浮動乘以段中的可能結果來計算的。然後它用於確定遊戲事件結果作為乘數,使用以下索引:
// Index per payout configuration
const PAYOUTS = {
'10': {
low: [ 1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0 ],
medium: [ 0, 1.9, 0, 1.5, 0, 2, 0, 1.5, 0, 3 ],
high: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9.9 ]
},
'20': {
low: [
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0
],
medium: [
1.5, 0, 2, 0, 2, 0, 2, 0, 1.5, 0,
3, 0, 1.8, 0, 2, 0, 2, 0, 2, 0
],
high: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 19.8
]
},
'30': {
low: [
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0
],
medium: [
1.5, 0, 1.5, 0, 2, 0, 1.5, 0, 2, 0,
2, 0, 1.5, 0, 3, 0, 1.5, 0, 2, 0,
2, 0, 1.7, 0, 4, 0, 1.5, 0, 2, 0
],
high: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 29.7
]
},
'40': {
low: [
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0
],
medium: [
2, 0, 3, 0, 2, 0, 1.5, 0, 3, 0,
1.5, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0,
1.5, 0, 2, 0, 2, 0, 1.6, 0, 2, 0,
1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0
],
high: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 39.6
]
},
'50': {
low: [
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0,
1.5, 1.2, 1.2, 1.2, 0, 1.2, 1.2, 1.2, 1.2, 0
],
medium: [
2, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0,
1.5, 0, 1.5, 0, 2, 0, 1.5, 0, 3, 0,
1.5, 0, 2, 0, 1.5, 0, 2, 0, 2, 0,
1.5, 0, 3, 0, 1.5, 0, 2, 0, 1.5, 0,
1.5, 0, 5, 0, 1.5, 0, 2, 0, 1.5, 0
],
high: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 49.5
]
}
};
// Game event translation
const spin = PAYOUTS[segments][risk][float * segments];
崩潰
為了證明我們的公平性,我們生成了一個包含10,000,000個SHA256哈希的鏈,其中每個哈希都是前一個哈希的十六進制表示的哈希。鏈中的最後一個哈希是:78a9757d3be42b74a3f70239078ad9317125fe9ee630d5bdada46de963e56752
生成遊戲結果的公式:
const gameHash = hashChain.pop()
const hmac = createHmac('sha256', gameHash);
// blockHash is the hash of bitcoin block 584,500
hmac.update(blockHash);
const hex = hmac.digest('hex').substr(0, 8);
const int = parseInt(hex, 16);
// 0.01 will result in 1% house edge with a lowest crashpoint of 1
const crashpoint = Math.max(1, (2 ** 32 / (int + 1)) * (1 - 0.01))
雙倍
我们的双人游戏源自欧洲版,轮盘由 15 个不同的口袋组成,范围从 0 到 14。游戏事件是通过将浮动值乘以 15 计算得出的,然后使用以下索引转换为相应的口袋:
// Index of 0 to 14
const POCKETS = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14
];
// Game event translation
const pocket = POCKETS[Math.floor(float * 15)];
塔
塔遊戲由9個獨立的遊戲事件生成,呈現為塔上的各個層級。我們根據每個層級的難度生成一定數量的雞蛋,並且用整數表示雞蛋可以在的瓷磚範圍。
每個生成的浮點數都轉換為整數,以確定每行的雞蛋位置。例如:一個簡單難度的關卡表示為:[0, 1, 3] - 雞蛋將出現在第1、2和4個瓷磚上。
// count represents the number of eggs
// size represents the number of possible squares
const LEVEL_MAP = {
easy: { count: 3, size: 4 },
medium: { count: 2, size: 3 },
hard: { count: 1, size: 2 },
expert: { count1, size: 3 },
master: { count: 1, size: 4 },}
Fisher-Yates 洗牌實現用於防止同一行中出現重複的雞蛋。