Implementation
Random Number Generation
import * as _ from 'lodash-es';
import { sha256 } from 'js-sha256';
export interface SeedPair {
serverSeed: string;
clientSeed: string;
nonce: number;
cursor?: number;
count?: number;
}
export interface MultiPlayerSeed {
gameHash: string;
salt: string;
houseEdge?: number;
}
export function genByte({
serverSeed = '',
clientSeed = '',
nonce = 0,
cursor = 0,
}: SeedPair): number {
const round = Math.floor(cursor / 32);
cursor -= round * 32;
const hmac = sha256.hmac.create(serverSeed);
hmac.update(`${clientSeed}:${nonce}:${round}`);
const buffer = hmac.digest();
return buffer[cursor];
}
export function genFloats({
serverSeed = '',
clientSeed = '',
nonce = 0,
cursor = 0,
count = 1,
}: SeedPair): number[] {
const bytes = [];
for (let i = 0; i < count * 4; i++) {
const v = genByte({
serverSeed,
clientSeed,
nonce,
cursor: cursor + i,
});
bytes.push(v);
}
return _.chunk(bytes, 4).map((bytesChunk) =>
bytesChunk.reduce((result, value, i) => {
const divider = 256 ** (i + 1);
return result + value / divider;
}, 0)
);
}
export function diceRoll(p: SeedPair): number {
const f = genFloats(p)[0];
return Math.floor(f * 10001) / 100;
}
export function crashPoint(s: MultiPlayerSeed): number {
const hmac = sha256.hmac.create(s.gameHash);
hmac.update(s.salt);
const hex = hmac.hex().substring(0, 8);
const int = parseInt(hex, 16);
const p = Math.max(1, (2 ** 32 / (int + 1)) * (1 - (s.houseEdge || 0.05)));
return Math.floor(p * 100) / 100;
}
export function drawCards(p: SeedPair): PokerCard[] {
const fs = genFloats(p);
return fs.map((f) => cards[Math.floor(f * cards.length)]);
}Server Seed
Client Seed
Nonce
Cursor (Incremental Number)
Last updated