redscript-mc 1.2.25 → 1.2.27

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 (265) hide show
  1. package/README.md +67 -9
  2. package/README.zh.md +61 -4
  3. package/dist/__tests__/cli.test.js +1 -1
  4. package/dist/__tests__/codegen.test.js +12 -6
  5. package/dist/__tests__/e2e.test.js +6 -6
  6. package/dist/__tests__/lowering.test.js +8 -8
  7. package/dist/__tests__/optimizer.test.js +31 -0
  8. package/dist/__tests__/stdlib-advanced.test.d.ts +4 -0
  9. package/dist/__tests__/stdlib-advanced.test.js +378 -0
  10. package/dist/__tests__/stdlib-bigint.test.d.ts +7 -0
  11. package/dist/__tests__/stdlib-bigint.test.js +428 -0
  12. package/dist/__tests__/stdlib-math.test.d.ts +7 -0
  13. package/dist/__tests__/stdlib-math.test.js +352 -0
  14. package/dist/__tests__/stdlib-vec.test.d.ts +4 -0
  15. package/dist/__tests__/stdlib-vec.test.js +264 -0
  16. package/dist/ast/types.d.ts +17 -1
  17. package/dist/codegen/mcfunction/index.js +154 -18
  18. package/dist/codegen/var-allocator.d.ts +17 -0
  19. package/dist/codegen/var-allocator.js +26 -0
  20. package/dist/compile.d.ts +14 -0
  21. package/dist/compile.js +62 -5
  22. package/dist/data/arena/function/__load.mcfunction +6 -0
  23. package/dist/data/arena/function/__tick.mcfunction +2 -0
  24. package/dist/data/arena/function/announce_leaders/else_1.mcfunction +3 -0
  25. package/dist/data/arena/function/announce_leaders/foreach_0/merge_2.mcfunction +1 -0
  26. package/dist/data/arena/function/announce_leaders/foreach_0/then_0.mcfunction +3 -0
  27. package/dist/data/arena/function/announce_leaders/foreach_0.mcfunction +7 -0
  28. package/dist/data/arena/function/announce_leaders/foreach_1/merge_2.mcfunction +1 -0
  29. package/dist/data/arena/function/announce_leaders/foreach_1/then_0.mcfunction +4 -0
  30. package/dist/data/arena/function/announce_leaders/foreach_1.mcfunction +6 -0
  31. package/dist/data/arena/function/announce_leaders/merge_2.mcfunction +1 -0
  32. package/dist/data/arena/function/announce_leaders/then_0.mcfunction +4 -0
  33. package/dist/data/arena/function/announce_leaders.mcfunction +6 -0
  34. package/dist/data/arena/function/arena_tick/merge_2.mcfunction +1 -0
  35. package/dist/data/arena/function/arena_tick/then_0.mcfunction +4 -0
  36. package/dist/data/arena/function/arena_tick.mcfunction +11 -0
  37. package/dist/data/counter/function/__load.mcfunction +5 -0
  38. package/dist/data/counter/function/__tick.mcfunction +2 -0
  39. package/dist/data/counter/function/counter_tick/merge_2.mcfunction +1 -0
  40. package/dist/data/counter/function/counter_tick/then_0.mcfunction +3 -0
  41. package/dist/data/counter/function/counter_tick.mcfunction +11 -0
  42. package/dist/data/gcd2/function/__load.mcfunction +3 -0
  43. package/dist/data/gcd2/function/abs/merge_2.mcfunction +3 -0
  44. package/dist/data/gcd2/function/abs/then_0.mcfunction +5 -0
  45. package/dist/data/gcd2/function/abs.mcfunction +7 -0
  46. package/dist/data/gcd2/function/gcd/loop_body_1.mcfunction +7 -0
  47. package/dist/data/gcd2/function/gcd/loop_check_0.mcfunction +5 -0
  48. package/dist/data/gcd2/function/gcd/loop_exit_2.mcfunction +3 -0
  49. package/dist/data/gcd2/function/gcd.mcfunction +14 -0
  50. package/dist/data/gcd3/function/__load.mcfunction +3 -0
  51. package/dist/data/gcd3/function/abs/merge_2.mcfunction +3 -0
  52. package/dist/data/gcd3/function/abs/then_0.mcfunction +5 -0
  53. package/dist/data/gcd3/function/abs.mcfunction +7 -0
  54. package/dist/data/gcd3/function/gcd/loop_body_1.mcfunction +7 -0
  55. package/dist/data/gcd3/function/gcd/loop_check_0.mcfunction +5 -0
  56. package/dist/data/gcd3/function/gcd/loop_exit_2.mcfunction +3 -0
  57. package/dist/data/gcd3/function/gcd.mcfunction +14 -0
  58. package/dist/data/gcd3/function/test.mcfunction +7 -0
  59. package/dist/data/gcd3nm/function/__load.mcfunction +3 -0
  60. package/dist/data/gcd3nm/function/abs/merge_2.mcfunction +3 -0
  61. package/dist/data/gcd3nm/function/abs/then_0.mcfunction +5 -0
  62. package/dist/data/gcd3nm/function/abs.mcfunction +7 -0
  63. package/dist/data/gcd3nm/function/gcd/loop_body_1.mcfunction +7 -0
  64. package/dist/data/gcd3nm/function/gcd/loop_check_0.mcfunction +5 -0
  65. package/dist/data/gcd3nm/function/gcd/loop_exit_2.mcfunction +3 -0
  66. package/dist/data/gcd3nm/function/gcd.mcfunction +14 -0
  67. package/dist/data/gcd3nm/function/test.mcfunction +7 -0
  68. package/dist/data/gcd_test/function/__load.mcfunction +3 -0
  69. package/dist/data/gcd_test/function/abs/merge_2.mcfunction +3 -0
  70. package/dist/data/gcd_test/function/abs/then_0.mcfunction +5 -0
  71. package/dist/data/gcd_test/function/abs.mcfunction +7 -0
  72. package/dist/data/gcd_test/function/gcd/loop_body_1.mcfunction +7 -0
  73. package/dist/data/gcd_test/function/gcd/loop_check_0.mcfunction +5 -0
  74. package/dist/data/gcd_test/function/gcd/loop_exit_2.mcfunction +3 -0
  75. package/dist/data/gcd_test/function/gcd.mcfunction +14 -0
  76. package/dist/data/isqrttest/function/__load.mcfunction +6 -0
  77. package/dist/data/isqrttest/function/isqrt/loop_body_4.mcfunction +12 -0
  78. package/dist/data/isqrttest/function/isqrt/loop_check_3.mcfunction +5 -0
  79. package/dist/data/isqrttest/function/isqrt/loop_exit_5.mcfunction +3 -0
  80. package/dist/data/isqrttest/function/isqrt/merge_2.mcfunction +4 -0
  81. package/dist/data/isqrttest/function/isqrt/merge_8.mcfunction +6 -0
  82. package/dist/data/isqrttest/function/isqrt/then_0.mcfunction +3 -0
  83. package/dist/data/isqrttest/function/isqrt/then_6.mcfunction +3 -0
  84. package/dist/data/isqrttest/function/isqrt.mcfunction +7 -0
  85. package/dist/data/isqrttest/function/test.mcfunction +6 -0
  86. package/dist/data/mathtest/function/__load.mcfunction +3 -0
  87. package/dist/data/mathtest/function/abs/merge_2.mcfunction +3 -0
  88. package/dist/data/mathtest/function/abs/then_0.mcfunction +5 -0
  89. package/dist/data/mathtest/function/abs.mcfunction +6 -0
  90. package/dist/data/mathtest/function/test.mcfunction +5 -0
  91. package/dist/data/minecraft/tags/function/load.json +5 -0
  92. package/dist/data/minecraft/tags/function/tick.json +5 -0
  93. package/dist/data/mypack/function/__load.mcfunction +13 -0
  94. package/dist/data/mypack/function/_atan_init.mcfunction +2 -0
  95. package/dist/data/mypack/function/abs/merge_2.mcfunction +3 -0
  96. package/dist/data/mypack/function/abs/then_0.mcfunction +5 -0
  97. package/dist/data/mypack/function/abs.mcfunction +6 -0
  98. package/dist/data/mypack/function/atan2_fixed/__sgi_1.mcfunction +2 -0
  99. package/dist/data/mypack/function/atan2_fixed/else_34.mcfunction +3 -0
  100. package/dist/data/mypack/function/atan2_fixed/loop_body_31.mcfunction +19 -0
  101. package/dist/data/mypack/function/atan2_fixed/loop_check_30.mcfunction +5 -0
  102. package/dist/data/mypack/function/atan2_fixed/loop_exit_32.mcfunction +6 -0
  103. package/dist/data/mypack/function/atan2_fixed/merge_11.mcfunction +6 -0
  104. package/dist/data/mypack/function/atan2_fixed/merge_14.mcfunction +3 -0
  105. package/dist/data/mypack/function/atan2_fixed/merge_17.mcfunction +6 -0
  106. package/dist/data/mypack/function/atan2_fixed/merge_2.mcfunction +5 -0
  107. package/dist/data/mypack/function/atan2_fixed/merge_20.mcfunction +5 -0
  108. package/dist/data/mypack/function/atan2_fixed/merge_23.mcfunction +5 -0
  109. package/dist/data/mypack/function/atan2_fixed/merge_26.mcfunction +6 -0
  110. package/dist/data/mypack/function/atan2_fixed/merge_29.mcfunction +4 -0
  111. package/dist/data/mypack/function/atan2_fixed/merge_38.mcfunction +5 -0
  112. package/dist/data/mypack/function/atan2_fixed/merge_41.mcfunction +5 -0
  113. package/dist/data/mypack/function/atan2_fixed/merge_44.mcfunction +5 -0
  114. package/dist/data/mypack/function/atan2_fixed/merge_47.mcfunction +5 -0
  115. package/dist/data/mypack/function/atan2_fixed/merge_5.mcfunction +5 -0
  116. package/dist/data/mypack/function/atan2_fixed/merge_8.mcfunction +3 -0
  117. package/dist/data/mypack/function/atan2_fixed/then_0.mcfunction +5 -0
  118. package/dist/data/mypack/function/atan2_fixed/then_12.mcfunction +3 -0
  119. package/dist/data/mypack/function/atan2_fixed/then_15.mcfunction +5 -0
  120. package/dist/data/mypack/function/atan2_fixed/then_18.mcfunction +5 -0
  121. package/dist/data/mypack/function/atan2_fixed/then_21.mcfunction +3 -0
  122. package/dist/data/mypack/function/atan2_fixed/then_24.mcfunction +3 -0
  123. package/dist/data/mypack/function/atan2_fixed/then_27.mcfunction +6 -0
  124. package/dist/data/mypack/function/atan2_fixed/then_3.mcfunction +3 -0
  125. package/dist/data/mypack/function/atan2_fixed/then_33.mcfunction +5 -0
  126. package/dist/data/mypack/function/atan2_fixed/then_36.mcfunction +5 -0
  127. package/dist/data/mypack/function/atan2_fixed/then_39.mcfunction +5 -0
  128. package/dist/data/mypack/function/atan2_fixed/then_42.mcfunction +3 -0
  129. package/dist/data/mypack/function/atan2_fixed/then_45.mcfunction +5 -0
  130. package/dist/data/mypack/function/atan2_fixed/then_6.mcfunction +3 -0
  131. package/dist/data/mypack/function/atan2_fixed/then_9.mcfunction +5 -0
  132. package/dist/data/mypack/function/atan2_fixed.mcfunction +7 -0
  133. package/dist/data/mypack/function/my_game.mcfunction +10 -0
  134. package/dist/data/quiz/function/__load.mcfunction +16 -0
  135. package/dist/data/quiz/function/__tick.mcfunction +6 -0
  136. package/dist/data/quiz/function/__trigger_quiz_a_dispatch.mcfunction +4 -0
  137. package/dist/data/quiz/function/__trigger_quiz_b_dispatch.mcfunction +4 -0
  138. package/dist/data/quiz/function/__trigger_quiz_c_dispatch.mcfunction +4 -0
  139. package/dist/data/quiz/function/__trigger_quiz_start_dispatch.mcfunction +4 -0
  140. package/dist/data/quiz/function/answer_a.mcfunction +4 -0
  141. package/dist/data/quiz/function/answer_b.mcfunction +4 -0
  142. package/dist/data/quiz/function/answer_c.mcfunction +4 -0
  143. package/dist/data/quiz/function/ask_question/else_1.mcfunction +5 -0
  144. package/dist/data/quiz/function/ask_question/else_4.mcfunction +5 -0
  145. package/dist/data/quiz/function/ask_question/else_7.mcfunction +4 -0
  146. package/dist/data/quiz/function/ask_question/merge_2.mcfunction +1 -0
  147. package/dist/data/quiz/function/ask_question/merge_5.mcfunction +2 -0
  148. package/dist/data/quiz/function/ask_question/merge_8.mcfunction +2 -0
  149. package/dist/data/quiz/function/ask_question/then_0.mcfunction +4 -0
  150. package/dist/data/quiz/function/ask_question/then_3.mcfunction +4 -0
  151. package/dist/data/quiz/function/ask_question/then_6.mcfunction +4 -0
  152. package/dist/data/quiz/function/ask_question.mcfunction +7 -0
  153. package/dist/data/quiz/function/finish_quiz.mcfunction +6 -0
  154. package/dist/data/quiz/function/handle_answer/else_1.mcfunction +5 -0
  155. package/dist/data/quiz/function/handle_answer/else_10.mcfunction +3 -0
  156. package/dist/data/quiz/function/handle_answer/else_16.mcfunction +3 -0
  157. package/dist/data/quiz/function/handle_answer/else_4.mcfunction +3 -0
  158. package/dist/data/quiz/function/handle_answer/else_7.mcfunction +5 -0
  159. package/dist/data/quiz/function/handle_answer/merge_11.mcfunction +2 -0
  160. package/dist/data/quiz/function/handle_answer/merge_14.mcfunction +2 -0
  161. package/dist/data/quiz/function/handle_answer/merge_17.mcfunction +2 -0
  162. package/dist/data/quiz/function/handle_answer/merge_2.mcfunction +8 -0
  163. package/dist/data/quiz/function/handle_answer/merge_5.mcfunction +2 -0
  164. package/dist/data/quiz/function/handle_answer/merge_8.mcfunction +2 -0
  165. package/dist/data/quiz/function/handle_answer/then_0.mcfunction +5 -0
  166. package/dist/data/quiz/function/handle_answer/then_12.mcfunction +5 -0
  167. package/dist/data/quiz/function/handle_answer/then_15.mcfunction +6 -0
  168. package/dist/data/quiz/function/handle_answer/then_3.mcfunction +6 -0
  169. package/dist/data/quiz/function/handle_answer/then_6.mcfunction +5 -0
  170. package/dist/data/quiz/function/handle_answer/then_9.mcfunction +6 -0
  171. package/dist/data/quiz/function/handle_answer.mcfunction +11 -0
  172. package/dist/data/quiz/function/start_quiz.mcfunction +5 -0
  173. package/dist/data/reqtest/function/__load.mcfunction +4 -0
  174. package/dist/data/reqtest/function/_table_init.mcfunction +2 -0
  175. package/dist/data/reqtest/function/no_trig.mcfunction +3 -0
  176. package/dist/data/reqtest/function/use_table.mcfunction +4 -0
  177. package/dist/data/reqtest2/function/__load.mcfunction +3 -0
  178. package/dist/data/reqtest2/function/no_trig.mcfunction +3 -0
  179. package/dist/data/runtime/function/__load.mcfunction +5 -0
  180. package/dist/data/runtime/function/__tick.mcfunction +2 -0
  181. package/dist/data/runtime/function/counter_tick/then_0.mcfunction +3 -0
  182. package/dist/data/runtime/function/counter_tick.mcfunction +13 -0
  183. package/dist/data/shop/function/__load.mcfunction +7 -0
  184. package/dist/data/shop/function/__tick.mcfunction +3 -0
  185. package/dist/data/shop/function/__trigger_shop_buy_dispatch.mcfunction +4 -0
  186. package/dist/data/shop/function/complete_purchase/else_1.mcfunction +5 -0
  187. package/dist/data/shop/function/complete_purchase/else_4.mcfunction +5 -0
  188. package/dist/data/shop/function/complete_purchase/else_7.mcfunction +3 -0
  189. package/dist/data/shop/function/complete_purchase/merge_2.mcfunction +2 -0
  190. package/dist/data/shop/function/complete_purchase/merge_5.mcfunction +2 -0
  191. package/dist/data/shop/function/complete_purchase/merge_8.mcfunction +2 -0
  192. package/dist/data/shop/function/complete_purchase/then_0.mcfunction +4 -0
  193. package/dist/data/shop/function/complete_purchase/then_3.mcfunction +4 -0
  194. package/dist/data/shop/function/complete_purchase/then_6.mcfunction +4 -0
  195. package/dist/data/shop/function/complete_purchase.mcfunction +7 -0
  196. package/dist/data/shop/function/handle_shop_trigger.mcfunction +3 -0
  197. package/dist/data/swap_test/function/__load.mcfunction +3 -0
  198. package/dist/data/swap_test/function/gcd_old/loop_body_1.mcfunction +7 -0
  199. package/dist/data/swap_test/function/gcd_old/loop_check_0.mcfunction +5 -0
  200. package/dist/data/swap_test/function/gcd_old/loop_exit_2.mcfunction +3 -0
  201. package/dist/data/swap_test/function/gcd_old.mcfunction +8 -0
  202. package/dist/data/turret/function/__load.mcfunction +5 -0
  203. package/dist/data/turret/function/__tick.mcfunction +4 -0
  204. package/dist/data/turret/function/__trigger_deploy_turret_dispatch.mcfunction +4 -0
  205. package/dist/data/turret/function/deploy_turret.mcfunction +8 -0
  206. package/dist/data/turret/function/turret_tick/at_1.mcfunction +2 -0
  207. package/dist/data/turret/function/turret_tick/foreach_0.mcfunction +2 -0
  208. package/dist/data/turret/function/turret_tick/foreach_2.mcfunction +2 -0
  209. package/dist/data/turret/function/turret_tick/tick_body.mcfunction +3 -0
  210. package/dist/data/turret/function/turret_tick/tick_skip.mcfunction +1 -0
  211. package/dist/data/turret/function/turret_tick.mcfunction +5 -0
  212. package/dist/gcd2.map.json +15 -0
  213. package/dist/gcd3.map.json +17 -0
  214. package/dist/gcd_test.map.json +15 -0
  215. package/dist/index.js +20 -1
  216. package/dist/ir/types.d.ts +4 -0
  217. package/dist/isqrttest.map.json +15 -0
  218. package/dist/lexer/index.d.ts +1 -1
  219. package/dist/lexer/index.js +1 -0
  220. package/dist/lowering/index.d.ts +5 -0
  221. package/dist/lowering/index.js +154 -14
  222. package/dist/mathtest.map.json +6 -0
  223. package/dist/mypack.map.json +27 -0
  224. package/dist/optimizer/dce.js +21 -5
  225. package/dist/optimizer/passes.js +18 -6
  226. package/dist/optimizer/structure.js +7 -0
  227. package/dist/pack.mcmeta +6 -0
  228. package/dist/parser/index.d.ts +5 -0
  229. package/dist/parser/index.js +43 -2
  230. package/dist/reqtest.map.json +4 -0
  231. package/dist/reqtest2.map.json +4 -0
  232. package/dist/runtime/index.d.ts +6 -0
  233. package/dist/runtime/index.js +130 -9
  234. package/dist/runtime.map.json +7 -0
  235. package/dist/swap_test.map.json +14 -0
  236. package/editors/vscode/package-lock.json +3 -3
  237. package/editors/vscode/package.json +1 -1
  238. package/examples/showcase.mcrs +505 -0
  239. package/package.json +1 -1
  240. package/src/__tests__/cli.test.ts +1 -1
  241. package/src/__tests__/codegen.test.ts +12 -6
  242. package/src/__tests__/e2e.test.ts +6 -6
  243. package/src/__tests__/lowering.test.ts +8 -8
  244. package/src/__tests__/optimizer.test.ts +33 -0
  245. package/src/__tests__/stdlib-advanced.test.ts +379 -0
  246. package/src/__tests__/stdlib-bigint.test.ts +427 -0
  247. package/src/__tests__/stdlib-math.test.ts +374 -0
  248. package/src/__tests__/stdlib-vec.test.ts +259 -0
  249. package/src/ast/types.ts +11 -1
  250. package/src/codegen/mcfunction/index.ts +143 -19
  251. package/src/codegen/var-allocator.ts +29 -0
  252. package/src/compile.ts +72 -5
  253. package/src/index.ts +21 -1
  254. package/src/ir/types.ts +2 -0
  255. package/src/lexer/index.ts +2 -1
  256. package/src/lowering/index.ts +171 -14
  257. package/src/optimizer/dce.ts +22 -5
  258. package/src/optimizer/passes.ts +18 -5
  259. package/src/optimizer/structure.ts +6 -1
  260. package/src/parser/index.ts +47 -2
  261. package/src/runtime/index.ts +130 -10
  262. package/src/stdlib/advanced.mcrs +330 -0
  263. package/src/stdlib/bigint.mcrs +205 -0
  264. package/src/stdlib/math.mcrs +274 -21
  265. package/src/stdlib/vec.mcrs +246 -0
