Game
Server seed
Client seed
Salt
Bombs count

Seeds to bytes


HMAC_SHA512(SHA256(server_seed:salt), client_seed:0)
78959b80b46d56735b3aec5912935fe2b8cb7d4a2637d2e1ae4f72129862b335f712c3ba35dcb29cba9dd4f206df877ebcf2113bcbf9f7d410772a805a2a04bd
12014915512818010986115915823689181479522618420312574385521022517479114181529817953247181951865322017815618615721224262231351261882421759203249247212161194212890424189
HMAC_SHA512(SHA256(server_seed:salt), client_seed:1)
8c62160b2bc4978d41f545a690c72fb9115e839ee6a6e2b2f9f79e4d32d91ac35509e9c0427f1330b8eeec2e58fb9b906b460ba16c90eaa460fbc697a04bf7a6
140982211431961511416524569166144199471851794131158230166226178249247158775021726195859233192661271948184238236468825115514410770111611081442341649625119815116075247166
HMAC_SHA512(SHA256(server_seed:salt), client_seed:2)
ec12aff10fe46620beb2a078361a5c5b8769c69d843216043c2d4511b2f2b8b39eb7ed3cf13f26894d625a770fd7622a014e04a730b142498714b2d1ef009b65
2361817524115228102321901781601205426929113510519815713250224604569171782421841791581832376024163381377798901191521598421784167481776673135201782092390155101
Calculator SHA256 Calculator HMAC-SHA512

Bytes to numbers


