@v12-engine/engine 0.1.1 → 0.4.0

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 (951) hide show
  1. package/dist/abilities/amounts.d.ts +28 -0
  2. package/dist/abilities/amounts.js +74 -0
  3. package/dist/abilities/amounts.js.map +1 -0
  4. package/dist/abilities/buffs.d.ts +106 -6
  5. package/dist/abilities/buffs.js +443 -0
  6. package/dist/abilities/buffs.js.map +1 -0
  7. package/dist/abilities/castTold.d.ts +2 -0
  8. package/dist/abilities/castTold.js +66 -0
  9. package/dist/abilities/castTold.js.map +1 -0
  10. package/dist/abilities/chance.d.ts +38 -0
  11. package/dist/abilities/chance.js +77 -0
  12. package/dist/abilities/chance.js.map +1 -0
  13. package/dist/abilities/charges.d.ts +18 -0
  14. package/dist/abilities/charges.js +101 -0
  15. package/dist/abilities/charges.js.map +1 -0
  16. package/dist/abilities/control.d.ts +28 -0
  17. package/dist/abilities/control.js +113 -0
  18. package/dist/abilities/control.js.map +1 -0
  19. package/dist/abilities/dispel.js +51 -0
  20. package/dist/abilities/dispel.js.map +1 -0
  21. package/dist/abilities/effectFields.d.ts +1 -1
  22. package/dist/abilities/effectFields.js +676 -0
  23. package/dist/abilities/effectFields.js.map +1 -0
  24. package/dist/abilities/effectIndex.d.ts +27 -0
  25. package/dist/abilities/effectIndex.js +64 -0
  26. package/dist/abilities/effectIndex.js.map +1 -0
  27. package/dist/abilities/effects/buff.d.ts +9 -3
  28. package/dist/abilities/effects/buff.js +84 -0
  29. package/dist/abilities/effects/buff.js.map +1 -0
  30. package/dist/abilities/effects/conditions.d.ts +2 -0
  31. package/dist/abilities/effects/conditions.js +41 -0
  32. package/dist/abilities/effects/conditions.js.map +1 -0
  33. package/dist/abilities/effects/core.js +54 -0
  34. package/dist/abilities/effects/core.js.map +1 -0
  35. package/dist/abilities/effects/damage.d.ts +1 -1
  36. package/dist/abilities/effects/damage.js +43 -0
  37. package/dist/abilities/effects/damage.js.map +1 -0
  38. package/dist/abilities/effects/heal.d.ts +2 -2
  39. package/dist/abilities/effects/heal.js +51 -0
  40. package/dist/abilities/effects/heal.js.map +1 -0
  41. package/dist/abilities/effects/missile.d.ts +13 -1
  42. package/dist/abilities/effects/missile.js +104 -0
  43. package/dist/abilities/effects/missile.js.map +1 -0
  44. package/dist/abilities/effects/morph.d.ts +5 -0
  45. package/dist/abilities/effects/morph.js +43 -0
  46. package/dist/abilities/effects/morph.js.map +1 -0
  47. package/dist/abilities/effects/moves.d.ts +16 -4
  48. package/dist/abilities/effects/moves.js +212 -0
  49. package/dist/abilities/effects/moves.js.map +1 -0
  50. package/dist/abilities/effects/passives.d.ts +19 -9
  51. package/dist/abilities/effects/passives.js +131 -0
  52. package/dist/abilities/effects/passives.js.map +1 -0
  53. package/dist/abilities/effects/proxy.d.ts +5 -0
  54. package/dist/abilities/effects/proxy.js +60 -0
  55. package/dist/abilities/effects/proxy.js.map +1 -0
  56. package/dist/abilities/effects/sight.d.ts +2 -2
  57. package/dist/abilities/effects/sight.js +39 -0
  58. package/dist/abilities/effects/sight.js.map +1 -0
  59. package/dist/abilities/effects/spawn.d.ts +5 -2
  60. package/dist/abilities/effects/spawn.js +40 -0
  61. package/dist/abilities/effects/spawn.js.map +1 -0
  62. package/dist/abilities/effects/timed.d.ts +2 -2
  63. package/dist/abilities/effects/timed.js +96 -0
  64. package/dist/abilities/effects/timed.js.map +1 -0
  65. package/dist/abilities/effects/trade.d.ts +1 -1
  66. package/dist/abilities/effects/trade.js +25 -0
  67. package/dist/abilities/effects/trade.js.map +1 -0
  68. package/dist/abilities/effects.d.ts +97 -23
  69. package/dist/abilities/effects.js +860 -0
  70. package/dist/abilities/effects.js.map +1 -0
  71. package/dist/abilities/land.d.ts +38 -4
  72. package/dist/abilities/land.js +189 -0
  73. package/dist/abilities/land.js.map +1 -0
  74. package/dist/abilities/recast.d.ts +45 -0
  75. package/dist/abilities/recast.js +118 -0
  76. package/dist/abilities/recast.js.map +1 -0
  77. package/dist/abilities/scaled.js +40 -0
  78. package/dist/abilities/scaled.js.map +1 -0
  79. package/dist/abilities/screen.d.ts +6 -0
  80. package/dist/abilities/screen.js +83 -0
  81. package/dist/abilities/screen.js.map +1 -0
  82. package/dist/abilities/shapes.d.ts +66 -0
  83. package/dist/abilities/shapes.js +122 -0
  84. package/dist/abilities/shapes.js.map +1 -0
  85. package/dist/abilities/text.d.ts +14 -2
  86. package/dist/abilities/text.js +204 -0
  87. package/dist/abilities/text.js.map +1 -0
  88. package/dist/abilities/triggers.d.ts +98 -0
  89. package/dist/abilities/triggers.js +351 -0
  90. package/dist/abilities/triggers.js.map +1 -0
  91. package/dist/abilityChanges.d.ts +131 -0
  92. package/dist/abilityChanges.js +345 -0
  93. package/dist/abilityChanges.js.map +1 -0
  94. package/dist/ai/area.d.ts +4 -1
  95. package/dist/ai/brain.d.ts +4 -1
  96. package/dist/ai/brain.js +844 -0
  97. package/dist/ai/brain.js.map +1 -0
  98. package/dist/ai/budget.js +74 -0
  99. package/dist/ai/budget.js.map +1 -0
  100. package/dist/ai/checks.d.ts +9 -1
  101. package/dist/ai/checks.js +242 -0
  102. package/dist/ai/checks.js.map +1 -0
  103. package/dist/ai/computer.d.ts +11 -4
  104. package/dist/ai/computer.js +251 -0
  105. package/dist/ai/computer.js.map +1 -0
  106. package/dist/ai/defence.d.ts +4 -0
  107. package/dist/ai/defence.js +430 -0
  108. package/dist/ai/defence.js.map +1 -0
  109. package/dist/ai/define.d.ts +3 -2
  110. package/dist/ai/define.js +31 -0
  111. package/dist/ai/define.js.map +1 -0
  112. package/dist/ai/economy.d.ts +10 -7
  113. package/dist/ai/economy.js +780 -0
  114. package/dist/ai/economy.js.map +1 -0
  115. package/dist/ai/geometry.js +38 -0
  116. package/dist/ai/geometry.js.map +1 -0
  117. package/dist/ai/goals.d.ts +1 -0
  118. package/dist/ai/goals.js +560 -0
  119. package/dist/ai/goals.js.map +1 -0
  120. package/dist/ai/knowledge.d.ts +72 -7
  121. package/dist/ai/knowledge.js +804 -0
  122. package/dist/ai/knowledge.js.map +1 -0
  123. package/dist/ai/lanes.d.ts +10 -2
  124. package/dist/ai/lanes.js +715 -0
  125. package/dist/ai/lanes.js.map +1 -0
  126. package/dist/ai/melee/build.js +264 -0
  127. package/dist/ai/melee/build.js.map +1 -0
  128. package/dist/ai/melee/goals.d.ts +7 -0
  129. package/dist/ai/melee/goals.js +720 -0
  130. package/dist/ai/melee/goals.js.map +1 -0
  131. package/dist/ai/melee/heroes.js +68 -0
  132. package/dist/ai/melee/heroes.js.map +1 -0
  133. package/dist/ai/melee/index.d.ts +1 -1
  134. package/dist/ai/melee/index.js +51 -0
  135. package/dist/ai/melee/index.js.map +1 -0
  136. package/dist/ai/melee/production.js +29 -0
  137. package/dist/ai/melee/production.js.map +1 -0
  138. package/dist/ai/melee/surrender.js +64 -0
  139. package/dist/ai/melee/surrender.js.map +1 -0
  140. package/dist/ai/micro.d.ts +9 -0
  141. package/dist/ai/micro.js +1316 -0
  142. package/dist/ai/micro.js.map +1 -0
  143. package/dist/ai/mission.d.ts +9 -2
  144. package/dist/ai/mission.js +538 -0
  145. package/dist/ai/mission.js.map +1 -0
  146. package/dist/ai/missionRules.d.ts +1 -1
  147. package/dist/ai/missionRules.js +26 -0
  148. package/dist/ai/missionRules.js.map +1 -0
  149. package/dist/ai/module.d.ts +6 -2
  150. package/dist/ai/module.js +37 -0
  151. package/dist/ai/module.js.map +1 -0
  152. package/dist/ai/options.d.ts +3 -3
  153. package/dist/ai/plans/build.d.ts +20 -1
  154. package/dist/ai/plans/build.js +608 -0
  155. package/dist/ai/plans/build.js.map +1 -0
  156. package/dist/ai/plans/placement.d.ts +4 -1
  157. package/dist/ai/plans/placement.js +295 -0
  158. package/dist/ai/plans/placement.js.map +1 -0
  159. package/dist/ai/plans/plans.d.ts +9 -0
  160. package/dist/ai/plans/plans.js +110 -0
  161. package/dist/ai/plans/plans.js.map +1 -0
  162. package/dist/ai/plans/production.d.ts +14 -2
  163. package/dist/ai/plans/production.js +434 -0
  164. package/dist/ai/plans/production.js.map +1 -0
  165. package/dist/ai/plans/purse.d.ts +6 -3
  166. package/dist/ai/plans/purse.js +139 -0
  167. package/dist/ai/plans/purse.js.map +1 -0
  168. package/dist/ai/plans/tech.d.ts +6 -0
  169. package/dist/ai/plans/tech.js +122 -0
  170. package/dist/ai/plans/tech.js.map +1 -0
  171. package/dist/ai/profiles.d.ts +4 -4
  172. package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
  173. package/dist/ai/profiles.js.map +1 -0
  174. package/dist/ai/reach.js +54 -0
  175. package/dist/ai/reach.js.map +1 -0
  176. package/dist/ai/report.d.ts +8 -0
  177. package/dist/ai/report.js +87 -0
  178. package/dist/ai/report.js.map +1 -0
  179. package/dist/ai/roles.d.ts +4 -0
  180. package/dist/ai/roles.js +207 -0
  181. package/dist/ai/roles.js.map +1 -0
  182. package/dist/ai/rules.d.ts +8 -2
  183. package/dist/ai/rules.js +416 -0
  184. package/dist/ai/rules.js.map +1 -0
  185. package/dist/ai/scouting.d.ts +6 -0
  186. package/dist/ai/scouting.js +324 -0
  187. package/dist/ai/scouting.js.map +1 -0
  188. package/dist/ai/settings.js +99 -0
  189. package/dist/ai/settings.js.map +1 -0
  190. package/dist/ai/squads.d.ts +21 -2
  191. package/dist/ai/squads.js +916 -0
  192. package/dist/ai/squads.js.map +1 -0
  193. package/dist/ai/strength.js +320 -0
  194. package/dist/ai/strength.js.map +1 -0
  195. package/dist/ai/task.d.ts +3 -1
  196. package/dist/ai/task.js +17 -0
  197. package/dist/ai/task.js.map +1 -0
  198. package/dist/ai/tasks/attack.js +24 -0
  199. package/dist/ai/tasks/attack.js.map +1 -0
  200. package/dist/ai/tasks/capture.d.ts +3 -3
  201. package/dist/ai/tasks/capture.js +37 -0
  202. package/dist/ai/tasks/capture.js.map +1 -0
  203. package/dist/ai/tasks/creep.js +29 -0
  204. package/dist/ai/tasks/creep.js.map +1 -0
  205. package/dist/ai/tasks/defend.js +61 -0
  206. package/dist/ai/tasks/defend.js.map +1 -0
  207. package/dist/ai/tasks/drop.js +81 -0
  208. package/dist/ai/tasks/drop.js.map +1 -0
  209. package/dist/ai/tasks/escort.js +59 -0
  210. package/dist/ai/tasks/escort.js.map +1 -0
  211. package/dist/ai/tasks/gather.js +48 -0
  212. package/dist/ai/tasks/gather.js.map +1 -0
  213. package/dist/ai/tasks/harass.js +39 -0
  214. package/dist/ai/tasks/harass.js.map +1 -0
  215. package/dist/ai/tasks/hold.js +32 -0
  216. package/dist/ai/tasks/hold.js.map +1 -0
  217. package/dist/ai/tasks/index.js +34 -0
  218. package/dist/ai/tasks/index.js.map +1 -0
  219. package/dist/ai/tasks/move.js +26 -0
  220. package/dist/ai/tasks/move.js.map +1 -0
  221. package/dist/ai/tasks/patrol.js +59 -0
  222. package/dist/ai/tasks/patrol.js.map +1 -0
  223. package/dist/ai/tasks/retreat.js +28 -0
  224. package/dist/ai/tasks/retreat.js.map +1 -0
  225. package/dist/ai/tasks/scout.js +73 -0
  226. package/dist/ai/tasks/scout.js.map +1 -0
  227. package/dist/ai/tasks/shared.d.ts +1 -1
  228. package/dist/ai/tasks/shared.js +137 -0
  229. package/dist/ai/tasks/shared.js.map +1 -0
  230. package/dist/ai/team.d.ts +18 -1
  231. package/dist/ai/team.js +492 -0
  232. package/dist/ai/team.js.map +1 -0
  233. package/dist/ai/threat.d.ts +6 -0
  234. package/dist/ai/threat.js +206 -0
  235. package/dist/ai/threat.js.map +1 -0
  236. package/dist/ai/view.d.ts +21 -7
  237. package/dist/ai/view.js +677 -0
  238. package/dist/ai/view.js.map +1 -0
  239. package/dist/ai/waves.d.ts +6 -0
  240. package/dist/ai/waves.js +410 -0
  241. package/dist/ai/waves.js.map +1 -0
  242. package/dist/ai.js +54 -6239
  243. package/dist/aiTesting.d.ts +6 -3
  244. package/dist/aiTesting.js +229 -0
  245. package/dist/aiTesting.js.map +1 -0
  246. package/dist/areas.d.ts +4 -1
  247. package/dist/areas.js +295 -0
  248. package/dist/areas.js.map +1 -0
  249. package/dist/attacks.d.ts +3 -3
  250. package/dist/attacks.js +127 -0
  251. package/dist/attacks.js.map +1 -0
  252. package/dist/burning.d.ts +267 -0
  253. package/dist/burning.js +795 -0
  254. package/dist/burning.js.map +1 -0
  255. package/dist/bytes.js +21 -0
  256. package/dist/bytes.js.map +1 -0
  257. package/dist/callings.d.ts +71 -0
  258. package/dist/callings.js +157 -0
  259. package/dist/callings.js.map +1 -0
  260. package/dist/cameraOrders.d.ts +78 -0
  261. package/dist/cameraOrders.js +114 -0
  262. package/dist/cameraOrders.js.map +1 -0
  263. package/dist/camps.d.ts +70 -4
  264. package/dist/camps.js +501 -0
  265. package/dist/camps.js.map +1 -0
  266. package/dist/capture.d.ts +15 -3
  267. package/dist/capture.js +304 -0
  268. package/dist/capture.js.map +1 -0
  269. package/dist/cellLayers.d.ts +78 -13
  270. package/dist/cellLayers.js +275 -0
  271. package/dist/cellLayers.js.map +1 -0
  272. package/dist/cellPatches.d.ts +24 -0
  273. package/dist/cellPatches.js +73 -0
  274. package/dist/cellPatches.js.map +1 -0
  275. package/dist/cinematics.d.ts +10 -5
  276. package/dist/cinematics.js +161 -0
  277. package/dist/cinematics.js.map +1 -0
  278. package/dist/clock.d.ts +2 -2
  279. package/dist/clock.js +78 -0
  280. package/dist/clock.js.map +1 -0
  281. package/dist/commands.d.ts +36 -4
  282. package/dist/commands.js +636 -0
  283. package/dist/commands.js.map +1 -0
  284. package/dist/components.d.ts +31 -10
  285. package/dist/components.js +74 -0
  286. package/dist/components.js.map +1 -0
  287. package/dist/computers.d.ts +4 -4
  288. package/dist/computers.js +194 -0
  289. package/dist/computers.js.map +1 -0
  290. package/dist/concealment.d.ts +25 -2
  291. package/dist/concealment.js +409 -0
  292. package/dist/concealment.js.map +1 -0
  293. package/dist/coreComponents.js +130 -0
  294. package/dist/coreComponents.js.map +1 -0
  295. package/dist/createGame.d.ts +306 -0
  296. package/dist/createGame.js +405 -0
  297. package/dist/createGame.js.map +1 -0
  298. package/dist/dashing.d.ts +18 -2
  299. package/dist/dashing.js +41 -0
  300. package/dist/dashing.js.map +1 -0
  301. package/dist/debug.d.ts +8 -0
  302. package/dist/debug.js +5 -3
  303. package/dist/debug2.js +76 -0
  304. package/dist/debug2.js.map +1 -0
  305. package/dist/debugCommands.d.ts +6 -6
  306. package/dist/debugCommands.js +537 -0
  307. package/dist/debugCommands.js.map +1 -0
  308. package/dist/debugging.d.ts +1 -0
  309. package/dist/defaultSets.d.ts +183 -0
  310. package/dist/defaultSets.js +216 -0
  311. package/dist/defaultSets.js.map +1 -0
  312. package/dist/definitions.d.ts +6 -0
  313. package/dist/definitions.js +78 -0
  314. package/dist/definitions.js.map +1 -0
  315. package/dist/defs.d.ts +1895 -165
  316. package/dist/defs.js +380 -0
  317. package/dist/defs.js.map +1 -0
  318. package/dist/denying.d.ts +4 -4
  319. package/dist/denying.js +106 -0
  320. package/dist/denying.js.map +1 -0
  321. package/dist/destructibles.d.ts +2 -2
  322. package/dist/destructibles.js +36 -0
  323. package/dist/destructibles.js.map +1 -0
  324. package/dist/determinism.d.ts +4 -4
  325. package/dist/determinism.js +247 -0
  326. package/dist/determinism.js.map +1 -0
  327. package/dist/dialog.d.ts +17 -2
  328. package/dist/dialog.js +108 -0
  329. package/dist/dialog.js.map +1 -0
  330. package/dist/effectRefs.js +28 -0
  331. package/dist/effectRefs.js.map +1 -0
  332. package/dist/effects.d.ts +27 -11
  333. package/dist/effects.js +110 -0
  334. package/dist/effects.js.map +1 -0
  335. package/dist/endings.d.ts +1 -1
  336. package/dist/endings.js +78 -0
  337. package/dist/endings.js.map +1 -0
  338. package/dist/engagement.d.ts +40 -6
  339. package/dist/engagement.js +530 -0
  340. package/dist/engagement.js.map +1 -0
  341. package/dist/engineEvents.d.ts +72 -9
  342. package/dist/engineEvents.js +520 -0
  343. package/dist/engineEvents.js.map +1 -0
  344. package/dist/entity.d.ts +275 -26
  345. package/dist/entity.js +441 -0
  346. package/dist/entity.js.map +1 -0
  347. package/dist/entityIndex.d.ts +10 -3
  348. package/dist/entityIndex.js +149 -0
  349. package/dist/entityIndex.js.map +1 -0
  350. package/dist/errors.d.ts +6 -2
  351. package/dist/errors.js +59 -0
  352. package/dist/errors.js.map +1 -0
  353. package/dist/events.d.ts +11 -5
  354. package/dist/events.js +158 -0
  355. package/dist/events.js.map +1 -0
  356. package/dist/exactMath.js +273 -0
  357. package/dist/exactMath.js.map +1 -0
  358. package/dist/features.d.ts +1 -1
  359. package/dist/features.js +127 -0
  360. package/dist/features.js.map +1 -0
  361. package/dist/fields.d.ts +25 -5
  362. package/dist/fields.js +140 -0
  363. package/dist/fields.js.map +1 -0
  364. package/dist/fixture.d.ts +3 -3
  365. package/dist/fixture.js +512 -0
  366. package/dist/fixture.js.map +1 -0
  367. package/dist/fog.d.ts +26 -3
  368. package/dist/fog.js +333 -0
  369. package/dist/fog.js.map +1 -0
  370. package/dist/foliage.d.ts +476 -0
  371. package/dist/foliage.js +1478 -0
  372. package/dist/foliage.js.map +1 -0
  373. package/dist/foliageDebug.d.ts +57 -0
  374. package/dist/foliageDebug.js +172 -0
  375. package/dist/foliageDebug.js.map +1 -0
  376. package/dist/foliageRegrowth.d.ts +20 -0
  377. package/dist/foliageRegrowth.js +332 -0
  378. package/dist/foliageRegrowth.js.map +1 -0
  379. package/dist/formState.d.ts +67 -0
  380. package/dist/formState.js +65 -0
  381. package/dist/formState.js.map +1 -0
  382. package/dist/formation.d.ts +46 -8
  383. package/dist/formation.js +297 -0
  384. package/dist/formation.js.map +1 -0
  385. package/dist/forms.d.ts +58 -0
  386. package/dist/forms.js +146 -0
  387. package/dist/forms.js.map +1 -0
  388. package/dist/friendlyFire.d.ts +2 -2
  389. package/dist/friendlyFire.js +37 -0
  390. package/dist/friendlyFire.js.map +1 -0
  391. package/dist/game.d.ts +141 -48
  392. package/dist/game.js +834 -0
  393. package/dist/game.js.map +1 -0
  394. package/dist/gameData.d.ts +96 -22
  395. package/dist/gameData.js +1690 -0
  396. package/dist/gameData.js.map +1 -0
  397. package/dist/gameFiles.d.ts +3 -3
  398. package/dist/gameFiles.js +14 -0
  399. package/dist/gameFiles.js.map +1 -0
  400. package/dist/gates.js +92 -0
  401. package/dist/gates.js.map +1 -0
  402. package/dist/generate.d.ts +28 -1
  403. package/dist/generate.js +1062 -0
  404. package/dist/generate.js.map +1 -0
  405. package/dist/generateWorker.d.ts +7 -3
  406. package/dist/generateWorker.js +86 -0
  407. package/dist/generateWorker.js.map +1 -0
  408. package/dist/grid.d.ts +9 -0
  409. package/dist/grid.js +102 -0
  410. package/dist/grid.js.map +1 -0
  411. package/dist/ground.d.ts +17 -1
  412. package/dist/ground.js +375 -0
  413. package/dist/ground.js.map +1 -0
  414. package/dist/groundObjects.d.ts +70 -0
  415. package/dist/groundObjects.js +371 -0
  416. package/dist/groundObjects.js.map +1 -0
  417. package/dist/groundSpeed.d.ts +20 -3
  418. package/dist/groundSpeed.js +117 -0
  419. package/dist/groundSpeed.js.map +1 -0
  420. package/dist/hero.d.ts +126 -10
  421. package/dist/hero.js +432 -0
  422. package/dist/hero.js.map +1 -0
  423. package/dist/holds.d.ts +94 -0
  424. package/dist/holds.js +305 -0
  425. package/dist/holds.js.map +1 -0
  426. package/dist/home.d.ts +1 -1
  427. package/dist/home.js +30 -0
  428. package/dist/home.js.map +1 -0
  429. package/dist/hooks.d.ts +339 -57
  430. package/dist/hooks.js +105 -0
  431. package/dist/hooks.js.map +1 -0
  432. package/dist/hotReload.d.ts +6 -5
  433. package/dist/hotReload.js +145 -0
  434. package/dist/hotReload.js.map +1 -0
  435. package/dist/ids.d.ts +3 -3
  436. package/dist/ids.js +30 -0
  437. package/dist/ids.js.map +1 -0
  438. package/dist/idsFile.d.ts +36 -0
  439. package/dist/idsFile.js +134 -0
  440. package/dist/idsFile.js.map +1 -0
  441. package/dist/index.d.ts +105 -68
  442. package/dist/index.js +194 -4701
  443. package/dist/inspect.d.ts +29 -2
  444. package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
  445. package/dist/inspect.js.map +1 -0
  446. package/dist/inventory.d.ts +14 -1
  447. package/dist/inventory.js +84 -0
  448. package/dist/inventory.js.map +1 -0
  449. package/dist/items.d.ts +136 -8
  450. package/dist/items.js +585 -0
  451. package/dist/items.js.map +1 -0
  452. package/dist/lanes.d.ts +12 -3
  453. package/dist/lanes.js +496 -0
  454. package/dist/lanes.js.map +1 -0
  455. package/dist/life.d.ts +6 -2
  456. package/dist/life.js +287 -0
  457. package/dist/life.js.map +1 -0
  458. package/dist/log.d.ts +26 -3
  459. package/dist/log.js +192 -0
  460. package/dist/log.js.map +1 -0
  461. package/dist/manaBurn.d.ts +2 -2
  462. package/dist/manaBurn.js +75 -0
  463. package/dist/manaBurn.js.map +1 -0
  464. package/dist/map/file.d.ts +56 -3
  465. package/dist/map/file.js +264 -0
  466. package/dist/map/file.js.map +1 -0
  467. package/dist/map/images.js +61 -0
  468. package/dist/map/images.js.map +1 -0
  469. package/dist/map/look.d.ts +1 -1
  470. package/dist/map/look.js +30 -0
  471. package/dist/map/look.js.map +1 -0
  472. package/dist/map/pathProfile.js +183 -0
  473. package/dist/map/pathProfile.js.map +1 -0
  474. package/dist/map/resize.d.ts +4 -0
  475. package/dist/map/resize.js +136 -0
  476. package/dist/map/resize.js.map +1 -0
  477. package/dist/map/schema.js +257 -0
  478. package/dist/map/schema.js.map +1 -0
  479. package/dist/map/terrain.js +214 -0
  480. package/dist/map/terrain.js.map +1 -0
  481. package/dist/map/types.d.ts +92 -13
  482. package/dist/map/types.js +251 -0
  483. package/dist/map/types.js.map +1 -0
  484. package/dist/mapCheck/cells.js +94 -0
  485. package/dist/mapCheck/cells.js.map +1 -0
  486. package/dist/mapCheck/rules/foliage.d.ts +9 -0
  487. package/dist/mapCheck/rules/foliage.js +83 -0
  488. package/dist/mapCheck/rules/foliage.js.map +1 -0
  489. package/dist/mapCheck/rules/names.js +39 -0
  490. package/dist/mapCheck/rules/names.js.map +1 -0
  491. package/dist/mapCheck/rules/objects.d.ts +1 -1
  492. package/dist/mapCheck/rules/objects.js +56 -0
  493. package/dist/mapCheck/rules/objects.js.map +1 -0
  494. package/dist/mapCheck/rules/paths.js +32 -0
  495. package/dist/mapCheck/rules/paths.js.map +1 -0
  496. package/dist/mapCheck/rules/players.js +20 -0
  497. package/dist/mapCheck/rules/players.js.map +1 -0
  498. package/dist/mapCheck/rules/races.js +56 -0
  499. package/dist/mapCheck/rules/races.js.map +1 -0
  500. package/dist/mapCheck/rules/random.js +47 -0
  501. package/dist/mapCheck/rules/random.js.map +1 -0
  502. package/dist/mapCheck/rules/regions.js +30 -0
  503. package/dist/mapCheck/rules/regions.js.map +1 -0
  504. package/dist/mapCheck/rules/targets.js +31 -0
  505. package/dist/mapCheck/rules/targets.js.map +1 -0
  506. package/dist/mapCheck/rules/walking.js +45 -0
  507. package/dist/mapCheck/rules/walking.js.map +1 -0
  508. package/dist/mapCheck.d.ts +2 -2
  509. package/dist/mapCheck.js +63 -0
  510. package/dist/mapCheck.js.map +1 -0
  511. package/dist/mapFields.d.ts +25 -2
  512. package/dist/mapFields.js +134 -0
  513. package/dist/mapFields.js.map +1 -0
  514. package/dist/mapFile.js +176 -0
  515. package/dist/mapFile.js.map +1 -0
  516. package/dist/mapMeasure.d.ts +8 -0
  517. package/dist/mapMeasure.js +283 -0
  518. package/dist/mapMeasure.js.map +1 -0
  519. package/dist/mapMerge.d.ts +1 -0
  520. package/dist/mapMerge.js +172 -0
  521. package/dist/mapMerge.js.map +1 -0
  522. package/dist/mapObjectives.js +138 -0
  523. package/dist/mapObjectives.js.map +1 -0
  524. package/dist/mapObjects.js +80 -0
  525. package/dist/mapObjects.js.map +1 -0
  526. package/dist/math.d.ts +37 -7
  527. package/dist/math.js +155 -0
  528. package/dist/math.js.map +1 -0
  529. package/dist/messages.d.ts +71 -4
  530. package/dist/messages.js +29 -0
  531. package/dist/messages.js.map +1 -0
  532. package/dist/missionRules.d.ts +10 -2
  533. package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
  534. package/dist/missionRules.js.map +1 -0
  535. package/dist/mods.d.ts +39 -20
  536. package/dist/mods.js +271 -0
  537. package/dist/mods.js.map +1 -0
  538. package/dist/moves.d.ts +87 -0
  539. package/dist/moves.js +539 -0
  540. package/dist/moves.js.map +1 -0
  541. package/dist/names.d.ts +7 -0
  542. package/dist/names.js +122 -0
  543. package/dist/names.js.map +1 -0
  544. package/dist/navigation/agentParams.js +14 -0
  545. package/dist/navigation/agentParams.js.map +1 -0
  546. package/dist/navigation/air.d.ts +7 -3
  547. package/dist/navigation/air.js +401 -0
  548. package/dist/navigation/air.js.map +1 -0
  549. package/dist/navigation/builds.d.ts +34 -2
  550. package/dist/navigation/builds.js +287 -0
  551. package/dist/navigation/builds.js.map +1 -0
  552. package/dist/navigation/groundAreas.d.ts +59 -1
  553. package/dist/navigation/groundAreas.js +407 -0
  554. package/dist/navigation/groundAreas.js.map +1 -0
  555. package/dist/navigation/navigation.d.ts +98 -9
  556. package/dist/navigation/recast.d.ts +194 -18
  557. package/dist/navigation/recast.js +1379 -0
  558. package/dist/navigation/recast.js.map +1 -0
  559. package/dist/navigation/sidePaths.d.ts +8 -3
  560. package/dist/navigation/sidePaths.js +241 -0
  561. package/dist/navigation/sidePaths.js.map +1 -0
  562. package/dist/navigation/sized.js +243 -0
  563. package/dist/navigation/sized.js.map +1 -0
  564. package/dist/nearest.js +32 -0
  565. package/dist/nearest.js.map +1 -0
  566. package/dist/noise.js +59 -0
  567. package/dist/noise.js.map +1 -0
  568. package/dist/objectives.d.ts +12 -3
  569. package/dist/objectives.js +144 -0
  570. package/dist/objectives.js.map +1 -0
  571. package/dist/orders/basic.d.ts +5 -5
  572. package/dist/orders/basic.js +417 -0
  573. package/dist/orders/basic.js.map +1 -0
  574. package/dist/orders/build.js +278 -0
  575. package/dist/orders/build.js.map +1 -0
  576. package/dist/orders/cast.d.ts +13 -3
  577. package/dist/orders/cast.js +558 -0
  578. package/dist/orders/cast.js.map +1 -0
  579. package/dist/orders/facts.js +16 -0
  580. package/dist/orders/facts.js.map +1 -0
  581. package/dist/orders/harvest.d.ts +21 -5
  582. package/dist/orders/harvest.js +540 -0
  583. package/dist/orders/harvest.js.map +1 -0
  584. package/dist/orders/idle.d.ts +3 -1
  585. package/dist/orders/idle.js +234 -0
  586. package/dist/orders/idle.js.map +1 -0
  587. package/dist/orders/items.js +92 -0
  588. package/dist/orders/items.js.map +1 -0
  589. package/dist/orders/queue.js +108 -0
  590. package/dist/orders/queue.js.map +1 -0
  591. package/dist/orders/waiting.d.ts +39 -0
  592. package/dist/orders/waiting.js +149 -0
  593. package/dist/orders/waiting.js.map +1 -0
  594. package/dist/pack.schema.js +13 -0
  595. package/dist/pack.schema.js.map +1 -0
  596. package/dist/pack.schema.json +7622 -841
  597. package/dist/packs/director/index.d.ts +13 -5
  598. package/dist/packs/director/index.js +204 -0
  599. package/dist/packs/director/index.js.map +1 -0
  600. package/dist/packs/heroes/campaign.d.ts +3 -2
  601. package/dist/packs/heroes/campaign.js +241 -0
  602. package/dist/packs/heroes/campaign.js.map +1 -0
  603. package/dist/packs/heroes/carry.d.ts +6 -0
  604. package/dist/packs/heroes/carry.js +112 -0
  605. package/dist/packs/heroes/carry.js.map +1 -0
  606. package/dist/packs/heroes/commands.js +115 -0
  607. package/dist/packs/heroes/commands.js.map +1 -0
  608. package/dist/packs/heroes/fallen.d.ts +43 -0
  609. package/dist/packs/heroes/fallen.js +61 -0
  610. package/dist/packs/heroes/fallen.js.map +1 -0
  611. package/dist/packs/heroes/hire.js +60 -0
  612. package/dist/packs/heroes/hire.js.map +1 -0
  613. package/dist/packs/heroes/index.d.ts +7 -6
  614. package/dist/packs/heroes/index.js +130 -0
  615. package/dist/packs/heroes/index.js.map +1 -0
  616. package/dist/packs/heroes/loop.d.ts +95 -0
  617. package/dist/packs/heroes/loop.js +250 -0
  618. package/dist/packs/heroes/loop.js.map +1 -0
  619. package/dist/packs/heroes/making.d.ts +6 -3
  620. package/dist/packs/heroes/making.js +55 -0
  621. package/dist/packs/heroes/making.js.map +1 -0
  622. package/dist/packs/heroes/respawn.d.ts +3 -3
  623. package/dist/packs/heroes/respawn.js +87 -0
  624. package/dist/packs/heroes/respawn.js.map +1 -0
  625. package/dist/packs/heroes/sets.d.ts +32 -0
  626. package/dist/packs/heroes/sets.js +51 -0
  627. package/dist/packs/heroes/sets.js.map +1 -0
  628. package/dist/packs/heroes/spells.d.ts +16 -0
  629. package/dist/packs/heroes/spells.js +269 -0
  630. package/dist/packs/heroes/spells.js.map +1 -0
  631. package/dist/packs/items/defaults.d.ts +43 -0
  632. package/dist/packs/items/defaults.js +1504 -0
  633. package/dist/packs/items/defaults.js.map +1 -0
  634. package/dist/packs/items/index.d.ts +27 -0
  635. package/dist/packs/items/index.js +214 -0
  636. package/dist/packs/items/index.js.map +1 -0
  637. package/dist/packs/moba/index.d.ts +3 -3
  638. package/dist/packs/moba/index.js +174 -0
  639. package/dist/packs/moba/index.js.map +1 -0
  640. package/dist/packs/pack.d.ts +15 -15
  641. package/dist/packs/pack.js +14 -0
  642. package/dist/packs/pack.js.map +1 -0
  643. package/dist/packs.d.ts +15 -7
  644. package/dist/packs.js +222 -0
  645. package/dist/packs.js.map +1 -0
  646. package/dist/paths.d.ts +2 -0
  647. package/dist/paths.js +109 -0
  648. package/dist/paths.js.map +1 -0
  649. package/dist/plain.js +57 -0
  650. package/dist/plain.js.map +1 -0
  651. package/dist/player.d.ts +33 -10
  652. package/dist/player.js +159 -0
  653. package/dist/player.js.map +1 -0
  654. package/dist/portals.d.ts +1 -1
  655. package/dist/portals.js +194 -0
  656. package/dist/portals.js.map +1 -0
  657. package/dist/prefabs.d.ts +25 -2
  658. package/dist/prefabs.js +239 -0
  659. package/dist/prefabs.js.map +1 -0
  660. package/dist/presetBuildings.js +58 -0
  661. package/dist/presetBuildings.js.map +1 -0
  662. package/dist/presetFoliage.d.ts +27 -0
  663. package/dist/presetFoliage.js +98 -0
  664. package/dist/presetFoliage.js.map +1 -0
  665. package/dist/presetGround.js +65 -0
  666. package/dist/presetGround.js.map +1 -0
  667. package/dist/proxies.d.ts +12 -0
  668. package/dist/proxies.js +79 -0
  669. package/dist/proxies.js.map +1 -0
  670. package/dist/query.d.ts +56 -0
  671. package/dist/query.js +88 -0
  672. package/dist/query.js.map +1 -0
  673. package/dist/races.d.ts +15 -14
  674. package/dist/races.js +172 -0
  675. package/dist/races.js.map +1 -0
  676. package/dist/randomGroups.js +91 -0
  677. package/dist/randomGroups.js.map +1 -0
  678. package/dist/registry.d.ts +117 -53
  679. package/dist/registry.js +323 -0
  680. package/dist/registry.js.map +1 -0
  681. package/dist/remains.d.ts +11 -9
  682. package/dist/remains.js +188 -0
  683. package/dist/remains.js.map +1 -0
  684. package/dist/replication.d.ts +12 -7
  685. package/dist/replication.js +100 -0
  686. package/dist/replication.js.map +1 -0
  687. package/dist/rng.d.ts +2 -0
  688. package/dist/rng.js +40 -0
  689. package/dist/rng.js.map +1 -0
  690. package/dist/rules.d.ts +186 -99
  691. package/dist/rules.js +179 -0
  692. package/dist/rules.js.map +1 -0
  693. package/dist/rulesCheck.d.ts +5 -4
  694. package/dist/rulesCheck.js +693 -0
  695. package/dist/rulesCheck.js.map +1 -0
  696. package/dist/runes.d.ts +2 -2
  697. package/dist/runes.js +80 -0
  698. package/dist/runes.js.map +1 -0
  699. package/dist/save.d.ts +37 -12
  700. package/dist/save.js +532 -0
  701. package/dist/save.js.map +1 -0
  702. package/dist/scenario.d.ts +2 -2
  703. package/dist/scenario.js +99 -0
  704. package/dist/scenario.js.map +1 -0
  705. package/dist/scheduler.d.ts +3 -0
  706. package/dist/scheduler.js +156 -0
  707. package/dist/scheduler.js.map +1 -0
  708. package/dist/score.d.ts +19 -19
  709. package/dist/score.js +709 -0
  710. package/dist/score.js.map +1 -0
  711. package/dist/sequences.d.ts +10 -6
  712. package/dist/sequences.js +206 -0
  713. package/dist/sequences.js.map +1 -0
  714. package/dist/server/doorman.js +154 -0
  715. package/dist/server/doorman.js.map +1 -0
  716. package/dist/server/gameServer.d.ts +16 -1
  717. package/dist/server/gameServer.js +643 -0
  718. package/dist/server/gameServer.js.map +1 -0
  719. package/dist/server/index.d.ts +1 -1
  720. package/dist/server/lobby.js +199 -0
  721. package/dist/server/lobby.js.map +1 -0
  722. package/dist/server/log.js +18 -0
  723. package/dist/server/log.js.map +1 -0
  724. package/dist/server/match.js +267 -0
  725. package/dist/server/match.js.map +1 -0
  726. package/dist/server/mode.d.ts +18 -9
  727. package/dist/server/mode.js +220 -0
  728. package/dist/server/mode.js.map +1 -0
  729. package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
  730. package/dist/server/navigation-worker.js.map +1 -0
  731. package/dist/server/navigation.js +39 -0
  732. package/dist/server/navigation.js.map +1 -0
  733. package/dist/server/ops.d.ts +4 -0
  734. package/dist/server/ops.js +137 -0
  735. package/dist/server/ops.js.map +1 -0
  736. package/dist/server/packs.d.ts +3 -3
  737. package/dist/server/packs.js +32 -0
  738. package/dist/server/packs.js.map +1 -0
  739. package/dist/server/ratings.d.ts +5 -0
  740. package/dist/server/ratings.js +104 -0
  741. package/dist/server/ratings.js.map +1 -0
  742. package/dist/server/relay.d.ts +12 -2
  743. package/dist/server/relay.js +144 -0
  744. package/dist/server/relay.js.map +1 -0
  745. package/dist/server/rooms.d.ts +9 -2
  746. package/dist/server/rooms.js +442 -0
  747. package/dist/server/rooms.js.map +1 -0
  748. package/dist/server/seat.js +116 -0
  749. package/dist/server/seat.js.map +1 -0
  750. package/dist/server/seatSettings.d.ts +3 -3
  751. package/dist/server/seatSettings.js +63 -0
  752. package/dist/server/seatSettings.js.map +1 -0
  753. package/dist/server/secret.js +13 -0
  754. package/dist/server/secret.js.map +1 -0
  755. package/dist/server/start.d.ts +13 -6
  756. package/dist/server/start.js +76 -0
  757. package/dist/server/start.js.map +1 -0
  758. package/dist/server/websocket.d.ts +9 -1
  759. package/dist/server/websocket.js +306 -0
  760. package/dist/server/websocket.js.map +1 -0
  761. package/dist/server.js +15 -2861
  762. package/dist/session/can.js +26 -0
  763. package/dist/session/can.js.map +1 -0
  764. package/dist/session/commandReplay.d.ts +8 -2
  765. package/dist/session/commandReplay.js +293 -0
  766. package/dist/session/commandReplay.js.map +1 -0
  767. package/dist/session/debug.js +151 -0
  768. package/dist/session/debug.js.map +1 -0
  769. package/dist/session/delay.js +62 -0
  770. package/dist/session/delay.js.map +1 -0
  771. package/dist/session/delta.d.ts +14 -1
  772. package/dist/session/delta.js +407 -0
  773. package/dist/session/delta.js.map +1 -0
  774. package/dist/session/entityState.js +415 -0
  775. package/dist/session/entityState.js.map +1 -0
  776. package/dist/session/local.d.ts +47 -5
  777. package/dist/session/local.js +670 -0
  778. package/dist/session/local.js.map +1 -0
  779. package/dist/session/memory.d.ts +20 -2
  780. package/dist/session/memory.js +131 -0
  781. package/dist/session/memory.js.map +1 -0
  782. package/dist/session/protocol.d.ts +325 -31
  783. package/dist/session/protocol.js +55 -0
  784. package/dist/session/protocol.js.map +1 -0
  785. package/dist/session/remote.d.ts +74 -12
  786. package/dist/session/remote.js +1394 -0
  787. package/dist/session/remote.js.map +1 -0
  788. package/dist/session/replay.d.ts +11 -2
  789. package/dist/session/replay.js +160 -0
  790. package/dist/session/replay.js.map +1 -0
  791. package/dist/session/seed.js +12 -0
  792. package/dist/session/seed.js.map +1 -0
  793. package/dist/session/share.d.ts +5 -1
  794. package/dist/session/share.js +94 -0
  795. package/dist/session/share.js.map +1 -0
  796. package/dist/session/socket.d.ts +1 -1
  797. package/dist/session/socket.js +29 -0
  798. package/dist/session/socket.js.map +1 -0
  799. package/dist/session/wire.d.ts +5 -0
  800. package/dist/session/wire.js +84 -0
  801. package/dist/session/wire.js.map +1 -0
  802. package/dist/session/worker.d.ts +77 -12
  803. package/dist/session/worker.js +499 -0
  804. package/dist/session/worker.js.map +1 -0
  805. package/dist/shared.d.ts +31 -5
  806. package/dist/shared.js +166 -0
  807. package/dist/shared.js.map +1 -0
  808. package/dist/sides.d.ts +9 -3
  809. package/dist/sides.js +149 -0
  810. package/dist/sides.js.map +1 -0
  811. package/dist/sight.js +85 -0
  812. package/dist/sight.js.map +1 -0
  813. package/dist/simulate-worker.js +1 -1
  814. package/dist/simulate.d.ts +12 -8
  815. package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
  816. package/dist/simulate.js.map +1 -0
  817. package/dist/smart.js +77 -0
  818. package/dist/smart.js.map +1 -0
  819. package/dist/spatial.d.ts +32 -16
  820. package/dist/spatial.js +234 -0
  821. package/dist/spatial.js.map +1 -0
  822. package/dist/spawning.d.ts +1 -0
  823. package/dist/spawning.js +224 -0
  824. package/dist/spawning.js.map +1 -0
  825. package/dist/stances.d.ts +6 -3
  826. package/dist/stances.js +169 -0
  827. package/dist/stances.js.map +1 -0
  828. package/dist/start.d.ts +10 -10
  829. package/dist/start.js +75 -0
  830. package/dist/start.js.map +1 -0
  831. package/dist/stats.d.ts +42 -16
  832. package/dist/stats.js +290 -0
  833. package/dist/stats.js.map +1 -0
  834. package/dist/summoned.d.ts +52 -0
  835. package/dist/summoned.js +38 -0
  836. package/dist/summoned.js.map +1 -0
  837. package/dist/summons.d.ts +10 -13
  838. package/dist/summons.js +271 -0
  839. package/dist/summons.js.map +1 -0
  840. package/dist/systems/abilities.js +224 -0
  841. package/dist/systems/abilities.js.map +1 -0
  842. package/dist/systems/combat.d.ts +35 -1
  843. package/dist/systems/combat.js +677 -0
  844. package/dist/systems/combat.js.map +1 -0
  845. package/dist/systems/combatTold.d.ts +3 -1
  846. package/dist/systems/combatTold.js +85 -0
  847. package/dist/systems/combatTold.js.map +1 -0
  848. package/dist/systems/construction.js +80 -0
  849. package/dist/systems/construction.js.map +1 -0
  850. package/dist/systems/economy.d.ts +0 -6
  851. package/dist/systems/economy.js +128 -0
  852. package/dist/systems/economy.js.map +1 -0
  853. package/dist/systems/fog.d.ts +1 -1
  854. package/dist/systems/fog.js +120 -0
  855. package/dist/systems/fog.js.map +1 -0
  856. package/dist/systems/life.js +32 -0
  857. package/dist/systems/life.js.map +1 -0
  858. package/dist/systems/movement.d.ts +24 -12
  859. package/dist/systems/movement.js +1247 -0
  860. package/dist/systems/movement.js.map +1 -0
  861. package/dist/systems/orders.js +64 -0
  862. package/dist/systems/orders.js.map +1 -0
  863. package/dist/systems/production.js +322 -0
  864. package/dist/systems/production.js.map +1 -0
  865. package/dist/systems/productionQueue.js +120 -0
  866. package/dist/systems/productionQueue.js.map +1 -0
  867. package/dist/systems/victory.d.ts +1 -1
  868. package/dist/systems/victory.js +56 -0
  869. package/dist/systems/victory.js.map +1 -0
  870. package/dist/talk.d.ts +6 -6
  871. package/dist/talk.js +153 -0
  872. package/dist/talk.js.map +1 -0
  873. package/dist/targeting.d.ts +142 -0
  874. package/dist/targeting.js +49 -0
  875. package/dist/targeting.js.map +1 -0
  876. package/dist/tech.d.ts +20 -3
  877. package/dist/tech.js +239 -0
  878. package/dist/tech.js.map +1 -0
  879. package/dist/techTree.d.ts +7 -0
  880. package/dist/techTree.js +90 -0
  881. package/dist/techTree.js.map +1 -0
  882. package/dist/terrain.d.ts +59 -7
  883. package/dist/terrain.js +389 -0
  884. package/dist/terrain.js.map +1 -0
  885. package/dist/terrainSave.d.ts +6 -0
  886. package/dist/terrainSave.js +74 -0
  887. package/dist/terrainSave.js.map +1 -0
  888. package/dist/testing.d.ts +8 -7
  889. package/dist/testing.js +13 -739
  890. package/dist/testing.js.map +1 -1
  891. package/dist/tiles.d.ts +1 -1
  892. package/dist/tiles.js +43 -0
  893. package/dist/tiles.js.map +1 -0
  894. package/dist/timers.d.ts +29 -4
  895. package/dist/timers.js +242 -0
  896. package/dist/timers.js.map +1 -0
  897. package/dist/tomes.d.ts +4 -4
  898. package/dist/tomes.js +94 -0
  899. package/dist/tomes.js.map +1 -0
  900. package/dist/trade.js +103 -0
  901. package/dist/trade.js.map +1 -0
  902. package/dist/transport.d.ts +6 -1
  903. package/dist/transport.js +281 -0
  904. package/dist/transport.js.map +1 -0
  905. package/dist/tunables.d.ts +10 -3
  906. package/dist/tunables.js +56 -0
  907. package/dist/tunables.js.map +1 -0
  908. package/dist/unitResources.d.ts +67 -0
  909. package/dist/unitResources.js +266 -0
  910. package/dist/unitResources.js.map +1 -0
  911. package/dist/upkeep.d.ts +6 -1
  912. package/dist/upkeep.js +26 -0
  913. package/dist/upkeep.js.map +1 -0
  914. package/dist/veterancy.d.ts +8 -3
  915. package/dist/veterancy.js +131 -0
  916. package/dist/veterancy.js.map +1 -0
  917. package/dist/vision.d.ts +36 -0
  918. package/dist/vision.js +133 -0
  919. package/dist/vision.js.map +1 -0
  920. package/dist/walls.d.ts +1 -1
  921. package/dist/walls.js +278 -0
  922. package/dist/walls.js.map +1 -0
  923. package/dist/world.d.ts +606 -88
  924. package/dist/world.js +1263 -0
  925. package/dist/world.js.map +1 -0
  926. package/package.json +2 -2
  927. package/dist/ai.js.map +0 -1
  928. package/dist/attributes.d.ts +0 -66
  929. package/dist/brain-BvVdUhX8.js +0 -7659
  930. package/dist/brain-BvVdUhX8.js.map +0 -1
  931. package/dist/builds-C6LfgvEU.js +0 -460
  932. package/dist/builds-C6LfgvEU.js.map +0 -1
  933. package/dist/coreComponents-syuh2fPG.js +0 -5149
  934. package/dist/coreComponents-syuh2fPG.js.map +0 -1
  935. package/dist/debugCommands-CzjrSm66.js +0 -14739
  936. package/dist/debugCommands-CzjrSm66.js.map +0 -1
  937. package/dist/determinism-BCymQwiE.js +0 -518
  938. package/dist/determinism-BCymQwiE.js.map +0 -1
  939. package/dist/game-DiJEN-Ks.js +0 -5800
  940. package/dist/game-DiJEN-Ks.js.map +0 -1
  941. package/dist/index.js.map +0 -1
  942. package/dist/inspect-D9dWHmZ0.js.map +0 -1
  943. package/dist/local-Dkovq42k.js +0 -1379
  944. package/dist/local-Dkovq42k.js.map +0 -1
  945. package/dist/missionRules-C-bGxm0Q.js.map +0 -1
  946. package/dist/navigation-worker.js.map +0 -1
  947. package/dist/packs-g5thvmGn.js +0 -3199
  948. package/dist/packs-g5thvmGn.js.map +0 -1
  949. package/dist/profiles-B3NS9jwk.js.map +0 -1
  950. package/dist/server.js.map +0 -1
  951. package/dist/simulate-oXBiw1Ff.js.map +0 -1