@@ -0,0 +1,205 @@
1
+ // bigint.mcrs — Arbitrary precision integer arithmetic for RedScript.
2
+ //
3
+ // Representation:
4
+ // 8 limbs, base B = 10000 (10^4) per limb.
5
+ // Limb[0] = least significant (ones place in base 10000).
6
+ // Maximum value: 10^32 - 1 (32 decimal digits).
7
+ // Stored in NBT int arrays inside data storage ("rs:bigint").
8
+ //
9
+ // Registers: "a", "b", "c" (three independent BigInt values).
10
+ //
11
+ // Usage example:
12
+ // bigint_init();
13
+ // bigint_from_int_a(12345678); // a = 12345678
14
+ // bigint_from_int_b(87654321); // b = 87654321
15
+ // bigint_add(); // c = a + b = 99999999
16
+ // let limb0: int = bigint_get_c(0); // → 9999 (c[0])
17
+ // let limb1: int = bigint_get_c(1); // → 9999 (c[1])
18
+ //
19
+ // Multiply overflow note:
20
+ // bigint_mul uses grade-school O(n^2) algorithm.
21
+ // Per-product max: 9999 * 9999 + 9999 + 9999 = 99,999,999 < INT32 ✓
22
+
23
+ module library;
24
+
25
+ // ── Initialization ────────────────────────────────────────────────────────────
26
+
27
+ // Initialize (or reset) all BigInt registers to zero.
28
+ // Must be called once before using any bigint operation.
29
+ fn bigint_init() {
30
+ storage_set_array("rs:bigint", "a", "[0,0,0,0,0,0,0,0]");
31
+ storage_set_array("rs:bigint", "b", "[0,0,0,0,0,0,0,0]");
32
+ storage_set_array("rs:bigint", "c", "[0,0,0,0,0,0,0,0]");
33
+ }
34
+
35
+ // ── Load from int32 ───────────────────────────────────────────────────────────
36
+
37
+ // Set register a from a 32-bit integer (splits into up to 3 limbs).
38
+ // Supports any n in [0, 999999999999] (12-digit safe limit).
39
+ fn bigint_from_int_a(n: int) {
40
+ storage_set_array("rs:bigint", "a", "[0,0,0,0,0,0,0,0]");
41
+ storage_set_int("rs:bigint", "a", 0, n % 10000);
42
+ storage_set_int("rs:bigint", "a", 1, n / 10000 % 10000);
43
+ storage_set_int("rs:bigint", "a", 2, n / 10000 / 10000);
44
+ }
45
+
46
+ // Set register b from a 32-bit integer.
47
+ fn bigint_from_int_b(n: int) {
48
+ storage_set_array("rs:bigint", "b", "[0,0,0,0,0,0,0,0]");
49
+ storage_set_int("rs:bigint", "b", 0, n % 10000);
50
+ storage_set_int("rs:bigint", "b", 1, n / 10000 % 10000);
51
+ storage_set_int("rs:bigint", "b", 2, n / 10000 / 10000);
52
+ }
53
+
54
+ // ── Read limb ─────────────────────────────────────────────────────────────────
55
+
56
+ fn bigint_get_a(i: int) -> int { return storage_get_int("rs:bigint", "a", i); }
57
+ fn bigint_get_b(i: int) -> int { return storage_get_int("rs:bigint", "b", i); }
58
+ fn bigint_get_c(i: int) -> int { return storage_get_int("rs:bigint", "c", i); }
59
+
60
+ // ── Copy between registers ────────────────────────────────────────────────────
61
+
62
+ fn bigint_copy_a_to_b() {
63
+ let i: int = 0;
64
+ while (i < 8) {
65
+ storage_set_int("rs:bigint", "b", i, storage_get_int("rs:bigint", "a", i));
66
+ i = i + 1;
67
+ }
68
+ }
69
+
70
+ fn bigint_copy_b_to_a() {
71
+ let i: int = 0;
72
+ while (i < 8) {
73
+ storage_set_int("rs:bigint", "a", i, storage_get_int("rs:bigint", "b", i));
74
+ i = i + 1;
75
+ }
76
+ }
77
+
78
+ fn bigint_copy_c_to_a() {
79
+ let i: int = 0;
80
+ while (i < 8) {
81
+ storage_set_int("rs:bigint", "a", i, storage_get_int("rs:bigint", "c", i));
82
+ i = i + 1;
83
+ }
84
+ }
85
+
86
+ fn bigint_copy_c_to_b() {
87
+ let i: int = 0;
88
+ while (i < 8) {
89
+ storage_set_int("rs:bigint", "b", i, storage_get_int("rs:bigint", "c", i));
90
+ i = i + 1;
91
+ }
92
+ }
93
+
94
+ // ── Addition: c = a + b ───────────────────────────────────────────────────────
95
+
96
+ // c = a + b (carry propagated across all 8 limbs)
97
+ fn bigint_add() {
98
+ let carry: int = 0;
99
+ let i: int = 0;
100
+ while (i < 8) {
101
+ let s: int = storage_get_int("rs:bigint", "a", i)
102
+ + storage_get_int("rs:bigint", "b", i)
103
+ + carry;
104
+ carry = s / 10000;
105
+ storage_set_int("rs:bigint", "c", i, s % 10000);
106
+ i = i + 1;
107
+ }
108
+ }
109
+
110
+ // ── Subtraction: c = a - b (assumes a ≥ b) ──────────────────────────────────
111
+
112
+ fn bigint_sub() {
113
+ let borrow: int = 0;
114
+ let i: int = 0;
115
+ while (i < 8) {
116
+ let d: int = storage_get_int("rs:bigint", "a", i)
117
+ - storage_get_int("rs:bigint", "b", i)
118
+ - borrow;
119
+ if (d < 0) {
120
+ d = d + 10000;
121
+ borrow = 1;
122
+ } else {
123
+ borrow = 0;
124
+ }
125
+ storage_set_int("rs:bigint", "c", i, d);
126
+ i = i + 1;
127
+ }
128
+ }
129
+
130
+ // ── Comparison: returns 1 (a>b), 0 (a==b), -1 (a<b) ─────────────────────────
131
+
132
+ fn bigint_compare() -> int {
133
+ let i: int = 7;
134
+ while (i >= 0) {
135
+ let ai: int = storage_get_int("rs:bigint", "a", i);
136
+ let bi: int = storage_get_int("rs:bigint", "b", i);
137
+ if (ai > bi) { return 1; }
138
+ if (ai < bi) { return -1; }
139
+ i = i - 1;
140
+ }
141
+ return 0;
142
+ }
143
+
144
+ // ── Multiply by small constant: c = a × k (k < 10000) ───────────────────────
145
+ // Max per-limb: 9999 × 9999 + 9999 = 99,989,999 < INT32 ✓
146
+
147
+ fn bigint_mul_small(k: int) {
148
+ let carry: int = 0;
149
+ let i: int = 0;
150
+ while (i < 8) {
151
+ let p: int = storage_get_int("rs:bigint", "a", i) * k + carry;
152
+ carry = p / 10000;
153
+ storage_set_int("rs:bigint", "c", i, p % 10000);
154
+ i = i + 1;
155
+ }
156
+ }
157
+
158
+ // ── Multiply: c = a × b (grade-school O(n²), n=8) ───────────────────────────
159
+ // Per-product max: 9999 × 9999 + 9999 (prev c) + 9999 (carry) = 99,999,999 < INT32 ✓
160
+
161
+ fn bigint_mul() {
162
+ storage_set_array("rs:bigint", "c", "[0,0,0,0,0,0,0,0]");
163
+ let i: int = 0;
164
+ while (i < 8) {
165
+ let ai: int = storage_get_int("rs:bigint", "a", i);
166
+ if (ai != 0) {
167
+ let j: int = 0;
168
+ let carry: int = 0;
169
+ while (j < 8) {
170
+ let k: int = i + j;
171
+ if (k < 8) {
172
+ let p: int = ai * storage_get_int("rs:bigint", "b", j)
173
+ + storage_get_int("rs:bigint", "c", k)
174
+ + carry;
175
+ carry = p / 10000;
176
+ storage_set_int("rs:bigint", "c", k, p % 10000);
177
+ }
178
+ j = j + 1;
179
+ }
180
+ }
181
+ i = i + 1;
182
+ }
183
+ }
184
+
185
+ // ── Fibonacci: F(n) → register a (n ≤ 150 before 32-digit overflow) ─────────
186
+ //
187
+ // Invariant: a=F(k), b=F(k+1). After n iterations: a=F(n).
188
+ //
189
+ // F(50) = 12,586,269,025 → a[0]=9025, a[1]=8626, a[2]=125
190
+ // F(100) = 354,224,848,179,261,915,075 → 21 digits, fits in 6 limbs
191
+
192
+ fn bigint_fib(n: int) {
193
+ bigint_init(); // a=0=F(0), b=0
194
+ bigint_from_int_b(1); // b=1=F(1)
195
+ let i: int = 0;
196
+ while (i < n) {
197
+ // Invariant entering iteration: a=F(i), b=F(i+1)
198
+ bigint_add(); // c = F(i) + F(i+1) = F(i+2)
199
+ bigint_copy_b_to_a(); // a = F(i+1)
200
+ bigint_copy_c_to_b(); // b = F(i+2)
201
+ // Invariant restored: a=F(i+1), b=F(i+2)
202
+ i = i + 1;
203
+ }
204
+ // result: a = F(n)
205
+ }
@@ -1,49 +1,302 @@
1
- // Integer math helpers for RedScript datapacks.
1
+ // math.mcrs — Integer & fixed-point math helpers for RedScript datapacks.
2
+ //
3
+ // Fixed-point convention: scale = 1000
4
+ // 1.0 → 1000
5
+ // 3.14 → 3140
6
+ // Use `sqrt_fixed` / `lerp` for sub-integer precision.
7
+ //
8
+ // Phase 1: basic integer helpers (abs, sign, min, max, clamp, lerp)
9
+ // Phase 2: iterative algorithms (isqrt, sqrt_fixed, pow_int, gcd)
10
+ // Phase 3: trig (sin_fixed, cos_fixed) — lookup table in NBT storage
11
+
12
+ // All functions in this file are library-mode: only compiled into the
13
+ // datapack if actually called from user code. Use via `librarySources`
14
+ // compile option or concatenate with user code (module library; handles it).
15
+ module library;
16
+ // Phase 4: number theory & utilities (lcm, map, ceil_div, log2_int)
17
+
18
+ // ─── Phase 1: Basic integer helpers ──────────────────────────────────────────
2
19
 