(120, 149, 155, 128, 180, 109, 86, 115) -> [0, ..., 24] = 11
0.468750000000000000(120 / (256 ^ 1))
+0.002273559570312500(149 / (256 ^ 2))
+0.000009238719940186(155 / (256 ^ 3))
+0.000000029802322388(128 / (256 ^ 4))
+0.000000000163709046(180 / (256 ^ 5))
+0.000000000000387246(109 / (256 ^ 6))
+0.000000000000001193(086 / (256 ^ 7))
+0.000000000000000006(115 / (256 ^ 8))
=0.471032828256672587(* 25)
=11.775820706416814332
(91, 58, 236, 89, 18, 147, 95, 226) -> [0, ..., 23] = 8
0.355468750000000000(091 / (256 ^ 1))
+0.000885009765625000(058 / (256 ^ 2))
+0.000014066696166992(236 / (256 ^ 3))
+0.000000020721927285(089 / (256 ^ 4))
+0.000000000016370905(018 / (256 ^ 5))
+0.000000000000522249(147 / (256 ^ 6))
+0.000000000000001318(095 / (256 ^ 7))
+0.000000000000000012(226 / (256 ^ 8))
=0.356367847200613763(* 24)
=8.552828332814730317
(184, 203, 125, 74, 38, 55, 210, 225) -> [0, ..., 22] = 16
0.718750000000000000(184 / (256 ^ 1))
+0.003097534179687500(203 / (256 ^ 2))
+0.000007450580596924(125 / (256 ^ 3))
+0.000000017229467630(074 / (256 ^ 4))
+0.000000000034560799(038 / (256 ^ 5))
+0.000000000000195399(055 / (256 ^ 6))
+0.000000000000002914(210 / (256 ^ 7))
+0.000000000000000012(225 / (256 ^ 8))
=0.721855002024511139(* 23)
=16.602665046563757301
(174, 79, 114, 18, 152, 98, 179, 53) -> [0, ..., 21] = 14
0.679687500000000000(174 / (256 ^ 1))
+0.001205444335937500(079 / (256 ^ 2))
+0.000006794929504395(114 / (256 ^ 3))
+0.000000004190951586(018 / (256 ^ 4))
+0.000000000138243195(152 / (256 ^ 5))
+0.000000000000348166(098 / (256 ^ 6))
+0.000000000000002484(179 / (256 ^ 7))
+0.000000000000000003(053 / (256 ^ 8))
=0.680899743594987283(* 22)
=14.979794359089719791
(247, 18, 195, 186, 53, 220, 178, 156) -> [0, ..., 20] = 20
0.964843750000000000(247 / (256 ^ 1))
+0.000274658203125000(018 / (256 ^ 2))
+0.000011622905731201(195 / (256 ^ 3))
+0.000000043306499720(186 / (256 ^ 4))
+0.000000000048203219(053 / (256 ^ 5))
+0.000000000000781597(220 / (256 ^ 6))
+0.000000000000002470(178 / (256 ^ 7))
+0.000000000000000008(156 / (256 ^ 8))
=0.965130074464343179(* 21)
=20.267731563751205215
(186, 157, 212, 242, 6, 223, 135, 126) -> [0, ..., 19] = 14
0.726562500000000000(186 / (256 ^ 1))
+0.002395629882812500(157 / (256 ^ 2))
+0.000012636184692383(212 / (256 ^ 3))
+0.000000056345015764(242 / (256 ^ 4))
+0.000000000005456968(006 / (256 ^ 5))
+0.000000000000792255(223 / (256 ^ 6))
+0.000000000000001874(135 / (256 ^ 7))
+0.000000000000000007(126 / (256 ^ 8))
=0.728970822418771758(* 20)
=14.579416448375434712
(188, 242, 17, 59, 203, 249, 247, 212) -> [0, ..., 18] = 14
0.734375000000000000(188 / (256 ^ 1))
+0.003692626953125000(242 / (256 ^ 2))
+0.000001013278961182(017 / (256 ^ 3))
+0.000000013737007976(059 / (256 ^ 4))
+0.000000000184627424(203 / (256 ^ 5))
+0.000000000000884626(249 / (256 ^ 6))
+0.000000000000003428(247 / (256 ^ 7))
+0.000000000000000011(212 / (256 ^ 8))
=0.738068654154609649(* 19)
=14.023304428937583666
(16, 119, 42, 128, 90, 42, 4, 189) -> [0, ..., 17] = 1
0.062500000000000000(016 / (256 ^ 1))
+0.001815795898437500(119 / (256 ^ 2))
+0.000002503395080566(042 / (256 ^ 3))
+0.000000029802322388(128 / (256 ^ 4))
+0.000000000081854523(090 / (256 ^ 5))
+0.000000000000149214(042 / (256 ^ 6))
+0.000000000000000056(004 / (256 ^ 7))
+0.000000000000000010(189 / (256 ^ 8))
=0.064318329177844261(* 18)
=1.157729925201196775
(140, 98, 22, 11, 43, 196, 151, 141) -> [0, ..., 16] = 9
0.546875000000000000(140 / (256 ^ 1))
+0.001495361328125000(098 / (256 ^ 2))
+0.000001311302185059(022 / (256 ^ 3))
+0.000000002561137080(011 / (256 ^ 4))
+0.000000000039108272(043 / (256 ^ 5))
+0.000000000000696332(196 / (256 ^ 6))
+0.000000000000002096(151 / (256 ^ 7))
+0.000000000000000008(141 / (256 ^ 8))
=0.548371675231253852(* 17)
=9.322318478931315155
(65, 245, 69, 166, 144, 199, 47, 185) -> [0, ..., 15] = 4
0.253906250000000000(065 / (256 ^ 1))
+0.003738403320312500(245 / (256 ^ 2))
+0.000004112720489502(069 / (256 ^ 3))
+0.000000038649886847(166 / (256 ^ 4))
+0.000000000130967237(144 / (256 ^ 5))
+0.000000000000706990(199 / (256 ^ 6))
+0.000000000000000652(047 / (256 ^ 7))
+0.000000000000000010(185 / (256 ^ 8))
=0.257648804822363742(* 16)
=4.122380877157819867
(17, 94, 131, 158, 230, 166, 226, 178) -> [0, ..., 14] = 1
0.066406250000000000(017 / (256 ^ 1))
+0.001434326171875000(094 / (256 ^ 2))
+0.000007808208465576(131 / (256 ^ 3))
+0.000000036787241697(158 / (256 ^ 4))
+0.000000000209183781(230 / (256 ^ 5))
+0.000000000000589750(166 / (256 ^ 6))
+0.000000000000003136(226 / (256 ^ 7))
+0.000000000000000010(178 / (256 ^ 8))
=0.067848421377358956(* 15)
=1.017726320660384376
(249, 247, 158, 77, 50, 217, 26, 195) -> [0, ..., 13] = 13
0.972656250000000000(249 / (256 ^ 1))
+0.003768920898437500(247 / (256 ^ 2))
+0.000009417533874512(158 / (256 ^ 3))
+0.000000017927959561(077 / (256 ^ 4))
+0.000000000045474735(050 / (256 ^ 5))
+0.000000000000770939(217 / (256 ^ 6))
+0.000000000000000361(026 / (256 ^ 7))
+0.000000000000000011(195 / (256 ^ 8))
=0.976434606406517580(* 14)
=13.670084489691246787
(85, 9, 233, 192, 66, 127, 19, 48) -> [0, ..., 12] = 4
0.332031250000000000(085 / (256 ^ 1))
+0.000137329101562500(009 / (256 ^ 2))
+0.000013887882232666(233 / (256 ^ 3))
+0.000000044703483582(192 / (256 ^ 4))
+0.000000000060026650(066 / (256 ^ 5))
+0.000000000000451195(127 / (256 ^ 6))
+0.000000000000000264(019 / (256 ^ 7))
+0.000000000000000003(048 / (256 ^ 8))
=0.332182511747756870(* 13)
=4.318372652720839255
(184, 238, 236, 46, 88, 251, 155, 144) -> [0, ..., 11] = 8
0.718750000000000000(184 / (256 ^ 1))
+0.003631591796875000(238 / (256 ^ 2))
+0.000014066696166992(236 / (256 ^ 3))
+0.000000010710209608(046 / (256 ^ 4))
+0.000000000080035534(088 / (256 ^ 5))
+0.000000000000891731(251 / (256 ^ 6))
+0.000000000000002151(155 / (256 ^ 7))
+0.000000000000000008(144 / (256 ^ 8))
=0.722395669284180975(* 12)
=8.668748031410171251
(107, 70, 11, 161, 108, 144, 234, 164) -> [0, ..., 10] = 4
0.417968750000000000(107 / (256 ^ 1))
+0.001068115234375000(070 / (256 ^ 2))
+0.000000655651092529(011 / (256 ^ 3))
+0.000000037485733628(161 / (256 ^ 4))
+0.000000000098225428(108 / (256 ^ 5))
+0.000000000000511591(144 / (256 ^ 6))
+0.000000000000003247(234 / (256 ^ 7))
+0.000000000000000009(164 / (256 ^ 8))
=0.419037558469941396(* 11)
=4.609413143169355465
(96, 251, 198, 151, 160, 75, 247, 166) -> [0, ..., 9] = 3
0.375000000000000000(096 / (256 ^ 1))
+0.003829956054687500(251 / (256 ^ 2))
+0.000011801719665527(198 / (256 ^ 3))
+0.000000035157427192(151 / (256 ^ 4))
+0.000000000145519152(160 / (256 ^ 5))
+0.000000000000266454(075 / (256 ^ 6))
+0.000000000000003428(247 / (256 ^ 7))
+0.000000000000000009(166 / (256 ^ 8))
=0.378841793077569267(* 10)
=3.788417930775692888
(236, 18, 175, 241, 15, 228, 102, 32) -> [0, ..., 8] = 8
0.921875000000000000(236 / (256 ^ 1))
+0.000274658203125000(018 / (256 ^ 2))
+0.000010430812835693(175 / (256 ^ 3))
+0.000000056112185121(241 / (256 ^ 4))
+0.000000000013642421(015 / (256 ^ 5))
+0.000000000000810019(228 / (256 ^ 6))
+0.000000000000001416(102 / (256 ^ 7))
+0.000000000000000002(032 / (256 ^ 8))
=0.922160145142599696(* 9)
=8.299441306283396713
(190, 178, 160, 120, 54, 26, 92, 91) -> [0, ..., 7] = 5
0.742187500000000000(190 / (256 ^ 1))
+0.002716064453125000(178 / (256 ^ 2))
+0.000009536743164063(160 / (256 ^ 3))
+0.000000027939677238(120 / (256 ^ 4))
+0.000000000049112714(054 / (256 ^ 5))
+0.000000000000092371(026 / (256 ^ 6))
+0.000000000000001277(092 / (256 ^ 7))
+0.000000000000000005(091 / (256 ^ 8))
=0.744913129185172718(* 8)
=5.959305033481381741
(135, 105, 198, 157, 132, 50, 22, 4) -> [0, ..., 6] = 3
0.527343750000000000(135 / (256 ^ 1))
+0.001602172851562500(105 / (256 ^ 2))
+0.000011801719665527(198 / (256 ^ 3))
+0.000000036554411054(157 / (256 ^ 4))
+0.000000000120053301(132 / (256 ^ 5))
+0.000000000000177636(050 / (256 ^ 6))
+0.000000000000000305(022 / (256 ^ 7))
+0.000000000000000000(004 / (256 ^ 8))
=0.528957761245870350(* 7)
=3.702704328721092342
(60, 45, 69, 17, 178, 242, 184, 179) -> [0, ..., 5] = 1
0.234375000000000000(060 / (256 ^ 1))
+0.000686645507812500(045 / (256 ^ 2))
+0.000004112720489502(069 / (256 ^ 3))
+0.000000003958120942(017 / (256 ^ 4))
+0.000000000161890057(178 / (256 ^ 5))
+0.000000000000859757(242 / (256 ^ 6))
+0.000000000000002554(184 / (256 ^ 7))
+0.000000000000000010(179 / (256 ^ 8))
=0.235065762349175311(* 6)
=1.410394574095051867
(158, 183, 237, 60, 241, 63, 38, 137) -> [0, ..., 4] = 3
0.617187500000000000(158 / (256 ^ 1))
+0.002792358398437500(183 / (256 ^ 2))
+0.000014126300811768(237 / (256 ^ 3))
+0.000000013969838619(060 / (256 ^ 4))
+0.000000000219188223(241 / (256 ^ 5))
+0.000000000000223821(063 / (256 ^ 6))
+0.000000000000000527(038 / (256 ^ 7))
+0.000000000000000007(137 / (256 ^ 8))
=0.619993998888500486(* 5)
=3.099969994442502319
(77, 98, 90, 119, 15, 215, 98, 42) -> [0, ..., 3] = 1
0.300781250000000000(077 / (256 ^ 1))
+0.001495361328125000(098 / (256 ^ 2))
+0.000005364418029785(090 / (256 ^ 3))
+0.000000027706846595(119 / (256 ^ 4))
+0.000000000013642421(015 / (256 ^ 5))
+0.000000000000763833(215 / (256 ^ 6))
+0.000000000000001360(098 / (256 ^ 7))
+0.000000000000000002(042 / (256 ^ 8))
=0.302282003467408966(* 4)
=1.209128013869635865
(1, 78, 4, 167, 48, 177, 66, 73) -> [0, ..., 2] = 0
0.003906250000000000(001 / (256 ^ 1))
+0.001190185546875000(078 / (256 ^ 2))
+0.000000238418579102(004 / (256 ^ 3))
+0.000000038882717490(167 / (256 ^ 4))
+0.000000000043655746(048 / (256 ^ 5))
+0.000000000000628830(177 / (256 ^ 6))
+0.000000000000000916(066 / (256 ^ 7))
+0.000000000000000004(073 / (256 ^ 8))
=0.005096712892457088(* 3)
=0.015290138677371265
(135, 20, 178, 209, 239, 0, 155, 101) -> [0, ..., 1] = 1
0.527343750000000000(135 / (256 ^ 1))
+0.000305175781250000(020 / (256 ^ 2))
+0.000010609626770020(178 / (256 ^ 3))
+0.000000048661604524(209 / (256 ^ 4))
+0.000000000217369234(239 / (256 ^ 5))
+0.000000000000000000(000 / (256 ^ 6))
+0.000000000000002151(155 / (256 ^ 7))
+0.000000000000000005(101 / (256 ^ 8))
=0.527659584286995886(* 2)
=1.055319168573991773

