Pokerni: fichas sem valor monetário, não se compram, não se convertem nem se transferem; adversários IA assinalados com um distintivo. Como a casa fornece os adversários, devemos-lhe uma transparência total sobre a distribuição.
O cálculo é feito inteiramente no seu navegador; nada é enviado ao servidor. Este navegador guarda a impressão recebida antes da mão e a semente recebida depois; se tiver sessão iniciada, o seu histórico também é consultado. Também pode colar os dois valores: na mesa, a impressão aparece ao passar o rato sobre o distintivo «Distribuição verificável».
O que esta verificação prova: que a impressão publicada antes da primeira carta é mesmo a da semente revelada depois da última. O baralho estava, portanto, fixado antes de ver uma única carta, e ninguém o pôde mudar durante a mão.
O que não prova: a ordem exata das 52 cartas obtida a partir da semente. Esse baralhar usa o gerador do NumPy, que o navegador não consegue reproduzir; o script Python da versão técnica reconstrói-a carta a carta.
Os adversários IA usam permanentemente o distintivo IA no seu lugar, com o seu nível. Uma IA recebe exatamente a mesma informação que um jogador humano sentado no seu lugar: as suas duas cartas, as cartas comunitárias e as jogadas públicas; nunca as cartas dos outros nem as cartas por vir. O código da distribuição é verificável, como explicado acima. O coach é um sistema automatizado: os seus conselhos são calculados por um programa, nunca dados por uma pessoa, apenas a partir das suas cartas e das jogadas públicas.
Antes de cada mão, o servidor gera uma semente de 63 bits com o gerador criptográfico do sistema (secrets.randbits(63) em Python, imprevisível, inclusive para nós). Essa semente alimenta uma permutação determinista das 52 cartas (numpy.random.default_rng(semente).permutation(52)). As duas cartas de cada jogador e depois as 5 cartas comunitárias são servidas pela ordem do baralho, sem cartas queimadas.
O servidor não pode mudar as cartas durante a mão, e prova-o:
1. Antes da mão, cada mensagem de estado contém um compromisso: commit = SHA-256("selfpoker:" + semente). A impressão fixa o baralho completo sem revelar nada.
2. Depois da mão, a mensagem final (hand_end) revela a semente. Qualquer pessoa pode então verificar que a impressão corresponde e reconstruir o baralho inteiro, incluindo as cartas não distribuídas.
import hashlib
import numpy as np
graine = 1234567890123456789 # campo "fairplay.seed" do hand_end
commit = "..." # campo "commit" das mensagens de estado
assert hashlib.sha256(f"selfpoker:{graine}".encode()).hexdigest() == commit
paquet = list(np.random.default_rng(graine).permutation(52))
# n jogadores: cartas 0..2n-1 = mãos (2 por jogador), 2n..2n+4 = cartas comunitárias
# valor = carta // 4 (0=2 … 12=ás), naipe = carta % 4 (♣♦♥♠)
Cada mão jogada é arquivada com a sua semente: o histórico completo pode ser reproduzido de forma idêntica.
Dúvidas? O código do servidor pode ser inspecionado na máquina que o aloja: é um site privado, entre pessoas de confiança.
Música de ambiente: Jason Shaw, audionautix.com, licença Creative Commons BY 4.0 (« Big Swing Band », « Closer To Jazz », « Dirt Road Traveler », « Nice And Easy », « Acoustic Rock », « Feel Good Rock »).