hbengine 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (561) hide show
  1. package/README.md +20 -0
  2. package/engine-cli/connect.mjs +73 -0
  3. package/engine-cli/hbengine.mjs +565 -0
  4. package/engine-cli/package.json +1 -0
  5. package/engine-cli/templates.mjs +14 -0
  6. package/engine-conformance/analyse-worker.mjs +12 -0
  7. package/engine-conformance/analyse.mjs +4458 -0
  8. package/engine-conformance/bundle.mjs +208 -0
  9. package/engine-conformance/clock.mjs +294 -0
  10. package/engine-conformance/csp.go +56 -0
  11. package/engine-conformance/csp.json +6 -0
  12. package/engine-conformance/csp.mjs +20 -0
  13. package/engine-conformance/gzip-sizes.mjs +9 -0
  14. package/engine-conformance/package.json +1 -0
  15. package/engine-conformance/picture.mjs +55 -0
  16. package/engine-conformance/report.go +349 -0
  17. package/engine-conformance/run.mjs +1217 -0
  18. package/engine-conformance/scan.mjs +476 -0
  19. package/engine-conformance/testdata/clock-overlay/bundle/assets.json +1 -0
  20. package/engine-conformance/testdata/clock-overlay/bundle/game.css +17 -0
  21. package/engine-conformance/testdata/clock-overlay/bundle/game.js +83 -0
  22. package/engine-conformance/testdata/clock-overlay/bundle/hbtest.json +4 -0
  23. package/engine-conformance/testdata/clock-overlay/bundle/index.html +34 -0
  24. package/engine-conformance/testdata/clock-probe/bundle/assets.json +1 -0
  25. package/engine-conformance/testdata/clock-probe/bundle/game.css +17 -0
  26. package/engine-conformance/testdata/clock-probe/bundle/game.js +65 -0
  27. package/engine-conformance/testdata/clock-probe/bundle/hbtest.json +4 -0
  28. package/engine-conformance/testdata/clock-probe/bundle/index.html +35 -0
  29. package/engine-conformance/testdata/clock-probe/bundle/probe-worker.js +46 -0
  30. package/engine-conformance/testdata/clock-probe/bundle/probe.js +210 -0
  31. package/engine-conformance/testdata/clock-probe/math/dice.tsv +100 -0
  32. package/engine-conformance/testdata/clock-probe/math/manifest.json +2925 -0
  33. package/engine-conformance/testdata/clock-worker/bundle/assets.json +1 -0
  34. package/engine-conformance/testdata/clock-worker/bundle/clock-worker.js +14 -0
  35. package/engine-conformance/testdata/clock-worker/bundle/game.css +17 -0
  36. package/engine-conformance/testdata/clock-worker/bundle/game.js +61 -0
  37. package/engine-conformance/testdata/clock-worker/bundle/hbtest.json +4 -0
  38. package/engine-conformance/testdata/clock-worker/bundle/index.html +35 -0
  39. package/engine-conformance/testdata/clock-worker/math/dice.tsv +100 -0
  40. package/engine-conformance/testdata/clock-worker/math/manifest.json +2925 -0
  41. package/engine-conformance/travel.mjs +1209 -0
  42. package/engine-conformance/vendor/acorn/LICENSE +21 -0
  43. package/engine-conformance/vendor/acorn/acorn.mjs +6266 -0
  44. package/engine-conformance/wasm-releases.json +168 -0
  45. package/engine-examples/README.md +23 -0
  46. package/engine-examples/coin/AGENTS.md +3 -0
  47. package/engine-examples/coin/README.md +7 -0
  48. package/engine-examples/coin/bundle/assets.json +1 -0
  49. package/engine-examples/coin/bundle/game.css +5 -0
  50. package/engine-examples/coin/bundle/game.js +19 -0
  51. package/engine-examples/coin/bundle/hbtest.json +5 -0
  52. package/engine-examples/coin/bundle/index.html +16 -0
  53. package/engine-examples/coin/math/coin.tsv +2 -0
  54. package/engine-examples/coin/math/manifest.json +17 -0
  55. package/engine-examples/crash/AGENTS.md +3 -0
  56. package/engine-examples/crash/README.md +14 -0
  57. package/engine-examples/crash/bundle/assets.json +1 -0
  58. package/engine-examples/crash/bundle/game.css +8 -0
  59. package/engine-examples/crash/bundle/game.js +90 -0
  60. package/engine-examples/crash/bundle/hbtest.json +5 -0
  61. package/engine-examples/crash/bundle/index.html +20 -0
  62. package/engine-examples/crash/math/crash-01.tsv +2 -0
  63. package/engine-examples/crash/math/crash-02.tsv +2 -0
  64. package/engine-examples/crash/math/crash-03.tsv +2 -0
  65. package/engine-examples/crash/math/crash-04.tsv +2 -0
  66. package/engine-examples/crash/math/crash-05.tsv +2 -0
  67. package/engine-examples/crash/math/crash-06.tsv +2 -0
  68. package/engine-examples/crash/math/crash-07.tsv +2 -0
  69. package/engine-examples/crash/math/crash-08.tsv +2 -0
  70. package/engine-examples/crash/math/crash-09.tsv +2 -0
  71. package/engine-examples/crash/math/crash-10.tsv +2 -0
  72. package/engine-examples/crash/math/crash-11.tsv +2 -0
  73. package/engine-examples/crash/math/crash-12.tsv +2 -0
  74. package/engine-examples/crash/math/crash-13.tsv +2 -0
  75. package/engine-examples/crash/math/crash-14.tsv +2 -0
  76. package/engine-examples/crash/math/crash-15.tsv +2 -0
  77. package/engine-examples/crash/math/crash-16.tsv +2 -0
  78. package/engine-examples/crash/math/crash-17.tsv +2 -0
  79. package/engine-examples/crash/math/crash-18.tsv +2 -0
  80. package/engine-examples/crash/math/crash-19.tsv +2 -0
  81. package/engine-examples/crash/math/crash-20.tsv +2 -0
  82. package/engine-examples/crash/math/crash-21.tsv +2 -0
  83. package/engine-examples/crash/math/crash-22.tsv +2 -0
  84. package/engine-examples/crash/math/crash-23.tsv +2 -0
  85. package/engine-examples/crash/math/crash-24.tsv +2 -0
  86. package/engine-examples/crash/math/crash-25.tsv +2 -0
  87. package/engine-examples/crash/math/crash-26.tsv +2 -0
  88. package/engine-examples/crash/math/crash-27.tsv +2 -0
  89. package/engine-examples/crash/math/crash-28.tsv +2 -0
  90. package/engine-examples/crash/math/crash-29.tsv +2 -0
  91. package/engine-examples/crash/math/crash-30.tsv +2 -0
  92. package/engine-examples/crash/math/crash-31.tsv +2 -0
  93. package/engine-examples/crash/math/crash-32.tsv +2 -0
  94. package/engine-examples/crash/math/crash-33.tsv +2 -0
  95. package/engine-examples/crash/math/crash-34.tsv +2 -0
  96. package/engine-examples/crash/math/crash-35.tsv +2 -0
  97. package/engine-examples/crash/math/crash-36.tsv +2 -0
  98. package/engine-examples/crash/math/crash-37.tsv +2 -0
  99. package/engine-examples/crash/math/crash-38.tsv +2 -0
  100. package/engine-examples/crash/math/crash-39.tsv +2 -0
  101. package/engine-examples/crash/math/crash-40.tsv +2 -0
  102. package/engine-examples/crash/math/crash-41.tsv +2 -0
  103. package/engine-examples/crash/math/crash-42.tsv +2 -0
  104. package/engine-examples/crash/math/crash-43.tsv +2 -0
  105. package/engine-examples/crash/math/crash-44.tsv +2 -0
  106. package/engine-examples/crash/math/crash-45.tsv +2 -0
  107. package/engine-examples/crash/math/crash-46.tsv +2 -0
  108. package/engine-examples/crash/math/crash-47.tsv +2 -0
  109. package/engine-examples/crash/math/crash-48.tsv +2 -0
  110. package/engine-examples/crash/math/crash-49.tsv +2 -0
  111. package/engine-examples/crash/math/crash-50.tsv +2 -0
  112. package/engine-examples/crash/math/crash-51.tsv +2 -0
  113. package/engine-examples/crash/math/crash-52.tsv +2 -0
  114. package/engine-examples/crash/math/crash-53.tsv +2 -0
  115. package/engine-examples/crash/math/crash-54.tsv +2 -0
  116. package/engine-examples/crash/math/crash-55.tsv +2 -0
  117. package/engine-examples/crash/math/crash-56.tsv +2 -0
  118. package/engine-examples/crash/math/crash-57.tsv +2 -0
  119. package/engine-examples/crash/math/crash-58.tsv +2 -0
  120. package/engine-examples/crash/math/crash-59.tsv +2 -0
  121. package/engine-examples/crash/math/crash-60.tsv +2 -0
  122. package/engine-examples/crash/math/crash-61.tsv +2 -0
  123. package/engine-examples/crash/math/crash-62.tsv +2 -0
  124. package/engine-examples/crash/math/crash-63.tsv +2 -0
  125. package/engine-examples/crash/math/crash-64.tsv +2 -0
  126. package/engine-examples/crash/math/gen.mjs +31 -0
  127. package/engine-examples/crash/math/manifest.json +1 -0
  128. package/engine-examples/dice/AGENTS.md +3 -0
  129. package/engine-examples/dice/README.md +25 -0
  130. package/engine-examples/dice/bundle/assets.json +1 -0
  131. package/engine-examples/dice/bundle/game.css +17 -0
  132. package/engine-examples/dice/bundle/game.js +61 -0
  133. package/engine-examples/dice/bundle/hbtest.json +4 -0
  134. package/engine-examples/dice/bundle/index.html +34 -0
  135. package/engine-examples/dice/math/dice.tsv +100 -0
  136. package/engine-examples/dice/math/manifest.json +2925 -0
  137. package/engine-examples/keno/AGENTS.md +3 -0
  138. package/engine-examples/keno/README.md +11 -0
  139. package/engine-examples/keno/bundle/assets.json +1 -0
  140. package/engine-examples/keno/bundle/game.css +14 -0
  141. package/engine-examples/keno/bundle/game.js +86 -0
  142. package/engine-examples/keno/bundle/hbtest.json +4 -0
  143. package/engine-examples/keno/bundle/i18n.json +342 -0
  144. package/engine-examples/keno/bundle/index.html +20 -0
  145. package/engine-examples/keno/bundle/model.json +1 -0
  146. package/engine-examples/keno/math/gen.mjs +35 -0
  147. package/engine-examples/keno/math/keno-picks-1.tsv +2 -0
  148. package/engine-examples/keno/math/keno-picks-10.tsv +11 -0
  149. package/engine-examples/keno/math/keno-picks-2.tsv +3 -0
  150. package/engine-examples/keno/math/keno-picks-3.tsv +4 -0
  151. package/engine-examples/keno/math/keno-picks-4.tsv +5 -0
  152. package/engine-examples/keno/math/keno-picks-5.tsv +6 -0
  153. package/engine-examples/keno/math/keno-picks-6.tsv +7 -0
  154. package/engine-examples/keno/math/keno-picks-7.tsv +8 -0
  155. package/engine-examples/keno/math/keno-picks-8.tsv +9 -0
  156. package/engine-examples/keno/math/keno-picks-9.tsv +10 -0
  157. package/engine-examples/keno/math/manifest.json +1 -0
  158. package/engine-examples/keno/math-kit/pack.mjs +165 -0
  159. package/engine-examples/keno/math-kit/package.json +8 -0
  160. package/engine-examples/keno/math-kit/slot.mjs +94 -0
  161. package/engine-examples/keno/math-kit/tumble.mjs +94 -0
  162. package/engine-examples/lines/AGENTS.md +3 -0
  163. package/engine-examples/lines/README.md +20 -0
  164. package/engine-examples/lines/bundle/assets.json +1 -0
  165. package/engine-examples/lines/bundle/game.css +16 -0
  166. package/engine-examples/lines/bundle/game.js +125 -0
  167. package/engine-examples/lines/bundle/hbtest.json +4 -0
  168. package/engine-examples/lines/bundle/i18n.json +242 -0
  169. package/engine-examples/lines/bundle/index.html +23 -0
  170. package/engine-examples/lines/bundle/model.json +1 -0
  171. package/engine-examples/lines/math/gen.mjs +54 -0
  172. package/engine-examples/lines/math-kit/pack.mjs +165 -0
  173. package/engine-examples/lines/math-kit/package.json +8 -0
  174. package/engine-examples/lines/math-kit/slot.mjs +94 -0
  175. package/engine-examples/lines/math-kit/tumble.mjs +94 -0
  176. package/engine-examples/mines/AGENTS.md +3 -0
  177. package/engine-examples/mines/README.md +13 -0
  178. package/engine-examples/mines/bundle/assets.json +1 -0
  179. package/engine-examples/mines/bundle/game.css +12 -0
  180. package/engine-examples/mines/bundle/game.js +58 -0
  181. package/engine-examples/mines/bundle/hbtest.json +8 -0
  182. package/engine-examples/mines/bundle/index.html +16 -0
  183. package/engine-examples/mines/math/gen.mjs +40 -0
  184. package/engine-examples/mines/math/manifest.json +1 -0
  185. package/engine-examples/mines/math/mines-1-1.tsv +2 -0
  186. package/engine-examples/mines/math/mines-1-2.tsv +2 -0
  187. package/engine-examples/mines/math/mines-1-22.tsv +2 -0
  188. package/engine-examples/mines/math/mines-1-23.tsv +2 -0
  189. package/engine-examples/mines/math/mines-1-24.tsv +2 -0
  190. package/engine-examples/mines/math/mines-1-3.tsv +2 -0
  191. package/engine-examples/mines/math/mines-10-1.tsv +2 -0
  192. package/engine-examples/mines/math/mines-10-10.tsv +2 -0
  193. package/engine-examples/mines/math/mines-10-11.tsv +2 -0
  194. package/engine-examples/mines/math/mines-10-12.tsv +2 -0
  195. package/engine-examples/mines/math/mines-10-13.tsv +2 -0
  196. package/engine-examples/mines/math/mines-10-14.tsv +2 -0
  197. package/engine-examples/mines/math/mines-10-15.tsv +2 -0
  198. package/engine-examples/mines/math/mines-10-2.tsv +2 -0
  199. package/engine-examples/mines/math/mines-10-3.tsv +2 -0
  200. package/engine-examples/mines/math/mines-10-4.tsv +2 -0
  201. package/engine-examples/mines/math/mines-10-5.tsv +2 -0
  202. package/engine-examples/mines/math/mines-10-6.tsv +2 -0
  203. package/engine-examples/mines/math/mines-10-7.tsv +2 -0
  204. package/engine-examples/mines/math/mines-10-8.tsv +2 -0
  205. package/engine-examples/mines/math/mines-10-9.tsv +2 -0
  206. package/engine-examples/mines/math/mines-11-1.tsv +2 -0
  207. package/engine-examples/mines/math/mines-11-10.tsv +2 -0
  208. package/engine-examples/mines/math/mines-11-11.tsv +2 -0
  209. package/engine-examples/mines/math/mines-11-12.tsv +2 -0
  210. package/engine-examples/mines/math/mines-11-13.tsv +2 -0
  211. package/engine-examples/mines/math/mines-11-14.tsv +2 -0
  212. package/engine-examples/mines/math/mines-11-2.tsv +2 -0
  213. package/engine-examples/mines/math/mines-11-3.tsv +2 -0
  214. package/engine-examples/mines/math/mines-11-4.tsv +2 -0
  215. package/engine-examples/mines/math/mines-11-5.tsv +2 -0
  216. package/engine-examples/mines/math/mines-11-6.tsv +2 -0
  217. package/engine-examples/mines/math/mines-11-7.tsv +2 -0
  218. package/engine-examples/mines/math/mines-11-8.tsv +2 -0
  219. package/engine-examples/mines/math/mines-11-9.tsv +2 -0
  220. package/engine-examples/mines/math/mines-12-1.tsv +2 -0
  221. package/engine-examples/mines/math/mines-12-10.tsv +2 -0
  222. package/engine-examples/mines/math/mines-12-11.tsv +2 -0
  223. package/engine-examples/mines/math/mines-12-12.tsv +2 -0
  224. package/engine-examples/mines/math/mines-12-13.tsv +2 -0
  225. package/engine-examples/mines/math/mines-12-2.tsv +2 -0
  226. package/engine-examples/mines/math/mines-12-3.tsv +2 -0
  227. package/engine-examples/mines/math/mines-12-4.tsv +2 -0
  228. package/engine-examples/mines/math/mines-12-5.tsv +2 -0
  229. package/engine-examples/mines/math/mines-12-6.tsv +2 -0
  230. package/engine-examples/mines/math/mines-12-7.tsv +2 -0
  231. package/engine-examples/mines/math/mines-12-8.tsv +2 -0
  232. package/engine-examples/mines/math/mines-12-9.tsv +2 -0
  233. package/engine-examples/mines/math/mines-13-1.tsv +2 -0
  234. package/engine-examples/mines/math/mines-13-10.tsv +2 -0
  235. package/engine-examples/mines/math/mines-13-11.tsv +2 -0
  236. package/engine-examples/mines/math/mines-13-12.tsv +2 -0
  237. package/engine-examples/mines/math/mines-13-2.tsv +2 -0
  238. package/engine-examples/mines/math/mines-13-3.tsv +2 -0
  239. package/engine-examples/mines/math/mines-13-4.tsv +2 -0
  240. package/engine-examples/mines/math/mines-13-5.tsv +2 -0
  241. package/engine-examples/mines/math/mines-13-6.tsv +2 -0
  242. package/engine-examples/mines/math/mines-13-7.tsv +2 -0
  243. package/engine-examples/mines/math/mines-13-8.tsv +2 -0
  244. package/engine-examples/mines/math/mines-13-9.tsv +2 -0
  245. package/engine-examples/mines/math/mines-14-1.tsv +2 -0
  246. package/engine-examples/mines/math/mines-14-10.tsv +2 -0
  247. package/engine-examples/mines/math/mines-14-11.tsv +2 -0
  248. package/engine-examples/mines/math/mines-14-2.tsv +2 -0
  249. package/engine-examples/mines/math/mines-14-3.tsv +2 -0
  250. package/engine-examples/mines/math/mines-14-4.tsv +2 -0
  251. package/engine-examples/mines/math/mines-14-5.tsv +2 -0
  252. package/engine-examples/mines/math/mines-14-6.tsv +2 -0
  253. package/engine-examples/mines/math/mines-14-7.tsv +2 -0
  254. package/engine-examples/mines/math/mines-14-8.tsv +2 -0
  255. package/engine-examples/mines/math/mines-14-9.tsv +2 -0
  256. package/engine-examples/mines/math/mines-15-1.tsv +2 -0
  257. package/engine-examples/mines/math/mines-15-10.tsv +2 -0
  258. package/engine-examples/mines/math/mines-15-2.tsv +2 -0
  259. package/engine-examples/mines/math/mines-15-3.tsv +2 -0
  260. package/engine-examples/mines/math/mines-15-4.tsv +2 -0
  261. package/engine-examples/mines/math/mines-15-5.tsv +2 -0
  262. package/engine-examples/mines/math/mines-15-6.tsv +2 -0
  263. package/engine-examples/mines/math/mines-15-7.tsv +2 -0
  264. package/engine-examples/mines/math/mines-15-8.tsv +2 -0
  265. package/engine-examples/mines/math/mines-15-9.tsv +2 -0
  266. package/engine-examples/mines/math/mines-16-1.tsv +2 -0
  267. package/engine-examples/mines/math/mines-16-2.tsv +2 -0
  268. package/engine-examples/mines/math/mines-16-3.tsv +2 -0
  269. package/engine-examples/mines/math/mines-16-4.tsv +2 -0
  270. package/engine-examples/mines/math/mines-16-5.tsv +2 -0
  271. package/engine-examples/mines/math/mines-16-6.tsv +2 -0
  272. package/engine-examples/mines/math/mines-16-7.tsv +2 -0
  273. package/engine-examples/mines/math/mines-16-8.tsv +2 -0
  274. package/engine-examples/mines/math/mines-16-9.tsv +2 -0
  275. package/engine-examples/mines/math/mines-17-1.tsv +2 -0
  276. package/engine-examples/mines/math/mines-17-2.tsv +2 -0
  277. package/engine-examples/mines/math/mines-17-3.tsv +2 -0
  278. package/engine-examples/mines/math/mines-17-4.tsv +2 -0
  279. package/engine-examples/mines/math/mines-17-5.tsv +2 -0
  280. package/engine-examples/mines/math/mines-17-6.tsv +2 -0
  281. package/engine-examples/mines/math/mines-17-7.tsv +2 -0
  282. package/engine-examples/mines/math/mines-17-8.tsv +2 -0
  283. package/engine-examples/mines/math/mines-18-1.tsv +2 -0
  284. package/engine-examples/mines/math/mines-18-2.tsv +2 -0
  285. package/engine-examples/mines/math/mines-18-3.tsv +2 -0
  286. package/engine-examples/mines/math/mines-18-4.tsv +2 -0
  287. package/engine-examples/mines/math/mines-18-5.tsv +2 -0
  288. package/engine-examples/mines/math/mines-18-6.tsv +2 -0
  289. package/engine-examples/mines/math/mines-18-7.tsv +2 -0
  290. package/engine-examples/mines/math/mines-19-1.tsv +2 -0
  291. package/engine-examples/mines/math/mines-19-2.tsv +2 -0
  292. package/engine-examples/mines/math/mines-19-3.tsv +2 -0
  293. package/engine-examples/mines/math/mines-19-4.tsv +2 -0
  294. package/engine-examples/mines/math/mines-19-5.tsv +2 -0
  295. package/engine-examples/mines/math/mines-19-6.tsv +2 -0
  296. package/engine-examples/mines/math/mines-2-1.tsv +2 -0
  297. package/engine-examples/mines/math/mines-2-19.tsv +2 -0
  298. package/engine-examples/mines/math/mines-2-2.tsv +2 -0
  299. package/engine-examples/mines/math/mines-2-20.tsv +2 -0
  300. package/engine-examples/mines/math/mines-2-21.tsv +2 -0
  301. package/engine-examples/mines/math/mines-2-22.tsv +2 -0
  302. package/engine-examples/mines/math/mines-2-23.tsv +2 -0
  303. package/engine-examples/mines/math/mines-2-3.tsv +2 -0
  304. package/engine-examples/mines/math/mines-2-4.tsv +2 -0
  305. package/engine-examples/mines/math/mines-2-5.tsv +2 -0
  306. package/engine-examples/mines/math/mines-20-1.tsv +2 -0
  307. package/engine-examples/mines/math/mines-20-2.tsv +2 -0
  308. package/engine-examples/mines/math/mines-20-3.tsv +2 -0
  309. package/engine-examples/mines/math/mines-20-4.tsv +2 -0
  310. package/engine-examples/mines/math/mines-20-5.tsv +2 -0
  311. package/engine-examples/mines/math/mines-21-1.tsv +2 -0
  312. package/engine-examples/mines/math/mines-21-2.tsv +2 -0
  313. package/engine-examples/mines/math/mines-21-3.tsv +2 -0
  314. package/engine-examples/mines/math/mines-21-4.tsv +2 -0
  315. package/engine-examples/mines/math/mines-22-1.tsv +2 -0
  316. package/engine-examples/mines/math/mines-22-2.tsv +2 -0
  317. package/engine-examples/mines/math/mines-22-3.tsv +2 -0
  318. package/engine-examples/mines/math/mines-23-1.tsv +2 -0
  319. package/engine-examples/mines/math/mines-23-2.tsv +2 -0
  320. package/engine-examples/mines/math/mines-24-1.tsv +2 -0
  321. package/engine-examples/mines/math/mines-3-1.tsv +2 -0
  322. package/engine-examples/mines/math/mines-3-17.tsv +2 -0
  323. package/engine-examples/mines/math/mines-3-18.tsv +2 -0
  324. package/engine-examples/mines/math/mines-3-19.tsv +2 -0
  325. package/engine-examples/mines/math/mines-3-2.tsv +2 -0
  326. package/engine-examples/mines/math/mines-3-20.tsv +2 -0
  327. package/engine-examples/mines/math/mines-3-21.tsv +2 -0
  328. package/engine-examples/mines/math/mines-3-22.tsv +2 -0
  329. package/engine-examples/mines/math/mines-3-3.tsv +2 -0
  330. package/engine-examples/mines/math/mines-3-4.tsv +2 -0
  331. package/engine-examples/mines/math/mines-3-5.tsv +2 -0
  332. package/engine-examples/mines/math/mines-3-6.tsv +2 -0
  333. package/engine-examples/mines/math/mines-4-1.tsv +2 -0
  334. package/engine-examples/mines/math/mines-4-13.tsv +2 -0
  335. package/engine-examples/mines/math/mines-4-14.tsv +2 -0
  336. package/engine-examples/mines/math/mines-4-15.tsv +2 -0
  337. package/engine-examples/mines/math/mines-4-16.tsv +2 -0
  338. package/engine-examples/mines/math/mines-4-17.tsv +2 -0
  339. package/engine-examples/mines/math/mines-4-18.tsv +2 -0
  340. package/engine-examples/mines/math/mines-4-19.tsv +2 -0
  341. package/engine-examples/mines/math/mines-4-2.tsv +2 -0
  342. package/engine-examples/mines/math/mines-4-20.tsv +2 -0
  343. package/engine-examples/mines/math/mines-4-21.tsv +2 -0
  344. package/engine-examples/mines/math/mines-4-3.tsv +2 -0
  345. package/engine-examples/mines/math/mines-4-4.tsv +2 -0
  346. package/engine-examples/mines/math/mines-4-5.tsv +2 -0
  347. package/engine-examples/mines/math/mines-4-6.tsv +2 -0
  348. package/engine-examples/mines/math/mines-4-7.tsv +2 -0
  349. package/engine-examples/mines/math/mines-4-8.tsv +2 -0
  350. package/engine-examples/mines/math/mines-4-9.tsv +2 -0
  351. package/engine-examples/mines/math/mines-5-1.tsv +2 -0
  352. package/engine-examples/mines/math/mines-5-10.tsv +2 -0
  353. package/engine-examples/mines/math/mines-5-11.tsv +2 -0
  354. package/engine-examples/mines/math/mines-5-12.tsv +2 -0
  355. package/engine-examples/mines/math/mines-5-13.tsv +2 -0
  356. package/engine-examples/mines/math/mines-5-14.tsv +2 -0
  357. package/engine-examples/mines/math/mines-5-15.tsv +2 -0
  358. package/engine-examples/mines/math/mines-5-16.tsv +2 -0
  359. package/engine-examples/mines/math/mines-5-17.tsv +2 -0
  360. package/engine-examples/mines/math/mines-5-18.tsv +2 -0
  361. package/engine-examples/mines/math/mines-5-19.tsv +2 -0
  362. package/engine-examples/mines/math/mines-5-2.tsv +2 -0
  363. package/engine-examples/mines/math/mines-5-20.tsv +2 -0
  364. package/engine-examples/mines/math/mines-5-3.tsv +2 -0
  365. package/engine-examples/mines/math/mines-5-4.tsv +2 -0
  366. package/engine-examples/mines/math/mines-5-5.tsv +2 -0
  367. package/engine-examples/mines/math/mines-5-6.tsv +2 -0
  368. package/engine-examples/mines/math/mines-5-7.tsv +2 -0
  369. package/engine-examples/mines/math/mines-5-8.tsv +2 -0
  370. package/engine-examples/mines/math/mines-5-9.tsv +2 -0
  371. package/engine-examples/mines/math/mines-6-1.tsv +2 -0
  372. package/engine-examples/mines/math/mines-6-10.tsv +2 -0
  373. package/engine-examples/mines/math/mines-6-11.tsv +2 -0
  374. package/engine-examples/mines/math/mines-6-12.tsv +2 -0
  375. package/engine-examples/mines/math/mines-6-13.tsv +2 -0
  376. package/engine-examples/mines/math/mines-6-14.tsv +2 -0
  377. package/engine-examples/mines/math/mines-6-15.tsv +2 -0
  378. package/engine-examples/mines/math/mines-6-16.tsv +2 -0
  379. package/engine-examples/mines/math/mines-6-17.tsv +2 -0
  380. package/engine-examples/mines/math/mines-6-18.tsv +2 -0
  381. package/engine-examples/mines/math/mines-6-19.tsv +2 -0
  382. package/engine-examples/mines/math/mines-6-2.tsv +2 -0
  383. package/engine-examples/mines/math/mines-6-3.tsv +2 -0
  384. package/engine-examples/mines/math/mines-6-4.tsv +2 -0
  385. package/engine-examples/mines/math/mines-6-5.tsv +2 -0
  386. package/engine-examples/mines/math/mines-6-6.tsv +2 -0
  387. package/engine-examples/mines/math/mines-6-7.tsv +2 -0
  388. package/engine-examples/mines/math/mines-6-8.tsv +2 -0
  389. package/engine-examples/mines/math/mines-6-9.tsv +2 -0
  390. package/engine-examples/mines/math/mines-7-1.tsv +2 -0
  391. package/engine-examples/mines/math/mines-7-10.tsv +2 -0
  392. package/engine-examples/mines/math/mines-7-11.tsv +2 -0
  393. package/engine-examples/mines/math/mines-7-12.tsv +2 -0
  394. package/engine-examples/mines/math/mines-7-13.tsv +2 -0
  395. package/engine-examples/mines/math/mines-7-14.tsv +2 -0
  396. package/engine-examples/mines/math/mines-7-15.tsv +2 -0
  397. package/engine-examples/mines/math/mines-7-16.tsv +2 -0
  398. package/engine-examples/mines/math/mines-7-17.tsv +2 -0
  399. package/engine-examples/mines/math/mines-7-18.tsv +2 -0
  400. package/engine-examples/mines/math/mines-7-2.tsv +2 -0
  401. package/engine-examples/mines/math/mines-7-3.tsv +2 -0
  402. package/engine-examples/mines/math/mines-7-4.tsv +2 -0
  403. package/engine-examples/mines/math/mines-7-5.tsv +2 -0
  404. package/engine-examples/mines/math/mines-7-6.tsv +2 -0
  405. package/engine-examples/mines/math/mines-7-7.tsv +2 -0
  406. package/engine-examples/mines/math/mines-7-8.tsv +2 -0
  407. package/engine-examples/mines/math/mines-7-9.tsv +2 -0
  408. package/engine-examples/mines/math/mines-8-1.tsv +2 -0
  409. package/engine-examples/mines/math/mines-8-10.tsv +2 -0
  410. package/engine-examples/mines/math/mines-8-11.tsv +2 -0
  411. package/engine-examples/mines/math/mines-8-12.tsv +2 -0
  412. package/engine-examples/mines/math/mines-8-13.tsv +2 -0
  413. package/engine-examples/mines/math/mines-8-14.tsv +2 -0
  414. package/engine-examples/mines/math/mines-8-15.tsv +2 -0
  415. package/engine-examples/mines/math/mines-8-16.tsv +2 -0
  416. package/engine-examples/mines/math/mines-8-17.tsv +2 -0
  417. package/engine-examples/mines/math/mines-8-2.tsv +2 -0
  418. package/engine-examples/mines/math/mines-8-3.tsv +2 -0
  419. package/engine-examples/mines/math/mines-8-4.tsv +2 -0
  420. package/engine-examples/mines/math/mines-8-5.tsv +2 -0
  421. package/engine-examples/mines/math/mines-8-6.tsv +2 -0
  422. package/engine-examples/mines/math/mines-8-7.tsv +2 -0
  423. package/engine-examples/mines/math/mines-8-8.tsv +2 -0
  424. package/engine-examples/mines/math/mines-8-9.tsv +2 -0
  425. package/engine-examples/mines/math/mines-9-1.tsv +2 -0
  426. package/engine-examples/mines/math/mines-9-10.tsv +2 -0
  427. package/engine-examples/mines/math/mines-9-11.tsv +2 -0
  428. package/engine-examples/mines/math/mines-9-12.tsv +2 -0
  429. package/engine-examples/mines/math/mines-9-13.tsv +2 -0
  430. package/engine-examples/mines/math/mines-9-14.tsv +2 -0
  431. package/engine-examples/mines/math/mines-9-15.tsv +2 -0
  432. package/engine-examples/mines/math/mines-9-16.tsv +2 -0
  433. package/engine-examples/mines/math/mines-9-2.tsv +2 -0
  434. package/engine-examples/mines/math/mines-9-3.tsv +2 -0
  435. package/engine-examples/mines/math/mines-9-4.tsv +2 -0
  436. package/engine-examples/mines/math/mines-9-5.tsv +2 -0
  437. package/engine-examples/mines/math/mines-9-6.tsv +2 -0
  438. package/engine-examples/mines/math/mines-9-7.tsv +2 -0
  439. package/engine-examples/mines/math/mines-9-8.tsv +2 -0
  440. package/engine-examples/mines/math/mines-9-9.tsv +2 -0
  441. package/engine-examples/plinko/AGENTS.md +3 -0
  442. package/engine-examples/plinko/README.md +9 -0
  443. package/engine-examples/plinko/bundle/assets.json +1 -0
  444. package/engine-examples/plinko/bundle/game.css +5 -0
  445. package/engine-examples/plinko/bundle/game.js +92 -0
  446. package/engine-examples/plinko/bundle/hbtest.json +4 -0
  447. package/engine-examples/plinko/bundle/index.html +16 -0
  448. package/engine-examples/plinko/bundle/model.json +1 -0
  449. package/engine-examples/plinko/math/gen.mjs +40 -0
  450. package/engine-examples/plinko/math/manifest.json +1 -0
  451. package/engine-examples/plinko/math/plinko-12-high.tsv +13 -0
  452. package/engine-examples/plinko/math/plinko-12-low.tsv +13 -0
  453. package/engine-examples/plinko/math/plinko-12-medium.tsv +13 -0
  454. package/engine-examples/plinko/math/plinko-16-high.tsv +17 -0
  455. package/engine-examples/plinko/math/plinko-16-low.tsv +17 -0
  456. package/engine-examples/plinko/math/plinko-16-medium.tsv +17 -0
  457. package/engine-examples/plinko/math/plinko-8-high.tsv +9 -0
  458. package/engine-examples/plinko/math/plinko-8-low.tsv +9 -0
  459. package/engine-examples/plinko/math/plinko-8-medium.tsv +9 -0
  460. package/engine-examples/plinko/math-kit/pack.mjs +165 -0
  461. package/engine-examples/plinko/math-kit/package.json +8 -0
  462. package/engine-examples/plinko/math-kit/slot.mjs +94 -0
  463. package/engine-examples/plinko/math-kit/tumble.mjs +94 -0
  464. package/engine-examples/slot/AGENTS.md +3 -0
  465. package/engine-examples/slot/README.md +26 -0
  466. package/engine-examples/slot/bundle/assets.json +1 -0
  467. package/engine-examples/slot/bundle/game.css +19 -0
  468. package/engine-examples/slot/bundle/game.js +42 -0
  469. package/engine-examples/slot/bundle/hbtest.json +4 -0
  470. package/engine-examples/slot/bundle/index.html +23 -0
  471. package/engine-examples/slot/math/gen.mjs +79 -0
  472. package/engine-examples/slot/math/manifest.json +1 -0
  473. package/engine-examples/slot/math/slot.tsv +110592 -0
  474. package/engine-examples/tower/AGENTS.md +3 -0
  475. package/engine-examples/tower/README.md +21 -0
  476. package/engine-examples/tower/bundle/assets.json +1 -0
  477. package/engine-examples/tower/bundle/game.css +8 -0
  478. package/engine-examples/tower/bundle/game.js +37 -0
  479. package/engine-examples/tower/bundle/hbtest.json +5 -0
  480. package/engine-examples/tower/bundle/index.html +16 -0
  481. package/engine-examples/tower/math/floor.tsv +4 -0
  482. package/engine-examples/tower/math/manifest.json +61 -0
  483. package/engine-examples/tumble/AGENTS.md +3 -0
  484. package/engine-examples/tumble/README.md +18 -0
  485. package/engine-examples/tumble/bundle/assets.json +1 -0
  486. package/engine-examples/tumble/bundle/game.css +13 -0
  487. package/engine-examples/tumble/bundle/game.js +119 -0
  488. package/engine-examples/tumble/bundle/hbtest.json +4 -0
  489. package/engine-examples/tumble/bundle/i18n.json +122 -0
  490. package/engine-examples/tumble/bundle/index.html +20 -0
  491. package/engine-examples/tumble/bundle/model.json +1 -0
  492. package/engine-examples/tumble/math/gen.mjs +38 -0
  493. package/engine-examples/tumble/math-kit/pack.mjs +165 -0
  494. package/engine-examples/tumble/math-kit/package.json +8 -0
  495. package/engine-examples/tumble/math-kit/slot.mjs +94 -0
  496. package/engine-examples/tumble/math-kit/tumble.mjs +94 -0
  497. package/engine-examples/wheel/README.md +14 -0
  498. package/engine-examples/wheel/bundle/assets.json +1 -0
  499. package/engine-examples/wheel/bundle/game.css +7 -0
  500. package/engine-examples/wheel/bundle/game.js +51 -0
  501. package/engine-examples/wheel/bundle/hbtest.json +4 -0
  502. package/engine-examples/wheel/bundle/index.html +19 -0
  503. package/engine-examples/wheel/math/high.tsv +24 -0
  504. package/engine-examples/wheel/math/low.tsv +24 -0
  505. package/engine-examples/wheel/math/manifest.json +48 -0
  506. package/engine-examples/wheel/math/medium.tsv +24 -0
  507. package/engine-math/pack.mjs +165 -0
  508. package/engine-math/package.json +1 -0
  509. package/engine-math/slot.mjs +94 -0
  510. package/engine-math/tumble.mjs +94 -0
  511. package/engine-mcp/package.json +1 -0
  512. package/engine-mcp/server.mjs +151 -0
  513. package/engine-sdk/GUIDE.md +855 -0
  514. package/engine-sdk/assets.js +92 -0
  515. package/engine-sdk/autoplay.js +82 -0
  516. package/engine-sdk/bet-field.js +391 -0
  517. package/engine-sdk/kit/fiat-coins.js +51 -0
  518. package/engine-sdk/kit/numeric-input.js +116 -0
  519. package/engine-sdk/kit/wallet-format.js +423 -0
  520. package/engine-sdk/marks.js +22 -0
  521. package/engine-sdk/messages.js +289 -0
  522. package/engine-sdk/money.js +89 -0
  523. package/engine-sdk/package.json +1 -0
  524. package/engine-sdk/protocol.js +263 -0
  525. package/engine-sdk/sdk.d.ts +138 -0
  526. package/engine-sdk/sdk.js +330 -0
  527. package/engine-sdk/stake.js +68 -0
  528. package/engine-sdk/ui.d.ts +36 -0
  529. package/engine-sdk/ui.js +340 -0
  530. package/engine-shell/core/faults.js +127 -0
  531. package/engine-shell/core/rgs.js +193 -0
  532. package/engine-shell/core/router.js +917 -0
  533. package/engine-shell/host/boot.js +408 -0
  534. package/engine-shell/host/engine-v1.js +438 -0
  535. package/engine-shell/host/fair.js +285 -0
  536. package/engine-shell/host/fonts/SOURCE.json +11 -0
  537. package/engine-shell/host/fonts/figtree-400.woff2 +0 -0
  538. package/engine-shell/host/fonts/figtree-500.woff2 +0 -0
  539. package/engine-shell/host/fonts/figtree-600.woff2 +0 -0
  540. package/engine-shell/host/fonts/red-hat-display-700.woff2 +0 -0
  541. package/engine-shell/host/index.html +230 -0
  542. package/engine-shell/host/page.js +809 -0
  543. package/engine-shell/host/sandbox-panel.js +681 -0
  544. package/engine-shell/host/sandbox-scenarios.js +554 -0
  545. package/engine-shell/host/site-bridge.js +87 -0
  546. package/engine-shell/host/strings.js +916 -0
  547. package/engine-shell/package.json +1 -0
  548. package/engine-shell/verifiers/badcat/coin.tsv +2 -0
  549. package/engine-shell/verifiers/badcat/dice-2.tsv +11 -0
  550. package/engine-shell/verifiers/badcat/dice-5.tsv +26 -0
  551. package/engine-shell/verifiers/badcat/dice-9.tsv +46 -0
  552. package/engine-shell/verifiers/badcat/manifest.json +3344 -0
  553. package/engine-shell/verifiers/badcat/rps.tsv +3 -0
  554. package/engine-shell/verifiers/badcat/triple.tsv +66 -0
  555. package/engine-shell/verifiers/engine-verify.js +358 -0
  556. package/engine-shell/verifiers/package.json +5 -0
  557. package/engine-shell/verifiers/parity/manifest.json +27 -0
  558. package/engine-shell/verifiers/parity/wide.tsv +5 -0
  559. package/engine-shell/verifiers/parity-vectors.json +244 -0
  560. package/engine-shell/verifiers/vectors.json +100 -0
  561. package/package.json +10 -0