Numbers to result


24 numbers received on the previous step (we will call them an index array) from the interval [0, 1) will be convertedto the position of bombs using the Fisher-Yates shuffle.

Lets create 2 arrays: the original array containing numbers from 0 to 24 in sequence, and an empty permutation array, into which we will "transfer" elements from the original array as the algorithm progresses, thus creating a random permutation. At each step, we will transfer one element from the original array to the end of the permutation array. The position of the element chosen from the original array will be determined as the product of the current length of the original array and the i-th number from the index array, where i is the number of the current step.

Thus, in 24 steps, we will obtain a permutation of 24 elements, where the first element determines the position of the first mine, the second element determines the position of the second mine, and so on. For example, if there are only 3 mines in the game, their positions will be equal to the first three elements of this permutation.

The counting of cells on the minefield starts from the top left corner (position #0), from left to right, and from top to bottom (the bottom right cell - position #24).

Step Index array element Original array Permutation
1 11 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] [11]
2 8 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] [11, 8]
3 16 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] [11, 8, 18]
4 14 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24] [11, 8, 18, 16]
5 20 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23, 24] [11, 8, 18, 16, 24]
6 14 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17]
7 14 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 19, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19]
8 1 [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19, 1]
9 9 [0, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 14, 15, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19, 1, 12]
10 4 [0, 2, 3, 4, 5, 6, 7, 9, 10, 13, 14, 15, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5]
11 1 [0, 2, 3, 4, 6, 7, 9, 10, 13, 14, 15, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2]
12 13 [0, 3, 4, 6, 7, 9, 10, 13, 14, 15, 20, 21, 22, 23] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23]
13 4 [0, 3, 4, 6, 7, 9, 10, 13, 14, 15, 20, 21, 22] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7]
14 8 [0, 3, 4, 6, 9, 10, 13, 14, 15, 20, 21, 22] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15]
15 4 [0, 3, 4, 6, 9, 10, 13, 14, 20, 21, 22] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9]
16 3 [0, 3, 4, 6, 10, 13, 14, 20, 21, 22] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6]
17 8 [0, 3, 4, 10, 13, 14, 20, 21, 22] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22]
18 5 [0, 3, 4, 10, 13, 14, 20, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14]
19 3 [0, 3, 4, 10, 13, 20, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10]
20 1 [0, 3, 4, 13, 20, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3]
21 3 [0, 4, 13, 20, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3, 20]
22 1 [0, 4, 13, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3, 20, 4]
23 0 [0, 13, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3, 20, 4, 0]
24 1 [13, 21] [11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3, 20, 4, 0, 21]
Result
[11, 8, 18, 16, 24, 17, 19, 1, 12, 5, 2, 23, 7, 15, 9, 6, 22, 14, 10, 3, 20, 4, 0, 21]

