Pokerni:筹码无货币价值,不可购买、不可兑换、不可转让;AI 对手带有标识。由于对手由平台提供,我们有责任让发牌完全透明。
计算完全在您的浏览器中完成,不会向服务器发送任何内容。本浏览器会保存牌局前收到的指纹和牌局后收到的种子;如果您已登录,也会查阅您的牌局记录。您也可以自己粘贴这两个值:在牌桌上,将鼠标悬停在“可验证的发牌”标识上即可看到指纹。
这项验证能证明什么: 在第一张牌发出前公布的指纹,确实就是最后一张牌之后公开的种子的指纹。也就是说,在您看到任何一张牌之前,整副牌就已经确定,牌局中没有人能更改它。
它不能证明什么: 由种子推导出的 52 张牌的确切顺序。这一洗牌过程使用 NumPy 的随机数生成器,浏览器无法重现;技术版本中的 Python 脚本可以逐张还原。
AI 对手在座位上始终带有 IA 标识,并显示其水平。AI 获得的信息与坐在同一位置的人类玩家完全相同:自己的两张牌、公共牌和公开的行动;绝不会看到其他玩家的牌或尚未发出的牌。发牌代码可以验证,如上所述。教练是一个自动化系统:它的建议由程序计算,从不由人给出,且仅依据您的牌和公开的行动。
每手牌开始前,服务器用系统的加密随机数生成器抽取一个 63 位的种子(Python 中的 secrets.randbits(63),不可预测,对我们也一样)。这个种子驱动 52 张牌的确定性置换(numpy.random.default_rng(种子).permutation(52))。每位玩家的两张牌,然后是 5 张公共牌,按牌堆顺序发出,不烧牌。
服务器无法在牌局中更改牌,并且能够证明这一点:
1. 牌局前,每条状态消息都包含一个承诺:commit = SHA-256("selfpoker:" + 种子)。指纹锁定整副牌,却不泄露任何内容。
2. 牌局后,结束消息(hand_end)公开种子。任何人都可以验证指纹是否一致,并还原整副牌,包括未发出的牌。
import hashlib
import numpy as np
graine = 1234567890123456789 # hand_end 中的 "fairplay.seed" 字段
commit = "..." # 状态消息中的 "commit" 字段
assert hashlib.sha256(f"selfpoker:{graine}".encode()).hexdigest() == commit
paquet = list(np.random.default_rng(graine).permutation(52))
# n 位玩家:第 0..2n-1 张 = 手牌(每人 2 张),第 2n..2n+4 张 = 公共牌
# 点数 = 牌 // 4(0=2 … 12=A),花色 = 牌 % 4(♣♦♥♠)
每一手牌都连同其种子一起存档:完整的历史可以一模一样地重放。
有疑问?服务器代码可以在托管它的机器上查看:这是一个私人网站,参与者彼此信任。
背景音乐:Jason Shaw,audionautix.com, 许可协议 Creative Commons BY 4.0 (« Big Swing Band », « Closer To Jazz », « Dirt Road Traveler », « Nice And Easy », « Acoustic Rock », « Feel Good Rock »).