@@ -0,0 +1,3 @@
1
+ # For agents
2
+
3
+ This is a House Engine game (Housebets). Read the guide first: `engine_guide` (MCP) or `engine-sdk/GUIDE.md`. Then `hbengine verify`, `hbengine dev`, `hbengine upload` (or the `engine_*` tools). The math is `math/`, the frontend `bundle/`; never compute money or outcomes in the frontend.
@@ -0,0 +1,11 @@
1
+ # Keno — exact hypergeometric weights
2
+
3
+ 40 numbers, 10 drawn, 1 to 10 picks: ten modes (`picks-1` … `picks-10`),
4
+ one `draw` bet each. With n picks, k hits have weight
5
+ C(n, k) · C(40 − n, 10 − k), exact. From half the picks up each extra hit
6
+ pays four times the last, up to 1,000×; the first is solved for 99% and every
7
+ multiplier is rounded down to 0.01×, so the board shows exactly what pays
8
+ (98.6%–99.0%). The player's picks choose the mode; which numbers show as
9
+ drawn is cosmetic, always exactly the drawn number of hits.
10
+
11
+ node math/gen.mjs && npx hbengine verify .
@@ -0,0 +1 @@
1
+ {"groups": {"boot": {"files": ["index.html", "game.js", "game.css", "model.json", "i18n.json"]}}}
@@ -0,0 +1,14 @@
1
+ body { margin: 0; background: #08141a; }
2
+ .keno { container-type: inline-size; display: flex; flex-direction: column; align-items: center; gap: 12px; width: 100%; padding: 14px 12px; box-sizing: border-box; font-family: 'Figtree', system-ui, sans-serif; }
3
+ .board { --c: min(58px, (100cqi - 24px - 7 * 6px) / 8); display: grid; grid-template-columns: repeat(8, var(--c)); gap: 6px; }
4
+ .board button { height: var(--c); border: 0; border-radius: 8px; background: #0D2A38; color: #8F96A8; font: 700 calc(var(--c) * .32)/1 'Red Hat Display', system-ui, sans-serif; cursor: pointer; transition: background 120ms; }
5
+ .board button[aria-pressed="true"] { background: #1b4a5c; color: #F9F9FB; box-shadow: inset 0 0 0 2px #5cf6f6; }
6
+ .board button.drawn { background: #26323a; color: #F9F9FB; }
7
+ .board button.hit { background: #7d5410; color: #FDDC73; box-shadow: inset 0 0 0 2px #FDDC73; }
8
+ .board button:disabled { cursor: default; }
9
+ .row { display: flex; gap: 8px; }
10
+ .row button { height: 34px; padding: 0 14px; border: 0; border-radius: 8px; background: rgba(9, 102, 125, .15); color: #8F96A8; font: 600 13px/1 'Figtree', system-ui, sans-serif; cursor: pointer; }
11
+ .row button:hover { color: #F9F9FB; }
12
+ .pays { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; max-width: 100%; }
13
+ .pays span { padding: 4px 8px; border-radius: 6px; background: #0b1f28; color: #8F96A8; font: 600 12px/16px 'Red Hat Display', system-ui, sans-serif; font-variant-numeric: tabular-nums; }
14
+ .pays span.on { background: #7d5410; color: #FDDC73; }
@@ -0,0 +1,86 @@
1
+ // Keno: 40 numbers, 10 drawn. The panel is the engine's (engine-sdk/ui.js);
2
+ // the player's picks choose the mode (picks-1 … picks-10). The server draws
3
+ // how many hit; which numbers show as drawn is cosmetic (from the round's
4
+ // nonce), always exactly that many of the picks.
5
+ import { mount } from '/engine-sdk/ui.js';
6
+
7
+ const model = await (await fetch('./model.json')).json();
8
+ // The page's own words in the player's language (bundle/i18n.json, English otherwise).
9
+ const I18N = await (await fetch('./i18n.json')).json();
10
+ let W = I18N.en;
11
+ const t = (k, v = {}) => W[k].replace(/\{(\w+)\}/g, (_, x) => v[x]);
12
+ const boardEl = document.getElementById('board'), paysEl = document.getElementById('pays');
13
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
14
+ let picks = [3, 11, 19, 27, 35]; // five to start with: a bet works at once
15
+ let busy = false, game;
16
+
17
+ const cells = Array.from({ length: model.balls }, (_, i) => {
18
+ const b = document.createElement('button');
19
+ b.type = 'button';
20
+ b.textContent = String(i + 1);
21
+ b.onclick = () => {
22
+ if (busy) return;
23
+ picks = picks.includes(i) ? picks.filter((x) => x !== i) : picks.length < 10 ? [...picks, i] : picks;
24
+ sync();
25
+ };
26
+ boardEl.append(b);
27
+ return b;
28
+ });
29
+
30
+ function paint(drawn = [], hits = -1) {
31
+ cells.forEach((b, i) => {
32
+ b.setAttribute('aria-pressed', String(picks.includes(i)));
33
+ b.classList.toggle('drawn', drawn.includes(i) && !picks.includes(i));
34
+ b.classList.toggle('hit', drawn.includes(i) && picks.includes(i));
35
+ });
36
+ const pays = model.pays[picks.length] || [];
37
+ paysEl.replaceChildren(...pays.map((bp, k) => Object.assign(document.createElement('span'), { textContent: `${k}: ${bp / 10000}×`, className: k === hits ? 'on' : '' })).filter((_, k) => pays[k] > 0 || k === hits));
38
+ }
39
+
40
+ // The picks are the mode; at least one pick.
41
+ function sync() {
42
+ if (!picks.length) picks = [Math.floor(Math.random() * model.balls)];
43
+ if (game && game.mode !== `picks-${picks.length}`) game.mode = `picks-${picks.length}`;
44
+ paint();
45
+ }
46
+
47
+ // Which numbers show as drawn: k of the picks and the rest from the others, shuffled by the nonce.
48
+ function drawn(k, seed) {
49
+ let s = (seed >>> 0) || 1;
50
+ const rnd = (n) => { s ^= s << 13; s ^= s >>> 17; s ^= s << 5; return (s >>> 0) % n; };
51
+ const shuffle = (a) => { for (let i = a.length - 1; i > 0; i--) { const j = rnd(i + 1); [a[i], a[j]] = [a[j], a[i]]; } return a; };
52
+ const others = shuffle([...Array(model.balls).keys()].filter((i) => !picks.includes(i)));
53
+ return shuffle([...shuffle([...picks]).slice(0, k), ...others.slice(0, model.drawn - k)]);
54
+ }
55
+
56
+ document.getElementById('random').onclick = () => {
57
+ if (busy) return;
58
+ const n = picks.length || 5, all = [...Array(model.balls).keys()];
59
+ picks = all.sort(() => Math.random() - 0.5).slice(0, n); // visual choice of numbers only
60
+ sync();
61
+ };
62
+ document.getElementById('clear').onclick = () => { if (!busy) { picks = []; sync(); } };
63
+
64
+ game = await mount(document.getElementById('game'), {
65
+ labels: Object.fromEntries(Object.entries(I18N).map(([l, w]) => [l, w.modes])),
66
+ async reveal(round) {
67
+ busy = true;
68
+ const k = round.data[0].k, shown = [];
69
+ for (const i of drawn(k, Number(round.nonce) || 1)) { shown.push(i); paint(shown); await wait(70); }
70
+ paint(shown, k);
71
+ busy = false;
72
+ },
73
+ });
74
+ document.getElementById('game').addEventListener('select', (e) => {
75
+ // A mode picked in the panel: add or drop picks to match it.
76
+ const n = Number(e.detail.mode.split('-')[1]);
77
+ while (picks.length > n) picks.pop();
78
+ const free = [...Array(model.balls).keys()].filter((i) => !picks.includes(i));
79
+ while (picks.length < n) picks.push(free.splice(Math.floor(Math.random() * free.length), 1)[0]);
80
+ paint();
81
+ });
82
+ sync();
83
+ W = I18N[(game.engine.config.locale || 'en').slice(0, 2)] || I18N.en;
84
+ document.getElementById('random').textContent = t('random');
85
+ document.getElementById('clear').textContent = t('clear');
86
+ boardEl.setAttribute('aria-label', t('pick'));
@@ -0,0 +1,4 @@
1
+ {
2
+ "stake": { "page": "index.html", "selector": "hb-game hb-bet-amount input", "value": "1.00" },
3
+ "bet": { "page": "index.html", "selector": "hb-game [data-main]" }
4
+ }
@@ -0,0 +1,342 @@
1
+ {
2
+ "en": {
3
+ "random": "Random picks",
4
+ "clear": "Clear",
5
+ "pick": "Pick up to 10 numbers",
6
+ "modes": {
7
+ "picks-1": "Picks: 1",
8
+ "picks-2": "Picks: 2",
9
+ "picks-3": "Picks: 3",
10
+ "picks-4": "Picks: 4",
11
+ "picks-5": "Picks: 5",
12
+ "picks-6": "Picks: 6",
13
+ "picks-7": "Picks: 7",
14
+ "picks-8": "Picks: 8",
15
+ "picks-9": "Picks: 9",
16
+ "picks-10": "Picks: 10"
17
+ }
18
+ },
19
+ "ar": {
20
+ "random": "اختيار عشوائي",
21
+ "clear": "مسح",
22
+ "pick": "اختر حتى 10 أرقام",
23
+ "modes": {
24
+ "picks-1": "1 أرقام",
25
+ "picks-2": "2 أرقام",
26
+ "picks-3": "3 أرقام",
27
+ "picks-4": "4 أرقام",
28
+ "picks-5": "5 أرقام",
29
+ "picks-6": "6 أرقام",
30
+ "picks-7": "7 أرقام",
31
+ "picks-8": "8 أرقام",
32
+ "picks-9": "9 أرقام",
33
+ "picks-10": "10 أرقام"
34
+ }
35
+ },
36
+ "da": {
37
+ "random": "Tilfældige valg",
38
+ "clear": "Ryd",
39
+ "pick": "Vælg op til 10 tal",
40
+ "modes": {
41
+ "picks-1": "1 tal",
42
+ "picks-2": "2 tal",
43
+ "picks-3": "3 tal",
44
+ "picks-4": "4 tal",
45
+ "picks-5": "5 tal",
46
+ "picks-6": "6 tal",
47
+ "picks-7": "7 tal",
48
+ "picks-8": "8 tal",
49
+ "picks-9": "9 tal",
50
+ "picks-10": "10 tal"
51
+ }
52
+ },
53
+ "de": {
54
+ "random": "Zufallsauswahl",
55
+ "clear": "Leeren",
56
+ "pick": "Wähle bis zu 10 Zahlen",
57
+ "modes": {
58
+ "picks-1": "1 Zahlen",
59
+ "picks-2": "2 Zahlen",
60
+ "picks-3": "3 Zahlen",
61
+ "picks-4": "4 Zahlen",
62
+ "picks-5": "5 Zahlen",
63
+ "picks-6": "6 Zahlen",
64
+ "picks-7": "7 Zahlen",
65
+ "picks-8": "8 Zahlen",
66
+ "picks-9": "9 Zahlen",
67
+ "picks-10": "10 Zahlen"
68
+ }
69
+ },
70
+ "es": {
71
+ "random": "Selección al azar",
72
+ "clear": "Borrar",
73
+ "pick": "Elige hasta 10 números",
74
+ "modes": {
75
+ "picks-1": "1 números",
76
+ "picks-2": "2 números",
77
+ "picks-3": "3 números",
78
+ "picks-4": "4 números",
79
+ "picks-5": "5 números",
80
+ "picks-6": "6 números",
81
+ "picks-7": "7 números",
82
+ "picks-8": "8 números",
83
+ "picks-9": "9 números",
84
+ "picks-10": "10 números"
85
+ }
86
+ },
87
+ "fi": {
88
+ "random": "Satunnaiset valinnat",
89
+ "clear": "Tyhjennä",
90
+ "pick": "Valitse enintään 10 numeroa",
91
+ "modes": {
92
+ "picks-1": "1 numeroa",
93
+ "picks-2": "2 numeroa",
94
+ "picks-3": "3 numeroa",
95
+ "picks-4": "4 numeroa",
96
+ "picks-5": "5 numeroa",
97
+ "picks-6": "6 numeroa",
98
+ "picks-7": "7 numeroa",
99
+ "picks-8": "8 numeroa",
100
+ "picks-9": "9 numeroa",
101
+ "picks-10": "10 numeroa"
102
+ }
103
+ },
104
+ "fr": {
105
+ "random": "Choix au hasard",
106
+ "clear": "Effacer",
107
+ "pick": "Choisissez jusqu'à 10 numéros",
108
+ "modes": {
109
+ "picks-1": "1 numéros",
110
+ "picks-2": "2 numéros",
111
+ "picks-3": "3 numéros",
112
+ "picks-4": "4 numéros",
113
+ "picks-5": "5 numéros",
114
+ "picks-6": "6 numéros",
115
+ "picks-7": "7 numéros",
116
+ "picks-8": "8 numéros",
117
+ "picks-9": "9 numéros",
118
+ "picks-10": "10 numéros"
119
+ }
120
+ },
121
+ "hi": {
122
+ "random": "रैंडम चुनाव",
123
+ "clear": "साफ़ करें",
124
+ "pick": "10 तक नंबर चुनें",
125
+ "modes": {
126
+ "picks-1": "1 नंबर",
127
+ "picks-2": "2 नंबर",
128
+ "picks-3": "3 नंबर",
129
+ "picks-4": "4 नंबर",
130
+ "picks-5": "5 नंबर",
131
+ "picks-6": "6 नंबर",
132
+ "picks-7": "7 नंबर",
133
+ "picks-8": "8 नंबर",
134
+ "picks-9": "9 नंबर",
135
+ "picks-10": "10 नंबर"
136
+ }
137
+ },
138
+ "hu": {
139
+ "random": "Véletlen választás",
140
+ "clear": "Törlés",
141
+ "pick": "Válassz legfeljebb 10 számot",
142
+ "modes": {
143
+ "picks-1": "1 szám",
144
+ "picks-2": "2 szám",
145
+ "picks-3": "3 szám",
146
+ "picks-4": "4 szám",
147
+ "picks-5": "5 szám",
148
+ "picks-6": "6 szám",
149
+ "picks-7": "7 szám",
150
+ "picks-8": "8 szám",
151
+ "picks-9": "9 szám",
152
+ "picks-10": "10 szám"
153
+ }
154
+ },
155
+ "id": {
156
+ "random": "Pilih acak",
157
+ "clear": "Hapus",
158
+ "pick": "Pilih hingga 10 angka",
159
+ "modes": {
160
+ "picks-1": "1 angka",
161
+ "picks-2": "2 angka",
162
+ "picks-3": "3 angka",
163
+ "picks-4": "4 angka",
164
+ "picks-5": "5 angka",
165
+ "picks-6": "6 angka",
166
+ "picks-7": "7 angka",
167
+ "picks-8": "8 angka",
168
+ "picks-9": "9 angka",
169
+ "picks-10": "10 angka"
170
+ }
171
+ },
172
+ "it": {
173
+ "random": "Scelta casuale",
174
+ "clear": "Cancella",
175
+ "pick": "Scegli fino a 10 numeri",
176
+ "modes": {
177
+ "picks-1": "1 numeri",
178
+ "picks-2": "2 numeri",
179
+ "picks-3": "3 numeri",
180
+ "picks-4": "4 numeri",
181
+ "picks-5": "5 numeri",
182
+ "picks-6": "6 numeri",
183
+ "picks-7": "7 numeri",
184
+ "picks-8": "8 numeri",
185
+ "picks-9": "9 numeri",
186
+ "picks-10": "10 numeri"
187
+ }
188
+ },
189
+ "ja": {
190
+ "random": "ランダム選択",
191
+ "clear": "クリア",
192
+ "pick": "数字を最大10個選択",
193
+ "modes": {
194
+ "picks-1": "1個",
195
+ "picks-2": "2個",
196
+ "picks-3": "3個",
197
+ "picks-4": "4個",
198
+ "picks-5": "5個",
199
+ "picks-6": "6個",
200
+ "picks-7": "7個",
201
+ "picks-8": "8個",
202
+ "picks-9": "9個",
203
+ "picks-10": "10個"
204
+ }
205
+ },
206
+ "ko": {
207
+ "random": "무작위 선택",
208
+ "clear": "지우기",
209
+ "pick": "숫자를 최대 10개 선택",
210
+ "modes": {
211
+ "picks-1": "1개",
212
+ "picks-2": "2개",
213
+ "picks-3": "3개",
214
+ "picks-4": "4개",
215
+ "picks-5": "5개",
216
+ "picks-6": "6개",
217
+ "picks-7": "7개",
218
+ "picks-8": "8개",
219
+ "picks-9": "9개",
220
+ "picks-10": "10개"
221
+ }
222
+ },
223
+ "pl": {
224
+ "random": "Losowy wybór",
225
+ "clear": "Wyczyść",
226
+ "pick": "Wybierz do 10 liczb",
227
+ "modes": {
228
+ "picks-1": "Liczby: 1",
229
+ "picks-2": "Liczby: 2",
230
+ "picks-3": "Liczby: 3",
231
+ "picks-4": "Liczby: 4",
232
+ "picks-5": "Liczby: 5",
233
+ "picks-6": "Liczby: 6",
234
+ "picks-7": "Liczby: 7",
235
+ "picks-8": "Liczby: 8",
236
+ "picks-9": "Liczby: 9",
237
+ "picks-10": "Liczby: 10"
238
+ }
239
+ },
240
+ "pt": {
241
+ "random": "Escolha aleatória",
242
+ "clear": "Limpar",
243
+ "pick": "Escolha até 10 números",
244
+ "modes": {
245
+ "picks-1": "1 números",
246
+ "picks-2": "2 números",
247
+ "picks-3": "3 números",
248
+ "picks-4": "4 números",
249
+ "picks-5": "5 números",
250
+ "picks-6": "6 números",
251
+ "picks-7": "7 números",
252
+ "picks-8": "8 números",
253
+ "picks-9": "9 números",
254
+ "picks-10": "10 números"
255
+ }
256
+ },
257
+ "ru": {
258
+ "random": "Случайный выбор",
259
+ "clear": "Очистить",
260
+ "pick": "Выберите до 10 чисел",
261
+ "modes": {
262
+ "picks-1": "Чисел: 1",
263
+ "picks-2": "Чисел: 2",
264
+ "picks-3": "Чисел: 3",
265
+ "picks-4": "Чисел: 4",
266
+ "picks-5": "Чисел: 5",
267
+ "picks-6": "Чисел: 6",
268
+ "picks-7": "Чисел: 7",
269
+ "picks-8": "Чисел: 8",
270
+ "picks-9": "Чисел: 9",
271
+ "picks-10": "Чисел: 10"
272
+ }
273
+ },
274
+ "th": {
275
+ "random": "สุ่มเลือก",
276
+ "clear": "ล้าง",
277
+ "pick": "เลือกได้สูงสุด 10 ตัวเลข",
278
+ "modes": {
279
+ "picks-1": "1 ตัวเลข",
280
+ "picks-2": "2 ตัวเลข",
281
+ "picks-3": "3 ตัวเลข",
282
+ "picks-4": "4 ตัวเลข",
283
+ "picks-5": "5 ตัวเลข",
284
+ "picks-6": "6 ตัวเลข",
285
+ "picks-7": "7 ตัวเลข",
286
+ "picks-8": "8 ตัวเลข",
287
+ "picks-9": "9 ตัวเลข",
288
+ "picks-10": "10 ตัวเลข"
289
+ }
290
+ },
291
+ "tr": {
292
+ "random": "Rastgele seçim",
293
+ "clear": "Temizle",
294
+ "pick": "En fazla 10 sayı seç",
295
+ "modes": {
296
+ "picks-1": "1 sayı",
297
+ "picks-2": "2 sayı",
298
+ "picks-3": "3 sayı",
299
+ "picks-4": "4 sayı",
300
+ "picks-5": "5 sayı",
301
+ "picks-6": "6 sayı",
302
+ "picks-7": "7 sayı",
303
+ "picks-8": "8 sayı",
304
+ "picks-9": "9 sayı",
305
+ "picks-10": "10 sayı"
306
+ }
307
+ },
308
+ "vi": {
309
+ "random": "Chọn ngẫu nhiên",
310
+ "clear": "Xóa",
311
+ "pick": "Chọn tối đa 10 số",
312
+ "modes": {
313
+ "picks-1": "1 số",
314
+ "picks-2": "2 số",
315
+ "picks-3": "3 số",
316
+ "picks-4": "4 số",
317
+ "picks-5": "5 số",
318
+ "picks-6": "6 số",
319
+ "picks-7": "7 số",
320
+ "picks-8": "8 số",
321
+ "picks-9": "9 số",
322
+ "picks-10": "10 số"
323
+ }
324
+ },
325
+ "zh": {
326
+ "random": "随机选择",
327
+ "clear": "清除",
328
+ "pick": "最多选择 10 个号码",
329
+ "modes": {
330
+ "picks-1": "1 个号码",
331
+ "picks-2": "2 个号码",
332
+ "picks-3": "3 个号码",
333
+ "picks-4": "4 个号码",
334
+ "picks-5": "5 个号码",
335
+ "picks-6": "6 个号码",
336
+ "picks-7": "7 个号码",
337
+ "picks-8": "8 个号码",
338
+ "picks-9": "9 个号码",
339
+ "picks-10": "10 个号码"
340
+ }
341
+ }
342
+ }
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
6
+ <title>Keno</title>
7
+ <link rel="stylesheet" href="./game.css">
8
+ <script type="module" src="/engine-sdk/bet-field.js"></script>
9
+ <script type="module" src="./game.js"></script>
10
+ </head>
11
+ <body>
12
+ <hb-game id="game">
13
+ <div slot="zone" class="keno">
14
+ <div class="board" id="board" role="group" aria-label="Pick up to 10 numbers"></div>
15
+ <div class="row"><button type="button" id="random">Random picks</button><button type="button" id="clear">Clear</button></div>
16
+ <div class="pays" id="pays" aria-live="polite"></div>
17
+ </div>
18
+ </hb-game>
19
+ </body>
20
+ </html>
@@ -0,0 +1 @@
1
+ {"balls":40,"drawn":10,"pays":{"1":[0,39500],"2":[0,16000,64300],"3":[0,0,53400,213700],"4":[0,0,24200,96900,387700],"5":[0,0,0,79900,319900,1279900],"6":[0,0,0,38500,154000,616000,2464000],"7":[0,0,0,0,131800,527500,2110000,8440100],"8":[0,0,0,0,65900,263700,1055000,4220100,10000000],"9":[0,0,0,0,0,241500,966100,3864400,10000000,10000000],"10":[0,0,0,0,0,123400,493600,1974400,7897700,10000000,10000000]}}
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ // Keno's maths: 40 numbers, 10 drawn, the player picks 1 to 10. With n
3
+ // picks, k hits have weight C(n, k) · C(40 − n, 10 − k) — exact, no
4
+ // simulation. From half the picks up, each extra hit pays GROWTH times the
5
+ // one before, up to CAP; the first multiplier is solved for 99% and every
6
+ // multiplier rounded down to 0.01× so the board shows exactly what pays.
7
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { dirname, join } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { binomial, writePack } from '../math-kit/pack.mjs';
11
+
12
+ const DIR = dirname(fileURLToPath(import.meta.url));
13
+ const project = join(DIR, '..', 'hbengine.json');
14
+ const GAME = process.argv[2] || (existsSync(project) ? JSON.parse(readFileSync(project, 'utf8')).slug : 'keno');
15
+ const BALLS = 40, DRAWN = 10, RTP = 9900, GROWTH = 4, CAP = 1000;
16
+
17
+ const modes = [], board = {};
18
+ for (let n = 1; n <= 10; n++) {
19
+ const weight = (k) => binomial(n, k) * binomial(BALLS - n, DRAWN - k);
20
+ const total = binomial(BALLS, DRAWN);
21
+ // Hits that pay: from half the picks up (rounded up), at least one.
22
+ const paying = [];
23
+ for (let k = Math.max(1, Math.ceil(n / 2)); k <= n; k++) paying.push(k);
24
+ const p = (k) => Number(weight(k)) / Number(total);
25
+ const shape = (c) => paying.map((k, i) => Math.min(CAP, c * GROWTH ** i));
26
+ let lo = 0, hi = CAP;
27
+ for (let i = 0; i < 200; i++) { const c = (lo + hi) / 2; (shape(c).reduce((s, m, j) => s + m * p(paying[j]), 0) < RTP / 10000 ? (lo = c) : (hi = c)); }
28
+ const pays = Array(n + 1).fill(0);
29
+ shape(lo).forEach((m, j) => { pays[paying[j]] = Math.floor(m * 100) * 100; }); // bp, down to 0.01×
30
+ board[n] = pays;
31
+ modes.push({ id: `picks-${n}`, label: `${n} pick${n > 1 ? 's' : ''}`, bets: [{ id: 'draw', label: 'Draw' }],
32
+ rows: pays.map((m, k) => ({ weight: weight(k), data: { k }, pay: { draw: m } })) });
33
+ }
34
+ writePack(DIR, { game: GAME, rtpBp: RTP, modes });
35
+ writeFileSync(join(DIR, '..', 'bundle', 'model.json'), JSON.stringify({ balls: BALLS, drawn: DRAWN, pays: board }) + '\n');
@@ -0,0 +1,2 @@
1
+ 635745396 {"k":0}
2
+ 211915132 {"k":1}
@@ -0,0 +1,11 @@
1
+ 30045015 {"k":0}
2
+ 143071500 {"k":1}
3
+ 263381625 {"k":2}
4
+ 244296000 {"k":3}
5
+ 124692750 {"k":4}
6
+ 35911512 {"k":5}
7
+ 5755050 {"k":6}
8
+ 487200 {"k":7}
9
+ 19575 {"k":8}
10
+ 300 {"k":9}
11
+ 1 {"k":10}
@@ -0,0 +1,3 @@
1
+ 472733756 {"k":0}
2
+ 326023280 {"k":1}
3
+ 48903492 {"k":2}
@@ -0,0 +1,4 @@
1
+ 348330136 {"k":0}
2
+ 373210860 {"k":1}
3
+ 115824060 {"k":2}
4
+ 10295472 {"k":3}
@@ -0,0 +1,5 @@
1
+ 254186856 {"k":0}
2
+ 376573120 {"k":1}
3
+ 181562040 {"k":2}
4
+ 33390720 {"k":3}
5
+ 1947792 {"k":4}
@@ -0,0 +1,6 @@
1
+ 183579396 {"k":0}
2
+ 353037300 {"k":1}
3
+ 235358200 {"k":2}
4
+ 67245200 {"k":3}
5
+ 8115800 {"k":4}
6
+ 324632 {"k":5}
@@ -0,0 +1,7 @@
1
+ 131128140 {"k":0}
2
+ 314707536 {"k":1}
3
+ 272343060 {"k":2}
4
+ 107592320 {"k":3}
5
+ 20173560 {"k":4}
6
+ 1669536 {"k":5}
7
+ 46376 {"k":6}
@@ -0,0 +1,8 @@
1
+ 92561040 {"k":0}
2
+ 269969700 {"k":1}
3
+ 291567276 {"k":2}
4
+ 149521680 {"k":3}
5
+ 38764880 {"k":4}
6
+ 4984056 {"k":5}
7
+ 286440 {"k":6}
8
+ 5456 {"k":7}
@@ -0,0 +1,9 @@
1
+ 64512240 {"k":0}
2
+ 224390400 {"k":1}
3
+ 294512400 {"k":2}
4
+ 188487936 {"k":3}
5
+ 63433440 {"k":4}
6
+ 11277056 {"k":5}
7
+ 1006880 {"k":6}
8
+ 39680 {"k":7}
9
+ 496 {"k":8}
@@ -0,0 +1,10 @@
1
+ 44352165 {"k":0}
2
+ 181440675 {"k":1}
3
+ 283994100 {"k":2}
4
+ 220884300 {"k":3}
5
+ 92771406 {"k":4}
6
+ 21408786 {"k":5}
7
+ 2643060 {"k":6}
8
+ 161820 {"k":7}
9
+ 4185 {"k":8}
10
+ 31 {"k":9}
@@ -0,0 +1 @@
1
+ {"format":"house-engine-math/1","game":"keno","rtpBp":9900,"modes":[{"id":"picks-1","label":"1 pick","kind":"table","table":"keno-picks-1.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[1,1]],"multBp":39500}]}]},{"id":"picks-2","label":"2 picks","kind":"table","table":"keno-picks-2.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[1,1]],"multBp":16000},{"outcomes":[[2,2]],"multBp":64300}]}]},{"id":"picks-3","label":"3 picks","kind":"table","table":"keno-picks-3.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[2,2]],"multBp":53400},{"outcomes":[[3,3]],"multBp":213700}]}]},{"id":"picks-4","label":"4 picks","kind":"table","table":"keno-picks-4.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[2,2]],"multBp":24200},{"outcomes":[[3,3]],"multBp":96900},{"outcomes":[[4,4]],"multBp":387700}]}]},{"id":"picks-5","label":"5 picks","kind":"table","table":"keno-picks-5.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[3,3]],"multBp":79900},{"outcomes":[[4,4]],"multBp":319900},{"outcomes":[[5,5]],"multBp":1279900}]}]},{"id":"picks-6","label":"6 picks","kind":"table","table":"keno-picks-6.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[3,3]],"multBp":38500},{"outcomes":[[4,4]],"multBp":154000},{"outcomes":[[5,5]],"multBp":616000},{"outcomes":[[6,6]],"multBp":2464000}]}]},{"id":"picks-7","label":"7 picks","kind":"table","table":"keno-picks-7.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[4,4]],"multBp":131800},{"outcomes":[[5,5]],"multBp":527500},{"outcomes":[[6,6]],"multBp":2110000},{"outcomes":[[7,7]],"multBp":8440100}]}]},{"id":"picks-8","label":"8 picks","kind":"table","table":"keno-picks-8.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[4,4]],"multBp":65900},{"outcomes":[[5,5]],"multBp":263700},{"outcomes":[[6,6]],"multBp":1055000},{"outcomes":[[7,7]],"multBp":4220100},{"outcomes":[[8,8]],"multBp":10000000}]}]},{"id":"picks-9","label":"9 picks","kind":"table","table":"keno-picks-9.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[5,5]],"multBp":241500},{"outcomes":[[6,6]],"multBp":966100},{"outcomes":[[7,7]],"multBp":3864400},{"outcomes":[[8,9]],"multBp":10000000}]}]},{"id":"picks-10","label":"10 picks","kind":"table","table":"keno-picks-10.tsv","bets":[{"id":"draw","label":"Draw","tiers":[{"outcomes":[[5,5]],"multBp":123400},{"outcomes":[[6,6]],"multBp":493600},{"outcomes":[[7,7]],"multBp":1974400},{"outcomes":[[8,8]],"multBp":7897700},{"outcomes":[[9,10]],"multBp":10000000}]}]}]}