The highlighted numbers indicate the positions where 3 mines are located. For details on the implementation algorithm, you can refer to the "Implementation" tab.

Provable fair


The fundamental concept of provable fairness is that players have the ability to prove and confirm that the results of their games are fair and have not been manipulated by the site. This is achieved through the use of the so-called commitment scheme, where random game outcomes are generated based on a set of parameters, some of which are known to the player before the start of the round. The commitment scheme is used to ensure that the player influences all received outcomes, while the parameters are chosen in such a way that the player cannot predict the outcome of any game in advance, but can always deterministically confirm the fairness of the game.

RNG parameters


In the proposed system as the input parameters of the random number generator, the following set of four parameters is used

Server seed

The server seed is generated by our system and consists of 32 bytes represented as a 64-character string. For modes where only one player participates in one round, the player has the opportunity to request the system to generate a new server seed, the new value of which will be immediately displayed. These modes include:

  • Mines
  • Dice
  • Tower
  • Slot
  • Plinko

For modes where multiple players participate in one round, a single player cannot request the system to generate a new server seed (this is because the system is unclear which player's request to satisfy), however, the fairness guarantee in these modes is that the server seed is constant, meaning it does not change from round to round. A pre-calculated hash of a specific bitcoin block is taken as the value of the server seed. The modes and their corresponding constant server seeds are provided below:

Client seed

The client seed belongs to the player and is used to allow the player to influence the generated numbers. Initially, the client seed is generated by the system when registering on the website, however, at any time, the user can change their client seed (note that, unlike the server seed, it is possible to enter the value of the desired client seed). For modes where only one player participates in one round, the user's client seed is used as the client seed. These modes are listed below:

  • Mines
  • Dice
  • Tower
  • Plinko

For modes where multiple players participate in one round, a user's custom client seed cannot be used as the client seed (this is because the system is unclear which player's seed to use), however, the fairness guarantee in these modes is that the client seed is constant, meaning it does not change from round to round. A pre-calculated hash of a specific bitcoin block is taken as the value of the client seed. The modes and their corresponding constant client seeds are provided below:

