可证明的公平
字节到浮点数
随机数生成器(byteGenerator)函数的输出是一个 32 字节的十六进制哈希。如游标(递增数)实现部分所述,我们使用 4 个字节的数据来生成单个游戏结果。每组 4 个字节用于生成 0 到 1 之间的浮点数(使用 4 个字节而非 1 个字节,以确保生成浮点数时具有更高的精度)。正是通过这些生成的浮点数,我们在将其转换为游戏事件之前,得到可验证公平算法的正式输出。
// Convert the hash output from the rng byteGenerator to floats
function generateFloats ({ serverSeed, clientSeed, nonce, cursor, count }) {
const rng = byteGenerator({ serverSeed, clientSeed, nonce, cursor });
const bytes = [];
while (bytes.length < count * 4) {
bytes.push(rng.next().value);
}
return _.chunk(bytes, 4).map(bytesChunk =>
bytesChunk.reduce((result, value, i) => {
const divider = 256 ** (i + 1);
const partialResult = value / divider;
return result + partialResult;
}, 0)
);
};浮点数到游戏事件
虽然随机输出的生成过程对我们所有游戏都是通用的,但在游戏结果生成的这一环节,会实施一个独特的程序来确定浮点数到游戏事件的转换方式。随机生成的浮点数会乘以该游戏当前可能剩余的结果数。例如:在使用 52 张牌的游戏中,这一操作就是将浮点数乘以 52。此方程的结果随后被转换为对应的游戏事件。对于需要生成多个游戏事件的游戏,这一过程会依次对使用 byteGenerator 函数生成的结果链中的每组 4 个字节进行处理。游戏事件的洗牌
对于如 Keno、Mines 和视频扑克(Video Poker)等不能重复结果的游戏,我们会使用 Fisher-Yates 洗牌算法 。此过程会影响浮点数到游戏事件的转换,因为每次游戏事件被转换后,剩余步骤中可能的游戏事件数量会相应减少。例如,在视频扑克中,完整牌堆中最初有 52 张牌,因此第一个游戏事件通过将浮点数乘以 52 来转换。发出该牌后,牌堆中仅剩 51 张,因此第二个游戏事件通过将第二个生成的浮点数乘以 51 来转换。此过程以相同方式继续,直到生成所需的所有游戏事件。对于 Mines 和 Keno,只需按照视频扑克中解释的相同流程,但将其应用于棋盘上的方块或位置,确保生成的每个游戏事件在结果链中之前未被生成过。



