Pokerni: chips zonder geldwaarde, niet te koop, niet inwisselbaar, niet overdraagbaar; AI-tegenstanders herkenbaar aan een badge. Omdat het huis de tegenstanders levert, zijn wij je volledige transparantie over de deling verschuldigd.
De berekening gebeurt volledig in je browser; er wordt niets naar de server gestuurd. Deze browser bewaart de vingerafdruk die voor de hand is ontvangen en de seed die erna is ontvangen; als je bent ingelogd, wordt ook je handgeschiedenis geraadpleegd. Je kunt de twee waarden ook zelf plakken: aan tafel verschijnt de vingerafdruk als je met de muis over de badge "Verifieerbare deling" gaat.
Wat deze controle bewijst: dat de vingerafdruk die voor de eerste kaart is gepubliceerd, echt die van de seed is die na de laatste kaart is onthuld. Het kaartspel lag dus vast voordat je ook maar één kaart zag, en niemand kon het tijdens de hand veranderen.
Wat ze niet bewijst: de exacte volgorde van de 52 kaarten die uit de seed volgt. Dat schudden gebruikt de generator van NumPy, die de browser niet kan naspelen; het Python-script in de technische versie bouwt hem kaart voor kaart na.
AI-tegenstanders dragen permanent de badge IA op hun stoel, met hun niveau. Een AI krijgt precies dezelfde informatie als een menselijke speler op haar plaats: haar twee kaarten, de gemeenschappelijke kaarten en de openbare acties; nooit de kaarten van anderen of de kaarten die nog komen. De code van de deling is verifieerbaar, zoals hierboven uitgelegd. De coach is een geautomatiseerd systeem: zijn adviezen worden door een programma berekend, nooit door een persoon gegeven, uitsluitend op basis van jouw kaarten en de openbare acties.
Voor elke hand trekt de server een seed van 63 bits met de cryptografische generator van het systeem (secrets.randbits(63) in Python, onvoorspelbaar, ook voor ons). Die seed stuurt een deterministische permutatie van de 52 kaarten aan (numpy.random.default_rng(seed).permutation(52)). De twee kaarten van elke speler en daarna de 5 gemeenschappelijke kaarten worden in de volgorde van het kaartspel gedeeld, zonder burn cards.
De server kan de kaarten tijdens een hand niet veranderen, en bewijst dat:
1. Voor de hand bevat elk statusbericht een vastlegging: commit = SHA-256("selfpoker:" + seed). De vingerafdruk legt het hele kaartspel vast zonder iets prijs te geven.
2. Na de hand onthult het eindbericht (hand_end) de seed. Iedereen kan dan controleren dat de vingerafdruk klopt en het hele kaartspel reconstrueren, inclusief de kaarten die niet zijn gedeeld.
import hashlib
import numpy as np
graine = 1234567890123456789 # veld "fairplay.seed" van hand_end
commit = "..." # veld "commit" van de statusberichten
assert hashlib.sha256(f"selfpoker:{graine}".encode()).hexdigest() == commit
paquet = list(np.random.default_rng(graine).permutation(52))
# n spelers: kaarten 0..2n-1 = handen (2 per speler), 2n..2n+4 = gemeenschappelijke kaarten
# waarde = kaart // 4 (0=2 … 12=aas), kleur = kaart % 4 (♣♦♥♠)
Elke gespeelde hand wordt met haar seed gearchiveerd: de volledige geschiedenis kan identiek worden nagespeeld.
Vragen? De servercode is in te zien op de machine die hem host: dit is een privésite, tussen mensen die elkaar vertrouwen.
Achtergrondmuziek: Jason Shaw, audionautix.com, licentie Creative Commons BY 4.0 (« Big Swing Band », « Closer To Jazz », « Dirt Road Traveler », « Nice And Easy », « Acoustic Rock », « Feel Good Rock »).