Salt

Since the server seed and client seed are constant and known to the user, the salt parameter is used in the scheme to obtain different results with the same pair of client seed + server seed. The salt is a random 32-byte value represented as a 64-character string. This parameter is unique for each round and is not available to the player before the start of the game, but is displayed at the end of the game (the so-called commitment unveiling phase in the commitment scheme).

Cursor

The random number generator, using the server seed, client seed, and salt as input parameters, generates random 64 bytes represented as a 128-character string. This string is used to generate 8 random numbers. However, some modes require generating more numbers. For this purpose, an additional parameter called cursor is introduced, which is initially set to 0 and is incremented by one each time it is necessary to generate the next 8 numbers within one round. Modes that use more than one cursor:

  • Mines (3 cursors)
  • Tower (5 cursors)
  • Slot (from 1 to 180 cursors)
  • Plinko (from 2 to 200 cursors)

Games that use exactly one cursor:

  • Dice
  • Double
  • x50
  • Jackpot
  • Crash

Random number generator


The generation of random bytes based on the input parameters is carried out using functions HMAC-SHA512 и SHA256

bytes = HMAC-SHA512(SHA256(server_seed:salt), client_seed:cursor)

The result of the generation is random 64 bytes, which are then divided into 8 blocks of 8 bytes, and each block is used to generate a random number in the range [0, 1). The algorithm for converting the block in the number is given in the section "Implementation", and is also graphically demonstrated when checking the game.

