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,246 @@
1
+ // vec.mcrs — 2D and 3D vector math for RedScript datapacks.
2
+ //
3
+ // Fixed-point convention: scale = 1000 (same as math.mcrs)
4
+ // A unit vector has components in [-1000, 1000].
5
+ // A position / displacement in block coordinates uses raw integers.
6
+ //
7
+ // Dependency: import "math.mcrs" before this file (or compile with librarySources).
8
+ // Requires: abs, sqrt_fixed, sin_fixed, cos_fixed, lerp, mulfix, length2d_fixed
9
+ //
10
+ // Phase 1: 2D geometry (dot, cross, distance, length, normalize, lerp)
11
+ // Phase 2: 2D direction (rotate, atan2)
12
+ // Phase 3: 3D geometry (dot, cross, length, distance, manhattan, chebyshev)
13
+
14
+ module library;
15
+
16
+ // ─── Phase 1: 2D geometry ────────────────────────────────────────────────────
17
+
18
+ // Dot product of two 2D integer vectors.
19
+ // dot2d(3, 4, 3, 4) == 25
20
+ fn dot2d(ax: int, ay: int, bx: int, by: int) -> int {
21
+ return ax * bx + ay * by;
22
+ }
23
+
24
+ // Z-component of the 3D cross product (ax*by − ay*bx).
25
+ // Positive: b is counter-clockwise from a.
26
+ // cross2d(1, 0, 0, 1) == 1
27
+ fn cross2d(ax: int, ay: int, bx: int, by: int) -> int {
28
+ return ax * by - ay * bx;
29
+ }
30
+
31
+ // Euclidean length of a 2D integer vector, result in fixed-point (×1000).
32
+ // length2d_fixed(3, 4) == 5000 (√25 × 1000)
33
+ // Note: |x|, |y| ≤ ~1000 to avoid overflow; scale larger vectors down first.
34
+ fn length2d_fixed(x: int, y: int) -> int {
35
+ return sqrt_fixed((x * x + y * y) * 1000);
36
+ }
37
+
38
+ // Euclidean distance between two integer-coordinate points, result ×1000.
39
+ // distance2d_fixed(0, 0, 3, 4) == 5000
40
+ fn distance2d_fixed(x1: int, y1: int, x2: int, y2: int) -> int {
41
+ let dx: int = x1 - x2;
42
+ let dy: int = y1 - y2;
43
+ return length2d_fixed(dx, dy);
44
+ }
45
+
46
+ // Manhattan distance (taxicab): |dx| + |dy|.
47
+ // manhattan(0, 0, 3, 4) == 7
48
+ fn manhattan(x1: int, y1: int, x2: int, y2: int) -> int {
49
+ let dx: int = x1 - x2;
50
+ let dy: int = y1 - y2;
51
+ if (dx < 0) { dx = 0 - dx; }
52
+ if (dy < 0) { dy = 0 - dy; }
53
+ return dx + dy;
54
+ }
55
+
56
+ // Chebyshev distance (chess-king): max(|dx|, |dy|).
57
+ // chebyshev(0, 0, 3, 4) == 4
58
+ fn chebyshev(x1: int, y1: int, x2: int, y2: int) -> int {
59
+ let dx: int = x1 - x2;
60
+ let dy: int = y1 - y2;
61
+ if (dx < 0) { dx = 0 - dx; }
62
+ if (dy < 0) { dy = 0 - dy; }
63
+ if (dx > dy) { return dx; }
64
+ return dy;
65
+ }
66
+
67
+ // X-component of the normalized unit vector (× 1000).
68
+ // normalize2d_x(3, 4) == 600 (3/5 × 1000)
69
+ // Returns 0 for the zero vector.
70
+ fn normalize2d_x(x: int, y: int) -> int {
71
+ let len: int = length2d_fixed(x, y);
72
+ if (len == 0) { return 0; }
73
+ return x * 1000000 / len;
74
+ }
75
+
76
+ // Y-component of the normalized unit vector (× 1000).
77
+ // normalize2d_y(3, 4) == 800 (4/5 × 1000)
78
+ fn normalize2d_y(x: int, y: int) -> int {
79
+ let len: int = length2d_fixed(x, y);
80
+ if (len == 0) { return 0; }
81
+ return y * 1000000 / len;
82
+ }
83
+
84
+ // Linearly interpolate between vectors a=(ax,ay) and b=(bx,by), return x.
85
+ // t in [0, 1000] (fixed-point).
86
+ // lerp2d_x(0, 0, 100, 200, 500) == 50
87
+ fn lerp2d_x(ax: int, ay: int, bx: int, by: int, t: int) -> int {
88
+ return ax + (bx - ax) * t / 1000;
89
+ }
90
+
91
+ // Linearly interpolate between vectors a and b, return y.
92
+ // lerp2d_y(0, 0, 100, 200, 500) == 100
93
+ fn lerp2d_y(ax: int, ay: int, bx: int, by: int, t: int) -> int {
94
+ return ay + (by - ay) * t / 1000;
95
+ }
96
+
97
+ // ─── Phase 2: 2D direction ────────────────────────────────────────────────────
98
+
99
+ // tan lookup table for atan2_fixed binary search
100
+ fn _atan_init() {
101
+ storage_set_array("math:tables", "tan",
102
+ "[0, 17, 35, 52, 70, 87, 105, 123, 141, 158, 176, 194, 213, 231, 249, 268, 287, 306, 325, 344, 364, 384, 404, 424, 445, 466, 488, 510, 532, 554, 577, 601, 625, 649, 675, 700, 727, 754, 781, 810, 839, 869, 900, 933, 966, 1000]"
103
+ );
104
+ }
105
+
106
+ // Angle of the vector (y, x) in integer degrees [0, 359].
107
+ // Uses binary search on the tan table → O(log 46) per call.
108
+ //
109
+ // atan2_fixed(0, 1) == 0 (east)
110
+ // atan2_fixed(1, 0) == 90
111
+ // atan2_fixed(0, -1) == 180 (west)
112
+ // atan2_fixed(-1, 0) == 270
113
+ // atan2_fixed(1, 1) == 45
114
+ //
115
+ // Inputs clamped to ≤ 46340 to avoid overflow. For larger vectors:
116
+ // atan2_fixed(dy / 1000, dx / 1000)
117
+ @require_on_load(_atan_init)
118
+ fn atan2_fixed(y: int, x: int) -> int {
119
+ if (x == 0) {
120
+ if (y > 0) { return 90; }
121
+ if (y < 0) { return 270; }
122
+ return 0;
123
+ }
124
+ if (y == 0) {
125
+ if (x > 0) { return 0; }
126
+ return 180;
127
+ }
128
+
129
+ let ax: int = x;
130
+ if (ax < 0) { ax = 0 - ax; }
131
+ let ay: int = y;
132
+ if (ay < 0) { ay = 0 - ay; }
133
+
134
+ if (ax > 46340) { ax = 46340; }
135
+ if (ay > 46340) { ay = 46340; }
136
+
137
+ let swapped: int = 0;
138
+ if (ay > ax) {
139
+ let tmp: int = ax;
140
+ ax = ay;
141
+ ay = tmp;
142
+ swapped = 1;
143
+ }
144
+
145
+ let lo: int = 0;
146
+ let hi: int = 45;
147
+ while (lo < hi) {
148
+ let mid: int = (lo + hi + 1) / 2;
149
+ let t: int = storage_get_int("math:tables", "tan", mid);
150
+ if (t * ax > ay * 1000) {
151
+ hi = mid - 1;
152
+ } else {
153
+ lo = mid;
154
+ }
155
+ }
156
+ let theta: int = lo;
157
+ if (swapped == 1) { theta = 90 - theta; }
158
+
159
+ if (x > 0) {
160
+ if (y >= 0) { return theta; }
161
+ return 360 - theta;
162
+ }
163
+ if (y >= 0) { return 180 - theta; }
164
+ return 180 + theta;
165
+ }
166
+
167
+ // Rotate a 2D vector (x, y) by deg degrees, return the new X component.
168
+ // Uses sin/cos table from math.mcrs — @require_on_load(_math_init) is
169
+ // automatically pulled in because this function calls sin_fixed/cos_fixed.
170
+ // rotate2d_x(1000, 0, 90) == 0 (unit vector east, rotated 90° = north)
171
+ // rotate2d_x(1000, 0, 45) == 707 (cos 45° × 1000)
172
+ fn rotate2d_x(x: int, y: int, deg: int) -> int {
173
+ // x' = x*cos(deg) - y*sin(deg) (all in fixed-point, /1000 via mulfix)
174
+ return mulfix(x, cos_fixed(deg)) - mulfix(y, sin_fixed(deg));
175
+ }
176
+
177
+ // Rotate a 2D vector (x, y) by deg degrees, return the new Y component.
178
+ // rotate2d_y(1000, 0, 90) == 1000 (unit vector east, rotated 90° = north)
179
+ fn rotate2d_y(x: int, y: int, deg: int) -> int {
180
+ // y' = x*sin(deg) + y*cos(deg)
181
+ return mulfix(x, sin_fixed(deg)) + mulfix(y, cos_fixed(deg));
182
+ }
183
+
184
+ // ─── Phase 3: 3D geometry ────────────────────────────────────────────────────
185
+
186
+ // Dot product of two 3D integer vectors.
187
+ fn dot3d(ax: int, ay: int, az: int, bx: int, by: int, bz: int) -> int {
188
+ return ax * bx + ay * by + az * bz;
189
+ }
190
+
191
+ // Cross product X component: ay*bz − az*by
192
+ fn cross3d_x(ax: int, ay: int, az: int, bx: int, by: int, bz: int) -> int {
193
+ return ay * bz - az * by;
194
+ }
195
+
196
+ // Cross product Y component: az*bx − ax*bz
197
+ fn cross3d_y(ax: int, ay: int, az: int, bx: int, by: int, bz: int) -> int {
198
+ return az * bx - ax * bz;
199
+ }
200
+
201
+ // Cross product Z component: ax*by − ay*bx
202
+ fn cross3d_z(ax: int, ay: int, az: int, bx: int, by: int, bz: int) -> int {
203
+ return ax * by - ay * bx;
204
+ }
205
+
206
+ // Euclidean length of a 3D integer vector, result in fixed-point (×1000).
207
+ // length3d_fixed(1, 1, 1) == 1732 (√3 × 1000)
208
+ // Note: |x|, |y|, |z| ≤ ~800 to keep x²+y²+z² ≤ ~2,000,000 (safe for *1000).
209
+ fn length3d_fixed(x: int, y: int, z: int) -> int {
210
+ return sqrt_fixed((x * x + y * y + z * z) * 1000);
211
+ }
212
+
213
+ // Euclidean distance between two 3D integer points, result ×1000.
214
+ fn distance3d_fixed(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int) -> int {
215
+ let dx: int = x1 - x2;
216
+ let dy: int = y1 - y2;
217
+ let dz: int = z1 - z2;
218
+ return length3d_fixed(dx, dy, dz);
219
+ }
220
+
221
+ // Manhattan distance in 3D.
222
+ // manhattan3d(0,0,0, 1,2,3) == 6
223
+ fn manhattan3d(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int) -> int {
224
+ let dx: int = x1 - x2;
225
+ let dy: int = y1 - y2;
226
+ let dz: int = z1 - z2;
227
+ if (dx < 0) { dx = 0 - dx; }
228
+ if (dy < 0) { dy = 0 - dy; }
229
+ if (dz < 0) { dz = 0 - dz; }
230
+ return dx + dy + dz;
231
+ }
232
+
233
+ // Chebyshev distance in 3D.
234
+ // chebyshev3d(0,0,0, 3,1,2) == 3
235
+ fn chebyshev3d(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int) -> int {
236
+ let dx: int = x1 - x2;
237
+ let dy: int = y1 - y2;
238
+ let dz: int = z1 - z2;
239
+ if (dx < 0) { dx = 0 - dx; }
240
+ if (dy < 0) { dy = 0 - dy; }
241
+ if (dz < 0) { dz = 0 - dz; }
242
+ let m: int = dx;
243
+ if (dy > m) { m = dy; }
244
+ if (dz > m) { m = dz; }
245
+ return m;
246
+ }