← back to the table

Verify a shoe

Before the first card of a shoe is dealt, the table publishes a fingerprint of the shuffle. When the shoe ends, the seed behind that fingerprint is revealed. Put both in here and this page re-runs the shuffle from scratch. If you get the same cards in the same order, the shoe was fixed before you bet and could not have been re-ordered in response to your bets.

THE COMMITMENT

THE ALGORITHM

So you do not have to trust this page either. Re-implement it in anything and you will get the same shoe.

shoe = []
for deck in 0..(decks-1):          # 8 at the main table, 6 on the scoreboard build
  for suit in [♠, ♥, ♦, ♣]:
    for rank in [A,2,3,4,5,6,7,8,9,10,J,Q,K]:
      shoe.push({rank, suit})          # 52 x decks cards, this exact order

stream = chained HMAC-SHA256:
  key     = serverSeed
  message = "{clientSeed}:{nonce}:{round}"   # round = 0,1,2,… as bytes run out

for i from (shoe.length-1) down to 1:
  j = unbiasedInt(stream, i+1)         # rejection sampling, 2 bytes at a time
  swap shoe[i], shoe[j]

deal from the END of the array (shoe.pop())

Unbiased integer: take ceil(log2(max)/8) bytes, reject any draw at or above 256^bytes - (256^bytes mod max), then take the remainder. Plain byte % max would skew the shuffle.

WHAT THIS DOES AND DOES NOT PROVE

It proves the shoe was committed in advance and dealt honestly from that commitment. On this single-player table the seeds are generated on your own device, so it is a check you run against us rather than a third-party audit, and it cannot show that the code which picked the seed was neutral. When the live arena table opens it will use the same scheme with the seed held server-side and published to every seat at once. Either way the shuffle is not adjustable once betting opens, which is the thing people actually worry about. Use "Copy this shoe's hands" on the table before you reveal, so you have the dealt cards to compare against the replay below.