Test battery Dieharder


The Dieharder Test Battery is a set of statistical tests for measuring the quality of a random number generator. It consists of a multitude of tests (including the Diehard test suite and the NIST Test Suite), which are collectively considered one of the most stringent test suites available. We generated 1 billion random numbers using the aforementioned generator and tested this set using Dieharder with the following options

dieharder -g 202 -f ./rng_output_test_random_CS -a |& tee -a output_dh_random_CS.txt

For greater statistical significance, we conducted the test twice on different sets. The test results show that the provided random number generator indeed generates unbiased random sequences without statistically significant patterns. Reports in the form of text files are available at the following links:
output_dh_random_CS_1.txt
output_dh_random_CS_2.txt

Generation of random numbers


For any round, client seed, server seed, salt, and cursor serve as the sole input parameters for the generator. The generator transforms these parameters into a sequence of random bytes using the HMAC-SHA512 and SHA256 hash functions, utilizing the property of the avalanche effect.

function seedsToBytes(serverSeed, clientSeed, salt, cursor) {
    // SHA-256 calculation
    const hmacKey = createHash(serverSeed + ":" + salt);
    const hmacMessage = clientSeed + ":" + cursor;
    // HMAC calculation
    return createHmac(hmacKey, hmacMessage);
}

Bytes to numbers


The result of the generator is 64 random bytes (128-symbolic line), which are divided into 8 blocks of 8 byte each, and each block is used to obtain one number in the interval [0, 1) using the algorithm below.

function numbersFromBytes(bytes) {
    for (let t = 0; t < 8; t++) {
        let value = 0;
        let pw = 256;
        for (let i = t * 8; i < t * 8 + 8; i++) {
            value += bytes[i] / pw;
            pw *= 256;
        }
        result.push(value);
    }
    return result;
}

Outcome derival in Mines


To generate the result in the Mines mode, 24 random numbers in the interval [0..1) are required, therefore 3 arrays with 8 numbers each are generated, which are then combined into one array called index. This array is used to select bomb positions on the field using the Fisher-Yates shuffle

// numbers - index array
function minesShuffling(numbers, minesCount) {
    // Initial array
    let range = [];
    // Resulting array
    let permutation = [];
    for (var i = 0; i <= 24; i++) range.push(i);
    for (var i = 0; i < numbers.length; i++) {
        let index = Math.floor(numbers[i] * range.length);
        permutation.push(range.splice(index, 1)[0]);
    }
    return permutation;
}

Outcome derival in Tower


