but from my code block above, 9999 is found often!
It's because theoretically the probability to roll "9999" is 1/10000 and the probability to roll "10000" is 1/20000 (and you make only 10 000 tries, which is not enough to test small probabilities like those).
Can you make 100 000 or even 1 000 000 tries? That would be interesting

"theoretically the probability to roll "9999" is 1/10000 and the probability to roll "10000" is 1/20000"
Wtf? how is that possible?
How are rolls calculated?
Two strings are created :
STRING1 = "[NONCE]:[SERVER SEED]:[NONCE]"
STRING2 = "[NONCE]:[CLIENT SEED]:[NONCE]"
Then HMAC-SHA512 is used to hash STRING1 with STRING2 giving us a 128 character hex string.
The first 8 characters of the hex string are taken and converted to a decimal.
This decimal is then divided by 429496.7295 and rounded up to the nearest whole number.
This whole number is used as your roll, with the maximum possible value being 10,000.
Since it uses "round up" instead of "round off", the chance to hit 9999 and 10000 should be the same...
Round up: All numbers bigger than 9999.0000001 will be converted to 10000
Round off: Only numbers bigger than 9999.5000001 will be converted to 10000