3
20
  fn abs(x: int) -> int {
4
21
  if (x < 0) {
5
- return -x;
6
- } else {
7
- return x;
22
+ return 0 - x;
8
23
  }
24
+ return x;
25
+ }
26
+
27
+ fn sign(x: int) -> int {
28
+ if (x > 0) {
29
+ return 1;
30
+ }
31
+ if (x < 0) {
32
+ return -1;
33
+ }
34
+ return 0;
9
35
  }
10
36
 
11
37
  fn min(a: int, b: int) -> int {
12
38
  if (a < b) {
13
39
  return a;
14
- } else {
15
- return b;
16
40
  }
41
+ return b;
17
42
  }
18
43
 
19
44
  fn max(a: int, b: int) -> int {
20
45
  if (a > b) {
21
46
  return a;
22
- } else {
23
- return b;
24
47
  }
48
+ return b;
25
49
  }
26
50
 
27
51
  fn clamp(x: int, lo: int, hi: int) -> int {
28
52
  if (x < lo) {
29
53
  return lo;
30
- } else {
31
- if (x > hi) {
32
- return hi;
33
- } else {
34
- return x;
35
- }
36
54
  }
55
+ if (x > hi) {
56
+ return hi;
57
+ }
58
+ return x;
37
59
  }
38
60
 