To generate the result in Tower mode, 40 random numbers in the interval [0..1) are required, therefore 5 arrays with 8 numbers each are generated, which are then combined into one array called index. Then this array is divided into 10 subarrays of 4 elements, and each subarray is used to generate rearrangements in the corresponding row of the tower using the Fisher-Yates shuffle

// numbers - index array
function minesShuffling(numbers, minesCount) {
    let field = [];
    for (var i = 0; i < 10; i++) {
        // Initial array
        let range = [];
        // Resulting array
        let permutation = [];
        for (var j = 0; j <= 4; j++) range.push(j);
        for (var j = 0; j < 4; j++) {
            permutation.push(range.splice(numbers[i * 4 + j], 1)[0]);
        }
        field.push(permutation);
    }
    return field;
}

Outcome derival in Slot


To generate one rotation in Slot mode, 5 random numbers are required in the interval [0..1), therefore, 1 array of 8 numbers is generated, of which the first 5 numbers are taken, which are converted into rotation of each drum by multiplication by its length according to the next algorithm

// numbers - index array
function slotSpin(numbers) {
    let spin_positions = [];
    for (var i = 0; i < 5; i++) {
        spin_positions.push(Math.floor(numbers[i] * (i == 4 ? 41 : 30)))
    }
    return spin_positions;
}

Array spin_positions contains the positions of symbols in the central row, the correspondence table of the numbers with the symbols is shown on the page "Check the game". The remaining characters on the drum are determined by the neighbors of the central characters in their columns. If the central symbol is the first (or last) in the table column, its upper (or lower) neighbor is the last (or first) symbol from this column.

Outcome derival in Plinko


To generate the winning bin number in Plinko mode, depending on the number of pins, from 8 to 16 random numbers in the interval [0..1) are required, so 2 arrays of 8 numbers are generated, which are then combined into one. The first n numbers, where n is the number of pins, are taken from this array. The resulting array is transformed as follows: if the array element is greater than 0.5, it is replaced with 1, otherwise it is replaced with 0. The winning bin number is equal to the sum of all elements of the transformed array.

// numbers - array of n elements in [0..1)
function plinkoBucket(numbers) {
    return numbers.map((number) => Math.floor(number * 2)).reduce((acc, item) => acc + item, 0);
}

The resulting value belongs to binomial distribution, which is a mathematical model of the Galton board.

Outcome derival in Dice


To generate the result in Dice mode, 1 random number in the interval [0..1) is required, which is then transformed to the outcome in the interval [0..100] according to the algorithm below.

// number has interval [0..1)
function diceOutcome(number) {
    return Math.floor(number * 10001) / 100;
}

Outcome derival in Double


To generate the result in Double mode requires 1 random number in the interval [0..1), which is then transformed to the wheel sector in the interval [0..14] according to the algorithm below.

// number has interval [0..1)
function doubleOutcome(number) {
    return Math.floor(number * 15);
}

Outcome derival in Jackpot


To generate the result in the Jackpot mode, 1 random number in the interval [0..1) is required, which is then transformed to a winning ticket by arithmetic multiplication by the total number of tickets rounded down, adjusted per unit (since the numbering of tickets begins with 1).

// number has interval [0..1)
function jackpotOutcome(number, ticketsCount) {
    return Math.floor(number * ticketsCount) + 1;
}

Outcome derival in Crash


To generate the result in Crash mode, 1 random number in the interval [0..1) is required, which is then transformed to the Crash multiplier, which has an exponential distribution, according to the algorithm below.

// number has interval [0..1)
function crashOutcome(number) {
    return max(1, 1000000 / (Math.floor(number * 1000000) + 1) * (1 - 0.05)).toFixed(2);
}
// number has interval [0..1)
function overgoOutcome(number) {
    return max(1, 1000000 / (Math.floor(number * 1000000) + 1) * (1 - 0.03)).toFixed(2);
}

Outcome derival in x50


To generate the result in X50 mode, 1 random number in the interval [0..1) is required, which is then converted to the wheel sector in the interval [0..53] according to the algorithm below.

// number has interval [0..1)
function doubleOutcome(number) {
    return Math.floor(number * 54);
}
Online chat
Users online:
Quiz
Reward:
gave the right answer:
0