Pokerni: фишки без денежной ценности, их нельзя купить, обменять или передать; соперники-ИИ отмечены значком. Поскольку соперников предоставляет заведение, мы обязаны обеспечить полную прозрачность раздачи.
Вычисление полностью выполняется в вашем браузере; на сервер ничего не отправляется. Этот браузер хранит отпечаток, полученный до раздачи, и зерно, полученное после неё; если вы вошли в систему, проверяется и ваша история. Вы также можете вставить оба значения сами: за столом отпечаток появляется при наведении на значок «Проверяемая раздача».
Что доказывает эта проверка: что отпечаток, опубликованный до первой карты, действительно принадлежит зерну, раскрытому после последней. Значит, колода была зафиксирована до того, как вы увидели хоть одну карту, и никто не мог изменить её во время раздачи.
Чего она не доказывает: точный порядок 52 карт, полученный из зерна. Эта тасовка использует генератор NumPy, который браузер не может воспроизвести; скрипт на Python из технической версии восстанавливает её карта за картой.
Соперники-ИИ постоянно носят значок IA на своём месте, вместе со своим уровнем. ИИ получает ровно ту же информацию, что и игрок-человек на его месте: свои две карты, общие карты и публичные ходы; никогда карты других игроков и карты, которые ещё не вышли. Код раздачи можно проверить, как объяснено выше. Тренер является автоматизированной системой: его советы вычисляет программа, а не человек, только на основе ваших карт и публичных ходов.
Перед каждой раздачей сервер получает 63-битное зерно с помощью криптографического генератора системы (secrets.randbits(63) в Python, непредсказуемое, в том числе для нас). Это зерно задаёт детерминированную перестановку 52 карт (numpy.random.default_rng(зерно).permutation(52)). Две карты каждого игрока, а затем 5 общих карт раздаются в порядке колоды, без сжигания карт.
Сервер не может изменить карты во время раздачи и доказывает это:
1. Перед раздачей каждое сообщение о состоянии содержит обязательство: commit = SHA-256("selfpoker:" + зерно). Отпечаток фиксирует всю колоду, ничего не раскрывая.
2. После раздачи завершающее сообщение (hand_end) раскрывает зерно. Каждый может затем проверить, что отпечаток совпадает, и восстановить всю колоду, включая нерозданные карты.
import hashlib
import numpy as np
graine = 1234567890123456789 # поле "fairplay.seed" сообщения hand_end
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=туз), масть = карта % 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 »).