A Betkyo dice roll can land on any of 9,999 results, so seeing the same one twice, say 41.07 on roll 30 and again on roll 95, feels like a glitch. It is the birthday problem, and it makes a repeat more likely than not by roll 119.

Where 9,999 comes from: the engine takes a 52-bit fraction 0 ≤ u < 1 from an HMAC-SHA256 keyed by the server seed (its SHA-256 hash is shown before you bet) over your client seed and a counting nonce, and returns (floor(u × 9,999) + 1) / 100, one of 0.01, 0.02, …, 99.99. The 2^52 possible values of u fall into 9,999 bins whose sizes differ by at most one (one part in 450 billion):

print(divmod(2**52, 9999)) # (450405003237, 3733): 3,733 bins get one extra value 

The chance that n rolls are all different is the product of (1 − i/N) for i = 0 … n − 1. With exact fractions:

from fractions import Fraction def rolls_for(N, p): """Fewest rolls with P(some result repeats) >= p, exact.""" distinct, n = Fraction(1), 0 while 1 - distinct < p: distinct *= Fraction(N - n, N) # roll n+1 misses the n results before it n += 1 return n, 1 - distinct for N in (365, 37, 9999): row = [rolls_for(N, Fraction(k, 100)) for k in (50, 90, 99)] print(N, [(n, f"{float(prob):.1%}") for n, prob in row]) # 365 [(23, '50.7%'), (41, '90.3%'), (57, '99.0%')] # 37 [(8, '55.7%'), (13, '90.9%'), (18, '99.3%')] # 9999 [(119, '50.6%'), (215, '90.1%'), (303, '99.0%')] 

The first row is the classic birthday answer, 23 people. A single-zero roulette wheel (37 pockets) repeats within 8 spins more often than not, and within 18 spins 99.3% of the time. The dice engine has 270 times as many results but needs only about 15 times as many rolls, because what collides is pairs: n rolls hold n(n − 1)/2 of them, each matching with probability 1/N. The shortcut sqrt(2N·ln 2) ≈ 117.7 says 118; at 118 rolls the exact chance is 49.997%, so the answer is 119.

Twice in a row is a different question: each roll matches the previous one with probability 1/N, independently, so the first back-to-back pair arrives on roll N + 1 on average. Printed: chance per roll, average wait, and the chance that 1,000 rolls (100 spins) contain one:

from fractions import Fraction for N, session in ((9999, 1000), (37, 100)): seen = 1 - (1 - Fraction(1, N)) ** (session - 1) print(N, f"{1 / N:.2%}", N + 1, f"{float(seen):.1%}") # 9999 0.01% 10000 9.5% # 37 2.70% 38 93.4% 

Why none of this is a signal: the formula's inputs are the two seeds and a nonce that counts up by one per bet. No earlier result enters it, so a number that just repeated is neither hot nor used up: the formula gives it the same one-in-9,999 share of the next roll as every other result. What grows with each roll is the number of earlier results a new one can collide with, so a repeat within a few hundred rolls is expected, and 300 rolls without one would be the rare event (1.08%). For any random source the meaningful test is a count, not a reaction: n rolls should hold about n(n − 1)/(2N) matching pairs, 49.95 in 1,000 dice rolls. Far fewer would be as odd as far more.

The longer version is on the Betkyo Journal: https://betkyo.com/en/blog/that-number-again-priced-119-dice-rolls-8-roulette-spins-and-the-birthday-problem/?utm_source=devto&utm_medium=referral&utm_campaign=journal

18+. Written with AI assistance and checked against the sources cited in the article.