39
- fn sign(x: int) -> int {
40
- if (x > 0) {
61
+ // Linear interpolation (fixed-point t, t in [0, 1000])
62
+ // lerp(0, 1000, 500) == 500
63
+ // lerp(100, 200, 750) == 175
64
+ fn lerp(a: int, b: int, t: int) -> int {
65
+ return a + (b - a) * t / 1000;
66
+ }
67
+
68
+ // ─── Phase 2: Iterative algorithms ───────────────────────────────────────────
69
+
70
+ // Integer square root: floor(sqrt(n))
71
+ // Uses Newton's method, converges in ≤16 iterations for all int32.
72
+ // isqrt(9) == 3, isqrt(10) == 3, isqrt(0) == 0
73
+ fn isqrt(n: int) -> int {
74
+ if (n <= 0) { return 0; }
75
+ if (n == 1) { return 1; }
76
+ // Bit-length of n: how many bits needed to represent n.
77
+ let bits: int = 0;
78
+ let tmp: int = n;
79
+ while (tmp > 0) {
80
+ tmp = tmp / 2;
81
+ bits = bits + 1;
82
+ }
83
+ // Initial guess: 2^((bits+1)/2). Always ≥ sqrt(n), so Newton converges
84
+ // monotonically from above — the standard floor-sqrt Newton iteration.
85
+ let half: int = (bits + 1) / 2;
86
+ let x: int = 1;
87
+ let j: int = 0;
88
+ while (j < half) {
89
+ x = x * 2;
90
+ j = j + 1;
91
+ }
92
+ // Newton–Raphson floor-sqrt: converges in ≤ 8 iterations from a 2× overestimate.
93
+ let i: int = 0;
94
+ while (i < 16) {
95
+ let next: int = (x + n / x) / 2;
96
+ if (next >= x) { return x; }
97
+ x = next;
98
+ i = i + 1;
99
+ }
100
+ return x;
101
+ }
102
+
103
+ // Fixed-point sqrt (scale = 1000)
104
+ // sqrt_fixed(2000) ≈ 1414 (√2 × 1000)
105
+ // sqrt_fixed(1000) == 1000 (√1 × 1000)
106
+ fn sqrt_fixed(x: int) -> int {
107
+ return isqrt(x * 1000);
108
+ }
109
+
110
+ // Integer power: base^exp (exp ≥ 0)
111
+ // Fast exponentiation by squaring: O(log exp)
112
+ // pow_int(2, 10) == 1024, pow_int(3, 0) == 1
113
+ fn pow_int(base: int, exp: int) -> int {
114
+ if (exp <= 0) {
41
115
  return 1;
42
- } else {
43
- if (x < 0) {
44
- return -1;
45
- } else {
46
- return 0;
116
+ }
117
+ let result: int = 1;
118
+ let b: int = base;
119
+ let e: int = exp;
120
+ while (e > 0) {
121
+ if (e % 2 == 1) {
122
+ result = result * b;
47
123
  }
124
+ b = b * b;
125
+ e = e / 2;
126
+ }
127
+ return result;
128
+ }
129
+
130
+ // Greatest common divisor (Euclidean algorithm)
131
+ // gcd(12, 8) == 4, gcd(0, 5) == 5
132
+ fn gcd(a: int, b: int) -> int {
133
+ // Inline abs to avoid cross-function scoreboard variable collision.
134
+ let x: int = a;
135
+ if (x < 0) { x = 0 - x; }
136
+ let y: int = b;
137
+ if (y < 0) { y = 0 - y; }
138
+ while (y > 0) {
139
+ let r: int = x % y;
140
+ x = y;
141
+ y = r;
142
+ }
143
+ return x;
144
+ }
145
+
146
+ // ─── Phase 3: Trigonometry ────────────────────────────────────────────────────
147
+ //
148
+ // sin/cos lookup table stored in NBT storage (math:tables).
149
+ // 91 entries covering 0-90°; other quadrants derived by symmetry.
150
+ // All values are sin(i°) × 1000, rounded to nearest integer.
151
+ //
152
+ // Accuracy: ≤ 1 unit error (≤0.1% relative) for all integer degrees.
153
+ // Cost: ~4 MC commands per call + 1 NBT read per call (O(1)).
154
+
155
+ // Initialize the sin lookup table.
156
+ // This function has NO @load — it is called from __load only when sin_fixed
157
+ // or cos_fixed are compiled into the project (via @requires). If you only
158
+ // use Phase 1/2/4 functions, this never runs and adds zero overhead.
159
+ fn _math_init() {
160
+ storage_set_array("math:tables", "sin",
161
+ "[0, 17, 35, 52, 70, 87, 105, 122, 139, 156, 174, 191, 208, 225, 242, 259, 276, 292, 309, 326, 342, 358, 375, 391, 407, 423, 438, 454, 469, 485, 500, 515, 530, 545, 559, 574, 588, 602, 616, 629, 643, 656, 669, 682, 695, 707, 719, 731, 743, 755, 766, 777, 788, 799, 809, 819, 829, 839, 848, 857, 866, 875, 883, 891, 899, 906, 914, 921, 927, 934, 940, 946, 951, 956, 961, 966, 970, 974, 978, 982, 985, 988, 990, 993, 995, 996, 998, 999, 999, 1000, 1000]"
162
+ );
163
+ }
164
+
165
+ // sin_fixed(deg) → sin(deg°) × 1000 (integer degrees, any value)
166
+ // sin_fixed(30) == 500
167
+ // sin_fixed(90) == 1000
168
+ // sin_fixed(180) == 0
169
+ // sin_fixed(270) == -1000
170
+ //
171
+ // @require_on_load(_math_init): the sin lookup table is written to NBT storage at
172
+ // world load automatically when this function is included in a project.
173
+ @require_on_load(_math_init)
174
+ fn sin_fixed(deg: int) -> int {
175
+ // Normalise to [0, 359]
176
+ let d: int = deg % 360;
177
+ if (d < 0) { d = d + 360; }
178
+
179
+ // Quadrant reduction to first quadrant index [0, 90]
180
+ if (d <= 90) {
181
+ return storage_get_int("math:tables", "sin", d);
182
+ }
183
+ if (d <= 180) {
184
+ return storage_get_int("math:tables", "sin", 180 - d);
185
+ }
186
+ if (d <= 270) {
187
+ let idx: int = d - 180;
188
+ return 0 - storage_get_int("math:tables", "sin", idx);
48
189
  }
190
+ // d in (270, 360)
191
+ let idx: int = 360 - d;
192
+ return 0 - storage_get_int("math:tables", "sin", idx);
193
+ }
194
+
195
+ // cos_fixed(deg) → cos(deg°) × 1000 (integer degrees, any value)
196
+ // cos_fixed(0) == 1000
197
+ // cos_fixed(90) == 0
198
+ // cos_fixed(180) == -1000
199
+ @require_on_load(_math_init)
200
+ fn cos_fixed(deg: int) -> int {
201
+ return sin_fixed(deg + 90);
202
+ }
203
+
204
+ // ─── Phase 4: Number theory & utilities ──────────────────────────────────────
205
+
206
+ // Least common multiple
207
+ // lcm(4, 6) == 12, lcm(0, 5) == 0
208
+ fn lcm(a: int, b: int) -> int {
209
+ let g: int = gcd(a, b);
210
+ if (g == 0) { return 0; }
211
+ return a / g * b;
212
+ }
213
+
214
+ // Range map: scale x from [in_lo, in_hi] onto [out_lo, out_hi].
215
+ // Uses integer arithmetic — multiply before dividing to preserve precision.
216
+ // map(5, 0, 10, 0, 100) == 50
217
+ // map(1, 0, 10, 100, 200) == 110
218
+ fn map(x: int, in_lo: int, in_hi: int, out_lo: int, out_hi: int) -> int {
219
+ let in_range: int = in_hi - in_lo;
220
+ if (in_range == 0) { return out_lo; }
221
+ return out_lo + (x - in_lo) * (out_hi - out_lo) / in_range;
222
+ }
223
+
224
+ // Ceiling division: ⌈a / b⌉ (b > 0 required)
225
+ // ceil_div(7, 3) == 3, ceil_div(6, 3) == 2
226
+ fn ceil_div(a: int, b: int) -> int {
227
+ return (a + b - 1) / b;
228
+ }
229
+
230
+ // Integer log base 2: ⌊log₂(n)⌋
231
+ // log2_int(1) == 0, log2_int(8) == 3, log2_int(7) == 2
232
+ // Returns -1 for n ≤ 0 (error sentinel).
233
+ fn log2_int(n: int) -> int {
234
+ if (n <= 0) { return -1; }
235
+ let result: int = 0;
236
+ let v: int = n;
237
+ while (v > 1) {
238
+ v = v / 2;
239
+ result = result + 1;
240
+ }
241
+ return result;
242
+ }
243
+
244
+ // ─── Phase 5: Fixed-point arithmetic & easing ────────────────────────────────
245
+ // Vector functions (dot2d, cross2d, length2d_fixed, manhattan, chebyshev,
246
+ // atan2_fixed, rotate2d, normalize2d, etc.) have moved to vec.mcrs.
247
+
248
+ // Fixed-point multiply: (a × b) / 1000
249
+ // Use instead of a*b when both operands are fixed-point (scale=1000),
250
+ // e.g. mulfix(sin_fixed(30), cos_fixed(45)) instead of sin*cos which overflows.
251
+ // mulfix(500, 707) == 353 (≈ 0.5 × 0.707)
252
+ fn mulfix(a: int, b: int) -> int {
253
+ return a * b / 1000;
254
+ }
255
+
256
+ // Fixed-point divide: (a × 1000) / b
257
+ // Inverse of mulfix; produces a fixed-point result from two integers.
258
+ // divfix(1, 3) == 333 (≈ 0.333)
259
+ fn divfix(a: int, b: int) -> int {
260
+ if (b == 0) { return 0; }
261
+ return a * 1000 / b;
262
+ }
263
+
264
+ // Smooth Hermite interpolation (Ken Perlin's smoothstep).
265
+ // Returns a value in [0, 1000] (fixed-point scale = 1000).
266
+ // Eases in AND out — useful for animations and value transitions.
267
+ //
268
+ // smoothstep(0, 100, 0) == 0
269
+ // smoothstep(0, 100, 50) == 500
270
+ // smoothstep(0, 100, 100) == 1000
271
+ // smoothstep(0, 100, 25) == 156 (≈ 3×0.25² − 2×0.25³ = 0.15625)
272
+ fn smoothstep(lo: int, hi: int, x: int) -> int {
273
+ let range: int = hi - lo;
274
+ if (range == 0) { return 0; }
275
+ // t in [0, 1000]
276
+ let t: int = (x - lo) * 1000 / range;
277
+ if (t < 0) { t = 0; }
278
+ if (t > 1000) { t = 1000; }
279
+ // f(t) = t² × (3 − 2t) / 1000 (all in scale=1000)
280
+ // Rewrite to avoid int32 overflow: use t/10 as intermediate
281
+ let t10: int = t / 10; // [0, 100], avoids 1000² = 10⁶ overflow
282
+ return t10 * t10 * (3000 - 2 * t) / 10000;
283
+ }
284
+
285
+ // Smoother step (Perlin's order-5): 6t⁵ − 15t⁴ + 10t³
286
+ // Higher-order derivative at edges → smoother acceleration curve.
287
+ // smootherstep(0, 100, 25) ≈ 103
288
+ fn smootherstep(lo: int, hi: int, x: int) -> int {
289
+ let range: int = hi - lo;
290
+ if (range == 0) { return 0; }
291
+ let t: int = (x - lo) * 1000 / range;
292
+ if (t < 0) { t = 0; }
293
+ if (t > 1000) { t = 1000; }
294
+ // f(t) = t³ × (10 − t × (15 − 6t) / 1000) / 1000000
295
+ // Compute in stages to stay within int32
296
+ let t10: int = t / 10; // [0, 100]
297
+ let t2: int = t10 * t10; // [0, 10000]
298
+ let t3: int = t2 * t10 / 100; // [0, 10000]
299
+ // 10t³ − 15t⁴ + 6t⁵ = t³(10 − 15t + 6t²) at scale=1000
300
+ let inner: int = 10000 - 15 * t10 + 6 * t2 / 100;
301
+ return t3 * inner / 100000;
49
302
  }