@@ -21,7 +21,7 @@ import { Brain } from './ai/brain';
21
21
  import type { GoalReport } from './ai/goals';
22
22
  import { type AiDecision, type AiReport } from './ai/report';
23
23
  import type { PlayerId } from './entity';
24
- import { type GameModule } from './game';
24
+ import { type Rules } from './game';
25
25
  import type { PlayerCommand, Snapshot } from './session/protocol';
26
26
  import type { World } from './world';
27
27
  /**
@@ -110,6 +110,7 @@ export interface FairPlay {
110
110
  readonly refused: number;
111
111
  /** Throws where it sent any command about what it did not see */
112
112
  assert(): void;
113
+ /** Stops watching the brain; the violations found so far stay */
113
114
  stop(): void;
114
115
  }
115
116
  /**
@@ -126,6 +127,7 @@ export declare function fairPlay(world: World, player: PlayerId): FairPlay;
126
127
  * @beta
127
128
  */
128
129
  export interface RecordedDecision extends AiDecision {
130
+ /** The player whose computer made the decision */
129
131
  player: PlayerId;
130
132
  /** The brain's id */
131
133
  brain: string;
@@ -139,6 +141,7 @@ export interface RecordedDecision extends AiDecision {
139
141
  export interface DecisionRecorder {
140
142
  /** Every decision so far, in the order made */
141
143
  readonly decisions: readonly RecordedDecision[];
144
+ /** Stops recording; the decisions so far stay */
142
145
  stop(): void;
143
146
  }
144
147
  /**
@@ -168,12 +171,12 @@ export interface DecisionsApart {
168
171
  * game seats them), runs it to `from`, saves it as a file would keep it and loads that with `game`, then runs both to
169
172
  * `ticks` and compares what every computer decided. What lost rng, tasks or memory in a restore shows as
170
173
  *
171
- * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, game: melee })).toBeNull()
174
+ * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, rules: melee })).toBeNull()
172
175
  *
173
176
  * @beta
174
177
  */
175
178
  export declare function checkComputerSave(make: () => World | Promise<World>, options: {
176
179
  from: number;
177
180
  ticks: number;
178
- game: GameModule;
181
+ rules: Rules;
179
182
  }): Promise<DecisionsApart | null>;
@@ -0,0 +1,229 @@
1
+ import { decodeSave, encodeSave, saveWorld } from "./save.js";
2
+ import { loadWorld } from "./game.js";
3
+ import { LocalSession } from "./session/local.js";
4
+ import { explainGoal } from "./ai/report.js";
5
+ import { checkBrain } from "./ai/checks.js";
6
+ import { Brain } from "./ai/brain.js";
7
+ //#region src/aiTesting.ts
8
+ /**
9
+ * Testing a computer player (AI plan, E3): what a game's tests of its brains are written with, in
10
+ * `@v12-engine/engine/testing` beside `testWorld` and `run`. A brain is tested as it plays, through the world it sits in:
11
+ *
12
+ * const world = await testWorld(myGame)
13
+ * world.computers.seat(ENEMY, { enemyBases: [home], brain: myBrain })
14
+ * const watch = watchComputer(world, ENEMY) // its invariants, every think
15
+ * run(world, 120)
16
+ * expectDecision(thinkOnce(world, ENEMY), 'ai.attack')
17
+ * watch.assert() // no rule broken
18
+ *
19
+ * `thinkOnce` has a seated brain think now and gives its report; `expectDecision` says a goal runs, or why not in
20
+ * words; `watchComputer` checks the invariants of `ai/checks.ts` after every think (a unit in one squad, gold spent
21
+ * once, finite numbers, commands about what it sees, no churn, nothing stuck) and keeps what it decided; `fairPlay` is
22
+ * the one about seeing; `recordDecisions` keeps every computer's decisions for a replay's side file; `checkComputerSave`
23
+ * is the seventh invariant: a game saved and loaded decides the same from then on. These take the world, which a test
24
+ * may: the brains under test never do.
25
+ */
26
+ /**
27
+ * The brain that plays a player, where one is seated (`world.computers.seat`): none where nobody is, or where what is
28
+ * seated is not a brain (`defineComputer`)
29
+ *
30
+ * @beta
31
+ */
32
+ function brainOf(world, player) {
33
+ const computer = world.computers.get(player)?.computer;
34
+ return computer instanceof Brain ? computer : void 0;
35
+ }
36
+ /** The brain at a player, or an error that says what is seated there instead */
37
+ function seated(world, player) {
38
+ const brain = brainOf(world, player);
39
+ if (brain) return brain;
40
+ const system = world.computers.get(player);
41
+ throw new Error(system ? `The computer player at ${player} is not a brain (defineBrain): it has no report` : `No computer player is seated at ${player}`);
42
+ }
43
+ /**
44
+ * Has the brain at a player think now, all of it (a think its budget slices over ticks is run to its end), over a new
45
+ * picture of the game, and gives its report: what a test reads after setting a scene. Its commands land at the next
46
+ * tick, as a think's do. A think the seat would have had is not skipped: this one is beside them
47
+ *
48
+ * @beta
49
+ */
50
+ function thinkOnce(world, player) {
51
+ const brain = seated(world, player);
52
+ do
53
+ brain.think();
54
+ while (brain.busy);
55
+ return brain.report();
56
+ }
57
+ /**
58
+ * Says that a goal runs, as of a report (`thinkOnce`, `Brain.report`): it is picked and holds what it claimed. Throws
59
+ * where it does not, with its row in words (`Brain.explain`): what each consideration answered and what kept it out.
60
+ * Gives the goal's row. With `picked: false`, says it does not run
61
+ *
62
+ * expectDecision(thinkOnce(world, ENEMY), 'ai.defend')
63
+ *
64
+ * @beta
65
+ */
66
+ function expectDecision(report, goal, options = {}) {
67
+ const wanted = options.picked ?? true;
68
+ const row = report.goals.find((each) => each.id === goal);
69
+ if (!row) throw new Error(`The brain ${report.brain} has no goal "${goal}": its goals are ${report.goals.map((each) => each.id).join(", ") || "none"}`);
70
+ if (row.picked === wanted) return row;
71
+ const seconds = (tick) => tick / report.tickRate;
72
+ throw new Error(`Expected ${goal} ${wanted ? "to run" : "not to run"} at ${report.time.toFixed(1)} s, and it ${wanted ? "does not" : "does"}. ${explainGoal(row, seconds, report.time)}${report.goal && report.goal !== goal ? ` The best goal is ${report.goal}.` : ""}`);
73
+ }
74
+ /**
75
+ * Follows the brain at a player from now on: after every think, the invariants of `ai/checks.ts` (a unit in one squad
76
+ * and one hold, gold spent once, finite numbers, commands about what it sees, no order sent again to a unit still at
77
+ * it, builders, tasks, holds and wants that end), with what it decided and sent. A broken rule is kept, not thrown,
78
+ * unless `onViolation` throws: `assert` at the end says them all
79
+ *
80
+ * @beta
81
+ */
82
+ function watchComputer(world, player, options = {}) {
83
+ const brain = seated(world, player);
84
+ const violations = [];
85
+ const decisions = [];
86
+ let thinks = 0;
87
+ let commands = 0;
88
+ const { stop: unchecked } = checkBrain(brain, {
89
+ ...options,
90
+ onViolation: (violation) => {
91
+ violations.push(violation);
92
+ options.onViolation?.(violation);
93
+ }
94
+ });
95
+ const observer = options.observe ? new LocalSession(world, player, { observer: true }) : void 0;
96
+ const unwatched = brain.watch({
97
+ sent: (command) => {
98
+ commands++;
99
+ options.sent?.(command, brain);
100
+ },
101
+ decided: (decision) => void decisions.push(decision),
102
+ thought: () => {
103
+ thinks++;
104
+ if (observer) options.observe(observer.snapshot(), brain);
105
+ }
106
+ });
107
+ return {
108
+ brain,
109
+ violations,
110
+ decisions,
111
+ get thinks() {
112
+ return thinks;
113
+ },
114
+ get commands() {
115
+ return commands;
116
+ },
117
+ assert() {
118
+ if (!violations.length) return;
119
+ const lines = violations.slice(0, 20).map((each) => ` ${each.invariant} at tick ${each.tick}: ${each.message}`);
120
+ const more = violations.length > 20 ? `\n and ${violations.length - 20} more` : "";
121
+ throw new Error(`The computer player at ${player} broke ${violations.length} rule${violations.length === 1 ? "" : "s"}:\n${lines.join("\n")}${more}`);
122
+ },
123
+ stop() {
124
+ unchecked();
125
+ unwatched();
126
+ observer?.dispose();
127
+ }
128
+ };
129
+ }
130
+ /**
131
+ * Follows the brain at a player from now on for fair play: that it never sends a command about an entity its snapshot
132
+ * did not have (a fog leak: its seat's session would drop the command, so a game shows nothing; this says it), and
133
+ * counts what the game refused
134
+ *
135
+ * @beta
136
+ */
137
+ function fairPlay(world, player) {
138
+ const watch = watchComputer(world, player, { invariants: ["commands"] });
139
+ const brain = watch.brain;
140
+ const refusedBefore = brain.stats.refused;
141
+ return {
142
+ get unfair() {
143
+ return watch.violations;
144
+ },
145
+ get refused() {
146
+ return brain.stats.refused - refusedBefore;
147
+ },
148
+ assert: () => watch.assert(),
149
+ stop: () => watch.stop()
150
+ };
151
+ }
152
+ /** How many recorders were made: each one's system a name of its own */
153
+ var recorders = 0;
154
+ /**
155
+ * Keeps the decisions of every brain seated at a world, from now on, those seated later included (looked for at each
156
+ * tick, by a system of its own that keeps nothing in a save)
157
+ *
158
+ * @beta
159
+ */
160
+ function recordDecisions(world) {
161
+ const decisions = [];
162
+ const watched = /* @__PURE__ */ new Map();
163
+ const look = () => {
164
+ for (const player of world.computers.list()) {
165
+ const brain = brainOf(world, player);
166
+ if (!brain || watched.has(brain)) continue;
167
+ watched.set(brain, brain.watch({ decided: (decision) => void decisions.push({
168
+ ...decision,
169
+ player: brain.playerId,
170
+ brain: brain.def.id
171
+ }) }));
172
+ }
173
+ };
174
+ look();
175
+ const name = `core.ai.recordDecisions.${++recorders}`;
176
+ world.addSystem({
177
+ name,
178
+ update: look
179
+ });
180
+ return {
181
+ decisions,
182
+ stop() {
183
+ world.removeSystem(name);
184
+ for (const unwatch of watched.values()) unwatch();
185
+ watched.clear();
186
+ }
187
+ };
188
+ }
189
+ /**
190
+ * The seventh invariant of a computer player: a game saved at tick `from` and loaded makes the same decisions from then
191
+ * on as the game it was saved from, under the same commands. Makes the world with `make` (its computers seated, as a
192
+ * game seats them), runs it to `from`, saves it as a file would keep it and loads that with `game`, then runs both to
193
+ * `ticks` and compares what every computer decided. What lost rng, tasks or memory in a restore shows as
194
+ *
195
+ * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, rules: melee })).toBeNull()
196
+ *
197
+ * @beta
198
+ */
199
+ async function checkComputerSave(make, options) {
200
+ const saved = await make();
201
+ let loaded;
202
+ try {
203
+ while (saved.tick < options.from) saved.step();
204
+ loaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { rules: options.rules });
205
+ const before = recordDecisions(saved);
206
+ const after = recordDecisions(loaded);
207
+ while (saved.tick < options.ticks) {
208
+ saved.step();
209
+ loaded.step();
210
+ }
211
+ before.stop();
212
+ after.stop();
213
+ const a = before.decisions;
214
+ const b = after.decisions;
215
+ for (let i = 0; i < Math.max(a.length, b.length); i++) if (JSON.stringify(a[i]) !== JSON.stringify(b[i])) return {
216
+ index: i,
217
+ ...a[i] && { saved: a[i] },
218
+ ...b[i] && { loaded: b[i] }
219
+ };
220
+ return null;
221
+ } finally {
222
+ saved.dispose();
223
+ loaded?.dispose();
224
+ }
225
+ }
226
+ //#endregion
227
+ export { brainOf, checkComputerSave, expectDecision, fairPlay, recordDecisions, thinkOnce, watchComputer };
228
+
229
+ //# sourceMappingURL=aiTesting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiTesting.js","names":[],"sources":["../src/aiTesting.ts"],"sourcesContent":["/**\n * Testing a computer player (AI plan, E3): what a game's tests of its brains are written with, in\n * `@v12-engine/engine/testing` beside `testWorld` and `run`. A brain is tested as it plays, through the world it sits in:\n *\n * const world = await testWorld(myGame)\n * world.computers.seat(ENEMY, { enemyBases: [home], brain: myBrain })\n * const watch = watchComputer(world, ENEMY) // its invariants, every think\n * run(world, 120)\n * expectDecision(thinkOnce(world, ENEMY), 'ai.attack')\n * watch.assert() // no rule broken\n *\n * `thinkOnce` has a seated brain think now and gives its report; `expectDecision` says a goal runs, or why not in\n * words; `watchComputer` checks the invariants of `ai/checks.ts` after every think (a unit in one squad, gold spent\n * once, finite numbers, commands about what it sees, no churn, nothing stuck) and keeps what it decided; `fairPlay` is\n * the one about seeing; `recordDecisions` keeps every computer's decisions for a replay's side file; `checkComputerSave`\n * is the seventh invariant: a game saved and loaded decides the same from then on. These take the world, which a test\n * may: the brains under test never do.\n */\nimport { type AiCheckOptions, type AiViolation, checkBrain } from './ai/checks'\nimport { Brain } from './ai/brain'\nimport type { GoalReport } from './ai/goals'\nimport { type AiDecision, type AiReport, explainGoal } from './ai/report'\nimport type { PlayerId } from './entity'\nimport { type Rules, loadWorld } from './game'\nimport { decodeSave, encodeSave, saveWorld } from './save'\nimport { LocalSession } from './session/local'\nimport type { PlayerCommand, Snapshot } from './session/protocol'\nimport type { World } from './world'\n\n/**\n * The brain that plays a player, where one is seated (`world.computers.seat`): none where nobody is, or where what is\n * seated is not a brain (`defineComputer`)\n *\n * @beta\n */\nexport function brainOf(world: World, player: PlayerId): Brain | undefined {\n\tconst computer = world.computers.get(player)?.computer\n\treturn computer instanceof Brain ? computer : undefined\n}\n\n/** The brain at a player, or an error that says what is seated there instead */\nfunction seated(world: World, player: PlayerId): Brain {\n\tconst brain = brainOf(world, player)\n\tif (brain) return brain\n\tconst system = world.computers.get(player)\n\tthrow new Error(\n\t\tsystem ? `The computer player at ${player} is not a brain (defineBrain): it has no report` : `No computer player is seated at ${player}`\n\t)\n}\n\n/**\n * Has the brain at a player think now, all of it (a think its budget slices over ticks is run to its end), over a new\n * picture of the game, and gives its report: what a test reads after setting a scene. Its commands land at the next\n * tick, as a think's do. A think the seat would have had is not skipped: this one is beside them\n *\n * @beta\n */\nexport function thinkOnce(world: World, player: PlayerId): AiReport {\n\tconst brain = seated(world, player)\n\tdo brain.think()\n\twhile (brain.busy)\n\treturn brain.report()\n}\n\n/**\n * Says that a goal runs, as of a report (`thinkOnce`, `Brain.report`): it is picked and holds what it claimed. Throws\n * where it does not, with its row in words (`Brain.explain`): what each consideration answered and what kept it out.\n * Gives the goal's row. With `picked: false`, says it does not run\n *\n * expectDecision(thinkOnce(world, ENEMY), 'ai.defend')\n *\n * @beta\n */\nexport function expectDecision(report: AiReport, goal: string, options: { picked?: boolean } = {}): GoalReport {\n\tconst wanted = options.picked ?? true\n\tconst row = report.goals.find((each) => each.id === goal)\n\tif (!row)\n\t\tthrow new Error(`The brain ${report.brain} has no goal \"${goal}\": its goals are ${report.goals.map((each) => each.id).join(', ') || 'none'}`)\n\tif (row.picked === wanted) return row\n\tconst seconds = (tick: number) => tick / report.tickRate\n\tthrow new Error(\n\t\t`Expected ${goal} ${wanted ? 'to run' : 'not to run'} at ${report.time.toFixed(1)} s, and it ${wanted ? 'does not' : 'does'}. ${explainGoal(row, seconds, report.time)}${\n\t\t\treport.goal && report.goal !== goal ? ` The best goal is ${report.goal}.` : ''\n\t\t}`\n\t)\n}\n\n/**\n * A computer player followed over a run (`watchComputer`): the rules it broke, what it decided and sent, and, where\n * asked, what an observer saw at each of its thinks\n *\n * @beta\n */\nexport interface ComputerWatch {\n\t/** The brain watched */\n\treadonly brain: Brain\n\t/** Every invariant it broke, in the order found (`ai/checks.ts`) */\n\treadonly violations: readonly AiViolation[]\n\t/** What it decided while watched, oldest first: every line, not only the last fifty its log keeps */\n\treadonly decisions: readonly AiDecision[]\n\t/** Its thinks while watched */\n\treadonly thinks: number\n\t/** Commands it sent while watched */\n\treadonly commands: number\n\t/** Throws, listing them, where it broke any rule */\n\tassert(): void\n\t/** Stops watching */\n\tstop(): void\n}\n\n/**\n * How a computer player is watched (`watchComputer`): which invariants and how long things may go on (`AiCheckOptions`),\n * and what to be shown at each think\n *\n * @beta\n */\nexport interface WatchOptions extends AiCheckOptions {\n\t/**\n\t * Shown, at the end of each of its thinks, the game as an observer sees it (everything, no fog) and the brain: for a\n\t * look at what it does (a test that writes frames, a page that draws them). An observer's seat is made only when given\n\t */\n\tobserve?: (snapshot: Snapshot, brain: Brain) => void\n\t/** Each command as it sends it */\n\tsent?: (command: PlayerCommand, brain: Brain) => void\n}\n\n/**\n * Follows the brain at a player from now on: after every think, the invariants of `ai/checks.ts` (a unit in one squad\n * and one hold, gold spent once, finite numbers, commands about what it sees, no order sent again to a unit still at\n * it, builders, tasks, holds and wants that end), with what it decided and sent. A broken rule is kept, not thrown,\n * unless `onViolation` throws: `assert` at the end says them all\n *\n * @beta\n */\nexport function watchComputer(world: World, player: PlayerId, options: WatchOptions = {}): ComputerWatch {\n\tconst brain = seated(world, player)\n\tconst violations: AiViolation[] = []\n\tconst decisions: AiDecision[] = []\n\tlet thinks = 0\n\tlet commands = 0\n\tconst { stop: unchecked } = checkBrain(brain, {\n\t\t...options,\n\t\tonViolation: (violation) => {\n\t\t\tviolations.push(violation)\n\t\t\toptions.onViolation?.(violation)\n\t\t}\n\t})\n\tconst observer = options.observe ? new LocalSession(world, player, { observer: true }) : undefined\n\tconst unwatched = brain.watch({\n\t\tsent: (command) => {\n\t\t\tcommands++\n\t\t\toptions.sent?.(command, brain)\n\t\t},\n\t\tdecided: (decision) => void decisions.push(decision),\n\t\tthought: () => {\n\t\t\tthinks++\n\t\t\tif (observer) options.observe!(observer.snapshot(), brain)\n\t\t}\n\t})\n\treturn {\n\t\tbrain,\n\t\tviolations,\n\t\tdecisions,\n\t\tget thinks() {\n\t\t\treturn thinks\n\t\t},\n\t\tget commands() {\n\t\t\treturn commands\n\t\t},\n\t\tassert() {\n\t\t\tif (!violations.length) return\n\t\t\tconst lines = violations.slice(0, 20).map((each) => ` ${each.invariant} at tick ${each.tick}: ${each.message}`)\n\t\t\tconst more = violations.length > 20 ? `\\n and ${violations.length - 20} more` : ''\n\t\t\tthrow new Error(\n\t\t\t\t`The computer player at ${player} broke ${violations.length} rule${violations.length === 1 ? '' : 's'}:\\n${lines.join('\\n')}${more}`\n\t\t\t)\n\t\t},\n\t\tstop() {\n\t\t\tunchecked()\n\t\t\tunwatched()\n\t\t\tobserver?.dispose()\n\t\t}\n\t}\n}\n\n/**\n * Whether a computer player played fair over a run (`fairPlay`): every command it sent named what its own snapshot\n * had, and how many the game refused\n *\n * @beta\n */\nexport interface FairPlay {\n\t/** Commands that named an entity it did not see, or a place off the map */\n\treadonly unfair: readonly AiViolation[]\n\t/** Commands the game refused while watched (a unit that could not do it, a place it could not build at) */\n\treadonly refused: number\n\t/** Throws where it sent any command about what it did not see */\n\tassert(): void\n\t/** Stops watching the brain; the violations found so far stay */\n\tstop(): void\n}\n\n/**\n * Follows the brain at a player from now on for fair play: that it never sends a command about an entity its snapshot\n * did not have (a fog leak: its seat's session would drop the command, so a game shows nothing; this says it), and\n * counts what the game refused\n *\n * @beta\n */\nexport function fairPlay(world: World, player: PlayerId): FairPlay {\n\tconst watch = watchComputer(world, player, { invariants: ['commands'] })\n\tconst brain = watch.brain\n\tconst refusedBefore = brain.stats.refused\n\treturn {\n\t\tget unfair() {\n\t\t\treturn watch.violations\n\t\t},\n\t\tget refused() {\n\t\t\treturn brain.stats.refused - refusedBefore\n\t\t},\n\t\tassert: () => watch.assert(),\n\t\tstop: () => watch.stop()\n\t}\n}\n\n/**\n * One thing a computer player decided, with whose: a line of a replay's side file (`recordDecisions`)\n *\n * @beta\n */\nexport interface RecordedDecision extends AiDecision {\n\t/** The player whose computer made the decision */\n\tplayer: PlayerId\n\t/** The brain's id */\n\tbrain: string\n}\n\n/**\n * The decisions of every computer of a world, as they are made (`recordDecisions`): plain data, for a side file beside a\n * replay of commands, read back by whoever wonders why the computer did what the replay shows\n *\n * @beta\n */\nexport interface DecisionRecorder {\n\t/** Every decision so far, in the order made */\n\treadonly decisions: readonly RecordedDecision[]\n\t/** Stops recording; the decisions so far stay */\n\tstop(): void\n}\n\n/** How many recorders were made: each one's system a name of its own */\nlet recorders = 0\n\n/**\n * Keeps the decisions of every brain seated at a world, from now on, those seated later included (looked for at each\n * tick, by a system of its own that keeps nothing in a save)\n *\n * @beta\n */\nexport function recordDecisions(world: World): DecisionRecorder {\n\tconst decisions: RecordedDecision[] = []\n\tconst watched = new Map<Brain, () => void>()\n\tconst look = () => {\n\t\tfor (const player of world.computers.list()) {\n\t\t\tconst brain = brainOf(world, player)\n\t\t\tif (!brain || watched.has(brain)) continue\n\t\t\twatched.set(brain, brain.watch({ decided: (decision) => void decisions.push({ ...decision, player: brain.playerId, brain: brain.def.id }) }))\n\t\t}\n\t}\n\tlook()\n\tconst name = `core.ai.recordDecisions.${++recorders}`\n\tworld.addSystem({ name, update: look })\n\treturn {\n\t\tdecisions,\n\t\tstop() {\n\t\t\tworld.removeSystem(name)\n\t\t\tfor (const unwatch of watched.values()) unwatch()\n\t\t\twatched.clear()\n\t\t}\n\t}\n}\n\n/**\n * Where a game saved and loaded first decided otherwise than the game it was saved from (`checkComputerSave`): the\n * decision each made at that place in their logs. `null` where they decided alike to the end\n *\n * @beta\n */\nexport interface DecisionsApart {\n\t/** How many decisions since the save they shared before this one */\n\tindex: number\n\t/** The game that went on from the save */\n\tsaved?: RecordedDecision\n\t/** The game loaded from it */\n\tloaded?: RecordedDecision\n}\n\n/**\n * The seventh invariant of a computer player: a game saved at tick `from` and loaded makes the same decisions from then\n * on as the game it was saved from, under the same commands. Makes the world with `make` (its computers seated, as a\n * game seats them), runs it to `from`, saves it as a file would keep it and loads that with `game`, then runs both to\n * `ticks` and compares what every computer decided. What lost rng, tasks or memory in a restore shows as\n *\n * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, rules: melee })).toBeNull()\n *\n * @beta\n */\nexport async function checkComputerSave(\n\tmake: () => World | Promise<World>,\n\toptions: { from: number; ticks: number; rules: Rules }\n): Promise<DecisionsApart | null> {\n\tconst saved = await make()\n\tlet loaded: World | undefined\n\ttry {\n\t\twhile (saved.tick < options.from) saved.step()\n\t\tloaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { rules: options.rules })\n\t\tconst before = recordDecisions(saved)\n\t\tconst after = recordDecisions(loaded)\n\t\twhile (saved.tick < options.ticks) {\n\t\t\tsaved.step()\n\t\t\tloaded.step()\n\t\t}\n\t\tbefore.stop()\n\t\tafter.stop()\n\t\tconst a = before.decisions\n\t\tconst b = after.decisions\n\t\tfor (let i = 0; i < Math.max(a.length, b.length); i++)\n\t\t\tif (JSON.stringify(a[i]) !== JSON.stringify(b[i])) return { index: i, ...(a[i] && { saved: a[i] }), ...(b[i] && { loaded: b[i] }) }\n\t\treturn null\n\t} finally {\n\t\tsaved.dispose()\n\t\tloaded?.dispose()\n\t}\n}\n"],"mappings":"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"}
package/dist/areas.d.ts CHANGED
@@ -77,13 +77,14 @@ export declare function areaShapeOf(ref: AreaRef, regions: readonly MapRegion[])
77
77
  /**
78
78
  * A named part of the map that the rules watch: who walks into it and out of it (`enteredArea`, `leftArea` events),
79
79
  * and who is in it now (`world.areas`). Units count, by where their middle is; buildings, scenery and units inside
80
- * something do not. Given in `GameModule.areas`
80
+ * something do not. Given in `Rules.areas`
81
81
  *
82
82
  * @beta
83
83
  */
84
84
  export interface AreaDef {
85
85
  /** Shared by every game, like other ids: give it a prefix of the game's (`'td.gate'`) */
86
86
  id: string;
87
+ /** The area's shape in cells, one of the `AreaShape`s */
87
88
  shape: AreaShape;
88
89
  }
89
90
  /**
@@ -122,7 +123,9 @@ export declare class Areas {
122
123
  constructor(world: World, defs: readonly AreaDef[]);
123
124
  /** The areas of the game, then those added while it runs */
124
125
  get all(): Iterable<AreaDef>;
126
+ /** How many areas there are: the game's and those added while it runs */
125
127
  get size(): number;
128
+ /** Gives the area with the id; throws when there is none */
126
129
  get(id: string): AreaDef;
127
130
  /** Whether there is an area of that id */
128
131
  has(id: string): boolean;
package/dist/areas.js ADDED
@@ -0,0 +1,295 @@
1
+ import { hypot } from "./exactMath.js";
2
+ import { defineComponent } from "./components.js";
3
+ import { enteredArea, leftArea } from "./engineEvents.js";
4
+ //#region src/areas.ts
5
+ /**
6
+ * The box round a shape: its least and greatest x and z on the map
7
+ *
8
+ * @beta
9
+ */
10
+ function shapeBounds(shape) {
11
+ if (shape.kind === "circle") return {
12
+ x0: shape.x - shape.radius,
13
+ z0: shape.z - shape.radius,
14
+ x1: shape.x + shape.radius,
15
+ z1: shape.z + shape.radius
16
+ };
17
+ if (shape.kind === "rect") return {
18
+ x0: shape.x - shape.width / 2,
19
+ z0: shape.z - shape.depth / 2,
20
+ x1: shape.x + shape.width / 2,
21
+ z1: shape.z + shape.depth / 2
22
+ };
23
+ let x0 = Infinity;
24
+ let z0 = Infinity;
25
+ let x1 = -Infinity;
26
+ let z1 = -Infinity;
27
+ for (const point of shape.points) {
28
+ x0 = Math.min(x0, shape.x + point.x);
29
+ z0 = Math.min(z0, shape.z + point.z);
30
+ x1 = Math.max(x1, shape.x + point.x);
31
+ z1 = Math.max(z1, shape.z + point.z);
32
+ }
33
+ return shape.points.length ? {
34
+ x0,
35
+ z0,
36
+ x1,
37
+ z1
38
+ } : {
39
+ x0: shape.x,
40
+ z0: shape.z,
41
+ x1: shape.x,
42
+ z1: shape.z
43
+ };
44
+ }
45
+ /**
46
+ * How much ground a shape covers, in cells
47
+ *
48
+ * @beta
49
+ */
50
+ function shapeArea(shape) {
51
+ if (shape.kind === "circle") return Math.PI * shape.radius * shape.radius;
52
+ if (shape.kind === "rect") return shape.width * shape.depth;
53
+ let twice = 0;
54
+ const { points } = shape;
55
+ for (let i = 0, j = points.length - 1; i < points.length; j = i++) twice += points[j].x * points[i].z - points[i].x * points[j].z;
56
+ return Math.abs(twice) / 2;
57
+ }
58
+ /**
59
+ * A shape as a circle or a rectangle: a polygon as the rectangle round it. For what draws only those (mist, clouds and
60
+ * weather in a region of the map)
61
+ *
62
+ * @beta
63
+ */
64
+ function shapeAsBox(shape) {
65
+ if (shape.kind !== "polygon") return shape;
66
+ const { x0, z0, x1, z1 } = shapeBounds(shape);
67
+ return {
68
+ kind: "rect",
69
+ x: (x0 + x1) / 2,
70
+ z: (z0 + z1) / 2,
71
+ width: x1 - x0,
72
+ depth: z1 - z0
73
+ };
74
+ }
75
+ /**
76
+ * A shape moved to stand at a point and sized `scale` times: a prefab's area where the prefab is put
77
+ *
78
+ * @beta
79
+ */
80
+ function shapeAt(shape, at, scale = 1) {
81
+ if (shape.kind === "circle") return {
82
+ kind: "circle",
83
+ x: at.x,
84
+ z: at.z,
85
+ radius: shape.radius * scale
86
+ };
87
+ if (shape.kind === "rect") return {
88
+ kind: "rect",
89
+ x: at.x,
90
+ z: at.z,
91
+ width: shape.width * scale,
92
+ depth: shape.depth * scale
93
+ };
94
+ return {
95
+ kind: "polygon",
96
+ x: at.x,
97
+ z: at.z,
98
+ points: shape.points.map((point) => ({
99
+ x: point.x * scale,
100
+ z: point.z * scale
101
+ }))
102
+ };
103
+ }
104
+ /**
105
+ * The shape an `AreaRef` stands for: its own, or the named region's among the map's. Nothing for a region that is
106
+ * not there
107
+ *
108
+ * @beta
109
+ */
110
+ function areaShapeOf(ref, regions) {
111
+ if ("region" in ref) return regions.find((region) => region.name === ref.region)?.shape;
112
+ return ref;
113
+ }
114
+ /**
115
+ * Typed help for writing an area
116
+ *
117
+ * @beta
118
+ */
119
+ var defineArea = (def) => def;
120
+ /**
121
+ * Whether a point is in a shape
122
+ *
123
+ * @beta
124
+ */
125
+ function inShape(shape, point) {
126
+ const dx = point.x - shape.x;
127
+ const dz = point.z - shape.z;
128
+ if (shape.kind === "circle") return dx * dx + dz * dz <= shape.radius * shape.radius;
129
+ if (shape.kind === "rect") return Math.abs(dx) <= shape.width / 2 && Math.abs(dz) <= shape.depth / 2;
130
+ const { points } = shape;
131
+ let odd = false;
132
+ for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
133
+ const a = points[i];
134
+ const b = points[j];
135
+ if (a.z > dz !== b.z > dz && dx < (b.x - a.x) * (dz - a.z) / (b.z - a.z) + a.x) odd = !odd;
136
+ }
137
+ return odd;
138
+ }
139
+ /**
140
+ * The radius of a circle round the whole shape from its middle (`x`, `z`): what the spatial index is asked for
141
+ *
142
+ * @beta
143
+ */
144
+ function shapeReach(shape) {
145
+ if (shape.kind === "circle") return shape.radius;
146
+ if (shape.kind === "rect") return hypot(shape.width, shape.depth) / 2;
147
+ let most = 0;
148
+ for (const point of shape.points) most = Math.max(most, hypot(point.x, point.z));
149
+ return most;
150
+ }
151
+ var reach = shapeReach;
152
+ /** Who is in each area, by id: kept in the world, so that a save knows, and nobody walks in twice after loading */
153
+ var inside = defineComponent({
154
+ id: "core.areas",
155
+ default: () => ({})
156
+ });
157
+ /** Areas added while the game runs (`areas.add`): kept in the world, so that a save has them */
158
+ var added = defineComponent({
159
+ id: "core.areasAdded",
160
+ default: () => []
161
+ });
162
+ /**
163
+ * The areas of a world, and who is in them
164
+ *
165
+ * @beta
166
+ */
167
+ var Areas = class {
168
+ world;
169
+ byId = /* @__PURE__ */ new Map();
170
+ /** Kept between ticks, not made anew */
171
+ found = [];
172
+ now = /* @__PURE__ */ new Set();
173
+ constructor(world, defs) {
174
+ this.world = world;
175
+ for (const def of defs) {
176
+ if (this.byId.has(def.id)) throw new Error(`Area "${def.id}" is there twice`);
177
+ this.byId.set(def.id, def);
178
+ }
179
+ }
180
+ /** The areas of the game, then those added while it runs */
181
+ get all() {
182
+ return [...this.byId.values(), ...this.added()];
183
+ }
184
+ /** How many areas there are: the game's and those added while it runs */
185
+ get size() {
186
+ return this.byId.size + this.added().length;
187
+ }
188
+ /** Gives the area with the id; throws when there is none */
189
+ get(id) {
190
+ const def = this.find(id);
191
+ if (!def) throw new Error(`There is no area "${id}"`);
192
+ return def;
193
+ }
194
+ /** Whether there is an area of that id */
195
+ has(id) {
196
+ return !!this.find(id);
197
+ }
198
+ find(id) {
199
+ return this.byId.get(id) ?? this.added().find((def) => def.id === id);
200
+ }
201
+ added() {
202
+ return this.world.state(added);
203
+ }
204
+ /**
205
+ * Adds an area while the game runs: a zone a spell leaves, a ring that closes in, a part of the map a quest opens.
206
+ * Who is in it is found at the end of the tick, and walks in then. One of the same id, added before, is replaced
207
+ */
208
+ add(def) {
209
+ if (this.byId.has(def.id)) throw new Error(`Area "${def.id}" is one of the game's: it cannot be added again`);
210
+ const list = this.added();
211
+ const index = list.findIndex((other) => other.id === def.id);
212
+ const copy = {
213
+ id: def.id,
214
+ shape: { ...def.shape }
215
+ };
216
+ if (index >= 0) list[index] = copy;
217
+ else list.push(copy);
218
+ }
219
+ /** Takes away an area added while the game runs. Who was in it leaves it (`leftArea`). False when there was none */
220
+ remove(id) {
221
+ const list = this.added();
222
+ const index = list.findIndex((def) => def.id === id);
223
+ if (index < 0) return false;
224
+ list.splice(index, 1);
225
+ const state = this.world.state(inside);
226
+ for (const entityId of state[id] ?? []) {
227
+ const entity = this.world.get(entityId);
228
+ if (entity?.alive) this.world.events.emit(leftArea, {
229
+ area: id,
230
+ entity
231
+ });
232
+ }
233
+ delete state[id];
234
+ return true;
235
+ }
236
+ /** Whether the entity was in the area when the areas were last looked at: the end of the last tick's movement */
237
+ contains(id, entity) {
238
+ return this.idsIn(id).includes(entity.id);
239
+ }
240
+ /** Who is in the area, as of the last look */
241
+ inside(id) {
242
+ const result = [];
243
+ for (const entityId of this.idsIn(id)) {
244
+ const entity = this.world.get(entityId);
245
+ if (entity) result.push(entity);
246
+ }
247
+ return result;
248
+ }
249
+ idsIn(id) {
250
+ this.get(id);
251
+ return this.world.state(inside)[id] ?? [];
252
+ }
253
+ /** Looks who is in each area now, and tells who walked in and who walked out. What died in one is just gone */
254
+ update() {
255
+ const state = this.world.state(inside);
256
+ for (const area of this.byId.values()) this.look(area, state);
257
+ for (const area of this.added()) this.look(area, state);
258
+ }
259
+ /** Who is in one area now, against who was */
260
+ look(area, state) {
261
+ const { world, found, now } = this;
262
+ const { shape } = area;
263
+ now.clear();
264
+ for (const entity of world.spatial.query(shape.x, shape.z, reach(shape), found)) {
265
+ if (entity.def.kind !== "unit" || !entity.alive || entity.hidden || !inShape(shape, entity.pos)) continue;
266
+ now.add(entity.id);
267
+ }
268
+ const before = state[area.id] ?? [];
269
+ for (const id of before) {
270
+ if (now.has(id)) continue;
271
+ const entity = world.get(id);
272
+ if (entity?.alive) world.events.emit(leftArea, {
273
+ area: area.id,
274
+ entity
275
+ });
276
+ }
277
+ for (const id of now) if (!before.includes(id)) world.events.emit(enteredArea, {
278
+ area: area.id,
279
+ entity: world.get(id)
280
+ });
281
+ if (now.size || before.length) state[area.id] = [...now];
282
+ }
283
+ };
284
+ /** Watches the areas, after everyone has moved. Does nothing in a game without any */
285
+ var areaSystem = {
286
+ name: "areas",
287
+ phase: "resolve",
288
+ update(world) {
289
+ if (world.areas.size) world.areas.update();
290
+ }
291
+ };
292
+ //#endregion
293
+ export { Areas, added, areaShapeOf, areaSystem, defineArea, inShape, inside, shapeArea, shapeAsBox, shapeAt, shapeBounds, shapeReach };
294
+
295
+ //# sourceMappingURL=areas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"areas.js","names":["leftAreaEvent","enteredAreaEvent"],"sources":["../src/areas.ts"],"sourcesContent":["import { enteredArea as enteredAreaEvent, leftArea as leftAreaEvent } from '#engine/engineEvents'\nimport { defineComponent } from './components'\nimport type { Entity } from './entity'\nimport type { Vec2 } from './math'\nimport type { System } from './registry'\nimport type { World } from './world'\nimport { hypot } from './exactMath'\nimport type { MapRegion } from './map'\n\n/**\n * Where an area is on the map: a circle, a rectangle by its middle and size, or a polygon by its corners round a middle\n * of its own (`points`, each from `x` and `z`, three or more, in order round it: moving the middle moves it whole)\n *\n * @beta\n */\nexport type AreaShape =\n\t| { kind: 'circle'; x: number; z: number; radius: number }\n\t| { kind: 'rect'; x: number; z: number; width: number; depth: number }\n\t| { kind: 'polygon'; x: number; z: number; points: Vec2[] }\n\n/**\n * The box round a shape: its least and greatest x and z on the map\n *\n * @beta\n */\nexport function shapeBounds(shape: AreaShape): { x0: number; z0: number; x1: number; z1: number } {\n\tif (shape.kind === 'circle')\n\t\treturn { x0: shape.x - shape.radius, z0: shape.z - shape.radius, x1: shape.x + shape.radius, z1: shape.z + shape.radius }\n\tif (shape.kind === 'rect')\n\t\treturn { x0: shape.x - shape.width / 2, z0: shape.z - shape.depth / 2, x1: shape.x + shape.width / 2, z1: shape.z + shape.depth / 2 }\n\tlet x0 = Infinity\n\tlet z0 = Infinity\n\tlet x1 = -Infinity\n\tlet z1 = -Infinity\n\tfor (const point of shape.points) {\n\t\tx0 = Math.min(x0, shape.x + point.x)\n\t\tz0 = Math.min(z0, shape.z + point.z)\n\t\tx1 = Math.max(x1, shape.x + point.x)\n\t\tz1 = Math.max(z1, shape.z + point.z)\n\t}\n\treturn shape.points.length ? { x0, z0, x1, z1 } : { x0: shape.x, z0: shape.z, x1: shape.x, z1: shape.z }\n}\n\n/**\n * How much ground a shape covers, in cells\n *\n * @beta\n */\nexport function shapeArea(shape: AreaShape): number {\n\tif (shape.kind === 'circle') return Math.PI * shape.radius * shape.radius\n\tif (shape.kind === 'rect') return shape.width * shape.depth\n\tlet twice = 0\n\tconst { points } = shape\n\tfor (let i = 0, j = points.length - 1; i < points.length; j = i++) twice += points[j].x * points[i].z - points[i].x * points[j].z\n\treturn Math.abs(twice) / 2\n}\n\n/**\n * A shape as a circle or a rectangle: a polygon as the rectangle round it. For what draws only those (mist, clouds and\n * weather in a region of the map)\n *\n * @beta\n */\nexport function shapeAsBox(shape: AreaShape): Exclude<AreaShape, { kind: 'polygon' }> {\n\tif (shape.kind !== 'polygon') return shape\n\tconst { x0, z0, x1, z1 } = shapeBounds(shape)\n\treturn { kind: 'rect', x: (x0 + x1) / 2, z: (z0 + z1) / 2, width: x1 - x0, depth: z1 - z0 }\n}\n\n/**\n * A shape moved to stand at a point and sized `scale` times: a prefab's area where the prefab is put\n *\n * @beta\n */\nexport function shapeAt(shape: AreaShape, at: Vec2, scale = 1): AreaShape {\n\tif (shape.kind === 'circle') return { kind: 'circle', x: at.x, z: at.z, radius: shape.radius * scale }\n\tif (shape.kind === 'rect') return { kind: 'rect', x: at.x, z: at.z, width: shape.width * scale, depth: shape.depth * scale }\n\treturn { kind: 'polygon', x: at.x, z: at.z, points: shape.points.map((point) => ({ x: point.x * scale, z: point.z * scale })) }\n}\n\n/**\n * Where something of the map is, by a shape of its own or by a region of the map, named: mist, clouds and weather in\n * places (`MapMistArea.shape`). By the region, it is where the region is, moved with it, and is the rules' too\n *\n * @beta\n */\nexport type AreaRef = AreaShape | { region: string }\n\n/**\n * The shape an `AreaRef` stands for: its own, or the named region's among the map's. Nothing for a region that is\n * not there\n *\n * @beta\n */\nexport function areaShapeOf(ref: AreaRef, regions: readonly MapRegion[]): AreaShape | undefined {\n\tif ('region' in ref) return regions.find((region) => region.name === ref.region)?.shape\n\treturn ref\n}\n\n/**\n * A named part of the map that the rules watch: who walks into it and out of it (`enteredArea`, `leftArea` events),\n * and who is in it now (`world.areas`). Units count, by where their middle is; buildings, scenery and units inside\n * something do not. Given in `Rules.areas`\n *\n * @beta\n */\nexport interface AreaDef {\n\t/** Shared by every game, like other ids: give it a prefix of the game's (`'td.gate'`) */\n\tid: string\n\t/** The area's shape in cells, one of the `AreaShape`s */\n\tshape: AreaShape\n}\n\n/**\n * Typed help for writing an area\n *\n * @beta\n */\nexport const defineArea = (def: AreaDef): AreaDef => def\n\n/**\n * Whether a point is in a shape\n *\n * @beta\n */\nexport function inShape(shape: AreaShape, point: Vec2): boolean {\n\tconst dx = point.x - shape.x\n\tconst dz = point.z - shape.z\n\tif (shape.kind === 'circle') return dx * dx + dz * dz <= shape.radius * shape.radius\n\tif (shape.kind === 'rect') return Math.abs(dx) <= shape.width / 2 && Math.abs(dz) <= shape.depth / 2\n\t// a polygon: in where a line from the point crosses its edges an odd number of times\n\tconst { points } = shape\n\tlet odd = false\n\tfor (let i = 0, j = points.length - 1; i < points.length; j = i++) {\n\t\tconst a = points[i]\n\t\tconst b = points[j]\n\t\tif (a.z > dz !== b.z > dz && dx < ((b.x - a.x) * (dz - a.z)) / (b.z - a.z) + a.x) odd = !odd\n\t}\n\treturn odd\n}\n\n/**\n * The radius of a circle round the whole shape from its middle (`x`, `z`): what the spatial index is asked for\n *\n * @beta\n */\nexport function shapeReach(shape: AreaShape): number {\n\tif (shape.kind === 'circle') return shape.radius\n\tif (shape.kind === 'rect') return hypot(shape.width, shape.depth) / 2\n\tlet most = 0\n\tfor (const point of shape.points) most = Math.max(most, hypot(point.x, point.z))\n\treturn most\n}\nconst reach = shapeReach\n\n/** Who is in each area, by id: kept in the world, so that a save knows, and nobody walks in twice after loading */\nexport const inside = defineComponent<Record<string, number[]>>({ id: 'core.areas', default: () => ({}) })\n/** Areas added while the game runs (`areas.add`): kept in the world, so that a save has them */\nexport const added = defineComponent<AreaDef[]>({ id: 'core.areasAdded', default: () => [] })\n\n/**\n * The areas of a world, and who is in them\n *\n * @beta\n */\nexport class Areas {\n\tprivate readonly byId = new Map<string, AreaDef>()\n\t/** Kept between ticks, not made anew */\n\tprivate readonly found: Entity[] = []\n\tprivate readonly now = new Set<number>()\n\n\tconstructor(\n\t\tprivate readonly world: World,\n\t\tdefs: readonly AreaDef[]\n\t) {\n\t\tfor (const def of defs) {\n\t\t\tif (this.byId.has(def.id)) throw new Error(`Area \"${def.id}\" is there twice`)\n\t\t\tthis.byId.set(def.id, def)\n\t\t}\n\t}\n\n\t/** The areas of the game, then those added while it runs */\n\tget all(): Iterable<AreaDef> {\n\t\treturn [...this.byId.values(), ...this.added()]\n\t}\n\n\t/** How many areas there are: the game's and those added while it runs */\n\tget size(): number {\n\t\treturn this.byId.size + this.added().length\n\t}\n\n\t/** Gives the area with the id; throws when there is none */\n\tget(id: string): AreaDef {\n\t\tconst def = this.find(id)\n\t\tif (!def) throw new Error(`There is no area \"${id}\"`)\n\t\treturn def\n\t}\n\n\t/** Whether there is an area of that id */\n\thas(id: string): boolean {\n\t\treturn !!this.find(id)\n\t}\n\n\tprivate find(id: string): AreaDef | undefined {\n\t\treturn this.byId.get(id) ?? this.added().find((def) => def.id === id)\n\t}\n\n\tprivate added(): AreaDef[] {\n\t\treturn this.world.state(added)\n\t}\n\n\t/**\n\t * Adds an area while the game runs: a zone a spell leaves, a ring that closes in, a part of the map a quest opens.\n\t * Who is in it is found at the end of the tick, and walks in then. One of the same id, added before, is replaced\n\t */\n\tadd(def: AreaDef): void {\n\t\tif (this.byId.has(def.id)) throw new Error(`Area \"${def.id}\" is one of the game's: it cannot be added again`)\n\t\tconst list = this.added()\n\t\tconst index = list.findIndex((other) => other.id === def.id)\n\t\t// a copy: the shape may be moved by adding it again, not by changing what was given\n\t\tconst copy = { id: def.id, shape: { ...def.shape } }\n\t\tif (index >= 0) list[index] = copy\n\t\telse list.push(copy)\n\t}\n\n\t/** Takes away an area added while the game runs. Who was in it leaves it (`leftArea`). False when there was none */\n\tremove(id: string): boolean {\n\t\tconst list = this.added()\n\t\tconst index = list.findIndex((def) => def.id === id)\n\t\tif (index < 0) return false\n\t\tlist.splice(index, 1)\n\t\tconst state = this.world.state(inside)\n\t\tfor (const entityId of state[id] ?? []) {\n\t\t\tconst entity = this.world.get(entityId)\n\t\t\tif (entity?.alive) this.world.events.emit(leftAreaEvent, { area: id, entity })\n\t\t}\n\t\tdelete state[id]\n\t\treturn true\n\t}\n\n\t/** Whether the entity was in the area when the areas were last looked at: the end of the last tick's movement */\n\tcontains(id: string, entity: Entity): boolean {\n\t\treturn this.idsIn(id).includes(entity.id)\n\t}\n\n\t/** Who is in the area, as of the last look */\n\tinside(id: string): Entity[] {\n\t\tconst result: Entity[] = []\n\t\tfor (const entityId of this.idsIn(id)) {\n\t\t\tconst entity = this.world.get(entityId)\n\t\t\tif (entity) result.push(entity)\n\t\t}\n\t\treturn result\n\t}\n\n\tprivate idsIn(id: string): number[] {\n\t\tthis.get(id)\n\t\treturn this.world.state(inside)[id] ?? []\n\t}\n\n\t/** Looks who is in each area now, and tells who walked in and who walked out. What died in one is just gone */\n\tupdate(): void {\n\t\tconst state = this.world.state(inside)\n\t\t// the game's, then those added: no list made of both every tick\n\t\tfor (const area of this.byId.values()) this.look(area, state)\n\t\tfor (const area of this.added()) this.look(area, state)\n\t}\n\n\t/** Who is in one area now, against who was */\n\tprivate look(area: AreaDef, state: Record<string, number[]>): void {\n\t\tconst { world, found, now } = this\n\t\tconst { shape } = area\n\t\tnow.clear()\n\t\tfor (const entity of world.spatial.query(shape.x, shape.z, reach(shape), found)) {\n\t\t\tif (entity.def.kind !== 'unit' || !entity.alive || entity.hidden || !inShape(shape, entity.pos)) continue\n\t\t\tnow.add(entity.id)\n\t\t}\n\t\tconst before = state[area.id] ?? []\n\t\tfor (const id of before) {\n\t\t\tif (now.has(id)) continue\n\t\t\tconst entity = world.get(id)\n\t\t\tif (entity?.alive) world.events.emit(leftAreaEvent, { area: area.id, entity })\n\t\t}\n\t\tfor (const id of now) {\n\t\t\tif (!before.includes(id)) world.events.emit(enteredAreaEvent, { area: area.id, entity: world.get(id)! })\n\t\t}\n\t\tif (now.size || before.length) state[area.id] = [...now]\n\t}\n}\n\n/** Watches the areas, after everyone has moved. Does nothing in a game without any */\nexport const areaSystem: System = {\n\tname: 'areas',\n\tphase: 'resolve',\n\tupdate(world) {\n\t\tif (world.areas.size) world.areas.update()\n\t}\n}\n"],"mappings":"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"}