@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
@@ -0,0 +1,1316 @@
1
+ import { distSq } from "../math.js";
2
+ import { anyEffect, at, baseStats, declaredAt, lowerChain, supplyOf } from "../defs.js";
3
+ import { snapshotOf } from "../components.js";
4
+ import { inventorySlots } from "../inventory.js";
5
+ import { heroOfState } from "../hero.js";
6
+ import { farthestReach } from "../attacks.js";
7
+ import { AIM_KINDS } from "../targeting.js";
8
+ import { shopStock } from "../items.js";
9
+ import { defineModule } from "./module.js";
10
+ import "./reach.js";
11
+ import { UnitSet } from "./view.js";
12
+ import { evaluate } from "./rules.js";
13
+ import { an, pair, point, where } from "./geometry.js";
14
+ import { orderKey } from "./checks.js";
15
+ import { defineTask } from "./task.js";
16
+ //#region src/ai/micro.ts
17
+ /** Seconds a squad keeps hitting the one it was told to, before it is chosen again */
18
+ var FOCUS_EVERY = 4;
19
+ /** Seconds between two steps back of one unit: what keeps a kiting unit from stuttering */
20
+ var KITE_EVERY = 3;
21
+ /** How near a melee foe comes, past its own reach, before a ranged unit steps back */
22
+ var KITE_CLOSE = 3;
23
+ /** How much faster than the foe a unit is to step back from it: as fast is not enough, the foe is on it again as it stops */
24
+ var KITE_FASTER = 1.05;
25
+ /** How far from the middle of its squad a kiting unit may step, past the squad's spread */
26
+ var KITE_LEASH = 1;
27
+ /** The odds under which a unit does not bother kiting: its squad falls back, or fights on to the last */
28
+ var KITE_ODDS = .3;
29
+ /** Seconds between two orders of a siege unit */
30
+ var SIEGE_EVERY = 4;
31
+ /** How near a siege unit a foe is for the unit to be threatened: it shoots what threatens it, not buildings */
32
+ var SIEGE_THREATENED = 6;
33
+ /** How far behind the squad's middle a siege unit ahead of it is sent */
34
+ var SIEGE_BEHIND = 3;
35
+ /** Seconds a fled unit with nothing to heal it waits in safety before it is back */
36
+ var FLEE_SAFE = 8;
37
+ /**
38
+ * Seconds of its own healing a fled unit is worth waiting for: one that would take longer to be back at `returnAt` (a
39
+ * trickle of regeneration) is as one nothing heals, and comes back once safe, rather than sitting out the game
40
+ */
41
+ var HEAL_WAIT = 60;
42
+ /** How far a unit with nowhere safe to go runs from the fight */
43
+ var FLEE_AWAY = 20;
44
+ /** Seconds before a fleeing unit standing idle short of its destination is sent again */
45
+ var FLEE_RESEND = 3;
46
+ /** How far a shop may be for a hero to walk to it: not across the map */
47
+ var SHOP_REACH = 60;
48
+ /** How near a shop a hero is at it: the engine's shop range (6), a little in */
49
+ var AT_SHOP = 5;
50
+ /** How important an item is to the purse: under a hero (35), over what can wait */
51
+ var SHOPPING_PRIORITY = 20;
52
+ /** How important a mercenary is to the purse: under an item, over the soldiers trained (0) */
53
+ var HIRING_PRIORITY = 10;
54
+ /** Money to have left over before hiring of itself (the kit's choice): a mercenary is bought with what would lie idle */
55
+ var HIRING_SPARE = 150;
56
+ /** Mercenaries it keeps at the most, of the kit's choice */
57
+ var HIRING_MOST = 4;
58
+ /** The share of its health under which a unit drinks what heals, and of its mana under which it drinks what restores */
59
+ var DRINK_HEALTH = .45;
60
+ var DRINK_MANA = .25;
61
+ /** The squad the micro module keeps the units that fled in */
62
+ var FLEEING = "fleeing";
63
+ /** Whose the fleeing squad is */
64
+ var OWNER = "micro";
65
+ /** The kit's rules of who is worth hitting first: casters, healers, heroes, siege; everyone else is worth 1 */
66
+ var DEFAULT_TARGETS = [
67
+ {
68
+ match: "caster",
69
+ weight: 2
70
+ },
71
+ {
72
+ match: "healer",
73
+ weight: 2
74
+ },
75
+ {
76
+ match: "hero",
77
+ weight: 1.5
78
+ },
79
+ {
80
+ match: "siege",
81
+ weight: 1
82
+ }
83
+ ];
84
+ var percent = (share) => `${Math.round(share * 100)}%`;
85
+ /**
86
+ * A brain's micro (`ai.micro`): how its squads fight once in a fight, run by the `micro()` module each think after the
87
+ * squads (`think`), and asked by whoever wants its judgement (`target`, `priority`, `nextHero`, `nextSkill`). Kept in
88
+ * the brain's memory (`BrainMemory.micro`)
89
+ *
90
+ * @internal
91
+ */
92
+ var Micro = class Micro {
93
+ ai;
94
+ /** What finds it on a brain (`ai.area(Micro)`): made the first time a module asks for it */
95
+ static id = "micro";
96
+ /** Makes the micro of a brain; what `ai.area(Micro)` calls the first time a module asks for it */
97
+ static make(ai) {
98
+ return new Micro(ai);
99
+ }
100
+ /** Its id among the brain's areas: what its memory and its report are kept under */
101
+ id = "micro";
102
+ /** What the log says where a save's memory of it is of a shape it does not read */
103
+ afresh = "the save remembers how the computer player was fighting in a shape this brain does not read: it fights afresh";
104
+ /** What the module was made with, under the brain's settings */
105
+ configured = {};
106
+ /** Whether a `micro()` module is in the brain: without one, nothing here runs by itself, and the squads fight as units do */
107
+ enabled = false;
108
+ memory = {
109
+ v: 1,
110
+ focus: {},
111
+ kited: {},
112
+ fled: {},
113
+ siege: {},
114
+ shopping: {},
115
+ rolled: {}
116
+ };
117
+ fights = [];
118
+ cast = 0;
119
+ /** Thinks its fights were left alone, a slip of its profile's `mistakes` */
120
+ slipped = 0;
121
+ thoughtAt = {};
122
+ constructor(ai) {
123
+ this.ai = ai;
124
+ ai.squads.define(FLEE);
125
+ }
126
+ /** Puts the `micro()` module's options under the brain's settings: what the module is made with */
127
+ configure(options) {
128
+ this.configured = options;
129
+ this.enabled = true;
130
+ }
131
+ /** How it fights: the module's options, the brain's settings over them (`ai.settings.micro`: when units and heroes flee, the flags) */
132
+ get options() {
133
+ return this.ai.cache("micro.options", () => ({
134
+ ...this.configured,
135
+ ...this.ai.settings.micro
136
+ }));
137
+ }
138
+ /** Whether the module fights for a squad: one on a task that fights (`TaskDef.fighting`), not told to be left alone (`SquadOptions.micro`) */
139
+ manages(squad) {
140
+ const state = squad.current;
141
+ return this.enabled && squad.options.micro !== false && !!state && state.done === void 0 && this.ai.squads.taskDef(state.kind)?.fighting !== false;
142
+ }
143
+ /**
144
+ * The whole think: the fights (focus fire, kiting, siege, fleeing), those that fled coming back, the spells, the
145
+ * items, the heroes' skills. Each part once a think: a part the melee player's steps asked for already is not done again
146
+ */
147
+ think() {
148
+ const mistakes = this.ai.profile.mistakes ?? 0;
149
+ if (!this.fighting && mistakes > 0 && this.ai.rng.next() < mistakes) {
150
+ this.slipped++;
151
+ this.done("fights");
152
+ }
153
+ if (!this.fight()) return;
154
+ this.spells();
155
+ this.items();
156
+ this.heroes();
157
+ }
158
+ /**
159
+ * The fights: each squad in one looked at, its units told whom to hit, stepped back, sent to shoot buildings, sent to
160
+ * safety; and the fled coming back. The squads are looked at as many a tick as the budget has room for (F2,
161
+ * `ai.budget`): false where it stopped for the tick with squads to go, to go on at the next over the same picture
162
+ */
163
+ fight() {
164
+ const { ai } = this;
165
+ const { view } = ai;
166
+ if (!this.fighting) {
167
+ if (!this.begin("fights")) return true;
168
+ this.prune();
169
+ this.fights = [];
170
+ const focused = this.memory.focus;
171
+ for (const name in focused) {
172
+ const squad = ai.squads.named(name);
173
+ if (!squad || !this.manages(squad)) delete focused[name];
174
+ }
175
+ this.fighting = {
176
+ squads: view.hostile.alive().length ? [...ai.squads.all()].filter((squad) => this.manages(squad)) : [],
177
+ at: 0
178
+ };
179
+ }
180
+ const hostile = view.hostile.alive();
181
+ const { squads } = this.fighting;
182
+ for (; this.fighting.at < squads.length; this.fighting.at++) {
183
+ const looked = this.fightOf(squads[this.fighting.at], hostile);
184
+ if (!ai.budget.spent(looked || 1) && this.fighting.at + 1 < squads.length) {
185
+ this.fighting.at++;
186
+ ai.budget.later();
187
+ return false;
188
+ }
189
+ }
190
+ this.fighting = void 0;
191
+ this.injured();
192
+ this.back();
193
+ return true;
194
+ }
195
+ /** One squad's fight, if it is in one: its units told whom to hit, stepped back, sent at buildings, sent to safety. Gives how many units were looked at */
196
+ fightOf(squad, hostile) {
197
+ const { view } = this.ai;
198
+ const focused = this.memory.focus;
199
+ const units = squad.units();
200
+ const middle = units.centre();
201
+ if (!middle) return 0;
202
+ const foes = hostile.near(middle, 14).where((entity, def) => !entity.asleep && (def.kind === "unit" || !!def.attacks?.length));
203
+ if (!foes.length) {
204
+ delete focused[squad.name];
205
+ return units.length;
206
+ }
207
+ const fight = {
208
+ squad,
209
+ units,
210
+ middle,
211
+ foes,
212
+ odds: view.strength.odds(units, foes),
213
+ kiting: [],
214
+ siege: []
215
+ };
216
+ this.fights.push(fight);
217
+ this.flee(fight);
218
+ fight.units = squad.units();
219
+ if (!fight.units.length) return units.length;
220
+ this.siegeOf(fight);
221
+ this.kite(fight);
222
+ this.focus(fight);
223
+ return units.length;
224
+ }
225
+ /** The squads still to be looked at for a fight this think, where a pass stopped for the tick's budget, and the next of them */
226
+ fighting;
227
+ /**
228
+ * How much a foe is worth hitting: what its type declares (`UnitTypeDef.ai.priority`, 1 when it says nothing) times
229
+ * one and the weights of the rules that pick it out (`targets`, the kit's when none are given)
230
+ */
231
+ priority(foe) {
232
+ const { view } = this.ai;
233
+ const def = view.def(foe);
234
+ let worth = 1;
235
+ const rules = Array.isArray(this.options.targets) ? this.options.targets : DEFAULT_TARGETS;
236
+ for (const rule of rules) {
237
+ if (rule.match === "hero" && this.options.targetHeroes === false && !Array.isArray(this.options.targets)) continue;
238
+ if (!this.matches(rule.match, foe, def)) continue;
239
+ if (rule.when !== void 0 && !evaluate(rule.when, this.ai)) continue;
240
+ worth += rule.weight ?? 1;
241
+ }
242
+ return (def.ai?.priority ?? 1) * worth;
243
+ }
244
+ /** Whether a rule's word picks a foe out: `building`, a role, a tag, a type */
245
+ matches(match, foe, def) {
246
+ if (match === "building") return def.kind === "building";
247
+ const { roles } = this.ai.view;
248
+ return foe.type === match || roles.has(foe.type, match) || roles.hasTag(foe.type, match);
249
+ }
250
+ /**
251
+ * Whom a squad in a fight hits: the foe worth most (`priority`), the weakest among those alike (what falls soonest
252
+ * deals no more damage), the nearest among those alike too; or what the game's picker says (`targets` as a function)
253
+ */
254
+ target(squad, foes) {
255
+ if (typeof this.options.targets === "function") return this.options.targets(this.ai, squad, foes);
256
+ const prey = this.preyOf(squad, foes);
257
+ if (prey) return prey;
258
+ const middle = squad.centre();
259
+ if (!middle || !foes.length) return void 0;
260
+ let best;
261
+ let most = -Infinity;
262
+ for (const foe of foes) {
263
+ const stats = this.ai.view.strength.statsOf(foe);
264
+ const health = Math.max(0, Math.min(1, foe.health / Math.max(1, foe.maxHealth ?? stats.health)));
265
+ const near = 1 - .2 * Math.min(1, Math.sqrt(distSq(foe, middle)) / 14);
266
+ const score = this.priority(foe) * (2 - health) * near;
267
+ if (score > most) {
268
+ most = score;
269
+ best = foe;
270
+ }
271
+ }
272
+ return best;
273
+ }
274
+ /**
275
+ * What the squad's task wants hit first, where it is among the foes: a harass's worker (`TaskState.memory.prey`). The
276
+ * task names it and the micro module, fighting for the squad, sends the order: one of them, not both, or the units are
277
+ * told the same twice
278
+ */
279
+ preyOf(squad, foes) {
280
+ const prey = squad.current?.memory.prey;
281
+ return typeof prey === "number" ? foes.find((foe) => foe.id === prey) : void 0;
282
+ }
283
+ /**
284
+ * All of a squad on one rival: chosen again once it fell or every `focusEvery` seconds, the units within reach of it
285
+ * told to attack it, and then, queued, to go on with the squad's errand. The healers are left to their spells, the
286
+ * siege to its buildings, what stepped back this think to its step
287
+ */
288
+ focus(fight) {
289
+ const { ai } = this;
290
+ const { squad, foes, units } = fight;
291
+ const every = (this.options.focusEvery ?? FOCUS_EVERY) * ai.session.tickRate;
292
+ const kept = this.memory.focus[squad.name];
293
+ const current = kept && foes.find((foe) => foe.id === kept.target);
294
+ const prey = this.preyOf(squad, foes);
295
+ if (current && ai.tick - kept.since < every && (!prey || prey.id === current.id)) {
296
+ fight.target = current;
297
+ return;
298
+ }
299
+ const target = this.target(squad, foes);
300
+ if (!target) {
301
+ delete this.memory.focus[squad.name];
302
+ return;
303
+ }
304
+ this.memory.focus[squad.name] = {
305
+ target: target.id,
306
+ since: ai.tick
307
+ };
308
+ fight.target = target;
309
+ const again = kept?.target === target.id;
310
+ if (squad.current?.kind === "defend") squad.current.memory.foe = target.id;
311
+ const { roles } = ai.view;
312
+ const reach = 196;
313
+ const told = orderKey({
314
+ type: "attack",
315
+ entities: [],
316
+ point: point(target),
317
+ target: target.id
318
+ });
319
+ const toldAlready = (unit) => {
320
+ const sent = ai.sentTo(unit.id);
321
+ return !!sent && sent.key === told && (unit.own?.order === "attack" || sent.tick >= ai.snapshot.tick);
322
+ };
323
+ const hitters = units.filter((unit) => distSq(unit, target) < reach && !unit.own?.hidden && !roles.has(unit.type, "healer") && !fight.kiting.includes(unit.id) && !fight.siege.includes(unit.id) && !(again && (unit.own?.order === "attack" || unit.own?.order === "cast")) && !toldAlready(unit));
324
+ if (!hitters.length) return;
325
+ const entities = hitters.map((unit) => unit.id);
326
+ ai.send({
327
+ type: "attack",
328
+ entities,
329
+ point: point(target),
330
+ target: target.id
331
+ });
332
+ const on = ai.squads.whereOf(squad) ?? fight.middle;
333
+ ai.send({
334
+ type: "attack",
335
+ entities,
336
+ point: point(on),
337
+ queue: true
338
+ });
339
+ }
340
+ /**
341
+ * The ranged units of a squad closed on by melee they can outrun step back as far as their reach, within the squad's
342
+ * spread, then go on with the fight: no more than once every few seconds each, and not when the squad is losing (it
343
+ * falls back, or fights to the last)
344
+ */
345
+ kite(fight) {
346
+ if ((this.options.kite ?? "ranged") === false || fight.odds < KITE_ODDS) return;
347
+ const { ai } = this;
348
+ const { view } = ai;
349
+ const { roles } = view;
350
+ const every = KITE_EVERY * ai.session.tickRate;
351
+ const melee = fight.foes.where((_, def) => def.kind === "unit" && !!def.attacks?.length && !def.attacks.some((attack) => attack.projectileSpeed));
352
+ if (!melee.length) return;
353
+ const spread = fight.squad.spread() + KITE_LEASH;
354
+ const { width, depth } = ai.session.terrain;
355
+ const on = ai.squads.whereOf(fight.squad) ?? fight.middle;
356
+ for (const unit of fight.units) {
357
+ if (!roles.hasTag(unit.type, "ranged") || unit.own?.hidden) continue;
358
+ const last = this.memory.kited[unit.id];
359
+ if (last !== void 0 && ai.tick - last < every) continue;
360
+ let closest;
361
+ let closestAt = Infinity;
362
+ for (const foe of melee) {
363
+ const d = distSq(unit, foe);
364
+ if (d < closestAt) {
365
+ closestAt = d;
366
+ closest = foe;
367
+ }
368
+ }
369
+ if (!closest) continue;
370
+ const theirs = view.strength.statsOf(closest);
371
+ const close = farthestReach(view.def(closest), theirs) + KITE_CLOSE;
372
+ if (closestAt > close * close) continue;
373
+ const mine = view.strength.statsOf(unit);
374
+ if (mine.moveSpeed < theirs.moveSpeed * KITE_FASTER) continue;
375
+ const range = farthestReach(view.def(unit), mine);
376
+ const step = Math.max(2, range - 1);
377
+ const dx = unit.x - closest.x;
378
+ const dz = unit.z - closest.z;
379
+ const length = Math.sqrt(dx * dx + dz * dz) || 1;
380
+ let to = {
381
+ x: unit.x + dx / length * step,
382
+ z: unit.z + dz / length * step
383
+ };
384
+ const fromMiddle = Math.sqrt(distSq(to, fight.middle));
385
+ if (fromMiddle > spread) to = {
386
+ x: fight.middle.x + (to.x - fight.middle.x) / fromMiddle * spread,
387
+ z: fight.middle.z + (to.z - fight.middle.z) / fromMiddle * spread
388
+ };
389
+ to = {
390
+ x: Math.min(width - 1, Math.max(1, to.x)),
391
+ z: Math.min(depth - 1, Math.max(1, to.z))
392
+ };
393
+ if (distSq(to, unit) < 2.25) continue;
394
+ this.memory.kited[unit.id] = ai.tick;
395
+ fight.kiting.push(unit.id);
396
+ ai.send({
397
+ type: "order",
398
+ entities: [unit.id],
399
+ order: {
400
+ type: "move",
401
+ point: to
402
+ }
403
+ });
404
+ ai.send({
405
+ type: "attack",
406
+ entities: [unit.id],
407
+ point: point(on),
408
+ queue: true
409
+ });
410
+ }
411
+ }
412
+ /**
413
+ * The siege units of a squad shoot buildings when there are any in their reach and no foe is upon them, and one
414
+ * that got ahead of the squad's middle is sent behind it: artillery is for walls, and dies to whatever reaches it
415
+ */
416
+ siegeOf(fight) {
417
+ if (this.options.smartArtillery === false) return;
418
+ const { ai } = this;
419
+ const { view } = ai;
420
+ const siege = fight.units.withRole("siege");
421
+ if (!siege.length) return;
422
+ const every = SIEGE_EVERY * ai.session.tickRate;
423
+ const threats = fight.foes.units();
424
+ const buildings = view.hostile.alive().buildings();
425
+ const on = ai.squads.whereOf(fight.squad) ?? fight.middle;
426
+ for (const unit of siege) {
427
+ if (unit.own?.hidden) continue;
428
+ const kept = this.memory.siege[unit.id];
429
+ if (threats.near(unit, SIEGE_THREATENED).length > 0) {
430
+ delete this.memory.siege[unit.id];
431
+ continue;
432
+ }
433
+ const range = farthestReach(view.def(unit), view.strength.statsOf(unit)) + 2;
434
+ const near = buildings.near(unit, range).visible();
435
+ const current = kept && near.find((building) => building.id === kept.target);
436
+ if (near.length && (!current || ai.tick - kept.since >= every)) {
437
+ const target = near.filter((building) => !!view.def(building).attacks?.length).sort((a, b) => distSq(a, unit) - distSq(b, unit))[0] ?? near.nearest(unit);
438
+ if (!current || current.id !== target.id) {
439
+ this.memory.siege[unit.id] = {
440
+ target: target.id,
441
+ since: ai.tick
442
+ };
443
+ ai.send({
444
+ type: "attack",
445
+ entities: [unit.id],
446
+ point: point(target),
447
+ target: target.id
448
+ });
449
+ ai.send({
450
+ type: "attack",
451
+ entities: [unit.id],
452
+ point: point(on),
453
+ queue: true
454
+ });
455
+ ai.decide(`${unit.type} ${unit.id} turns to the ${target.type} at ${where(target)}`, { kind: "micro" });
456
+ } else this.memory.siege[unit.id].since = ai.tick;
457
+ fight.siege.push(unit.id);
458
+ continue;
459
+ }
460
+ if (current) fight.siege.push(unit.id);
461
+ const foe = threats.nearest(unit);
462
+ if (!foe) continue;
463
+ if (Math.sqrt(distSq(fight.middle, foe)) - Math.sqrt(distSq(unit, foe)) <= 2 || kept && ai.tick - kept.since < every) continue;
464
+ const dx = fight.middle.x - foe.x;
465
+ const dz = fight.middle.z - foe.z;
466
+ const length = Math.sqrt(dx * dx + dz * dz) || 1;
467
+ const to = {
468
+ x: fight.middle.x + dx / length * SIEGE_BEHIND,
469
+ z: fight.middle.z + dz / length * SIEGE_BEHIND
470
+ };
471
+ this.memory.siege[unit.id] = {
472
+ target: 0,
473
+ since: ai.tick
474
+ };
475
+ fight.siege.push(unit.id);
476
+ ai.send({
477
+ type: "order",
478
+ entities: [unit.id],
479
+ order: {
480
+ type: "move",
481
+ point: to
482
+ }
483
+ });
484
+ ai.send({
485
+ type: "attack",
486
+ entities: [unit.id],
487
+ point: point(on),
488
+ queue: true
489
+ });
490
+ }
491
+ }
492
+ /** The share of its health under which a unit leaves a fight: heroes and units each their own; none for one that never does */
493
+ fleeAt(unit) {
494
+ const at = this.ai.view.hasRole(unit, "hero") ? this.options.heroesFlee ?? .35 : this.options.unitsFlee ?? .25;
495
+ return at === false || !(at > 0) ? void 0 : at;
496
+ }
497
+ /** How much of its health a unit has, 0 to 1 */
498
+ healthOf(unit) {
499
+ const stats = this.ai.view.strength.statsOf(unit);
500
+ return Math.max(0, Math.min(1, unit.health / Math.max(1, unit.maxHealth ?? stats.health)));
501
+ }
502
+ /** The units of a squad in a fight about to die leave it for safety */
503
+ flee(fight) {
504
+ for (const unit of fight.units) {
505
+ const at = this.fleeAt(unit);
506
+ if (at === void 0 || unit.own?.hidden) continue;
507
+ if (this.healthOf(unit) >= at) continue;
508
+ if (!fight.foes.some((foe) => distSq(unit, foe) <= 64)) continue;
509
+ this.sendToSafety(unit, fight.squad, "hurt");
510
+ }
511
+ }
512
+ /** With `removeInjuries`, the hurt units with something to heal them go home between fights */
513
+ injured() {
514
+ if (!this.options.removeInjuries) return;
515
+ const { ai } = this;
516
+ const { view } = ai;
517
+ const back = this.options.returnAt ?? .8;
518
+ const hostile = view.hostile.alive();
519
+ for (const squad of ai.squads.all()) {
520
+ if (!this.manages(squad) || this.fights.some((fight) => fight.squad === squad)) continue;
521
+ for (const unit of squad.units()) {
522
+ if (unit.own?.hidden || this.healthOf(unit) >= back) continue;
523
+ if (view.strength.statsOf(unit).healthRegen <= 0) continue;
524
+ if (hostile.near(unit, 14).length) continue;
525
+ this.sendToSafety(unit, squad, "injured");
526
+ }
527
+ }
528
+ }
529
+ /**
530
+ * Where a unit is safe: the nearest of its own finished buildings that no enemy strength reaches, else any of them,
531
+ * else home, else away from the foes
532
+ */
533
+ safety(unit, foes) {
534
+ const { view } = this.ai;
535
+ const buildings = view.mine.buildings().finished();
536
+ let best;
537
+ let bestAt = Infinity;
538
+ let safe = false;
539
+ for (const building of buildings) {
540
+ const quiet = view.threat.at(building).enemy === 0;
541
+ if (safe && !quiet) continue;
542
+ const d = distSq(unit, building);
543
+ if (quiet && !safe || d < bestAt) {
544
+ best = building;
545
+ bestAt = d;
546
+ safe = quiet;
547
+ }
548
+ }
549
+ if (best) return point(best);
550
+ const home = view.home();
551
+ if (home) return point(home);
552
+ const foe = foes.nearest(unit);
553
+ const dx = foe ? unit.x - foe.x : 1;
554
+ const dz = foe ? unit.z - foe.z : 0;
555
+ const length = Math.sqrt(dx * dx + dz * dz) || 1;
556
+ const { width, depth } = this.ai.session.terrain;
557
+ return {
558
+ x: Math.min(width - 1, Math.max(1, unit.x + dx / length * FLEE_AWAY)),
559
+ z: Math.min(depth - 1, Math.max(1, unit.z + dz / length * FLEE_AWAY))
560
+ };
561
+ }
562
+ /** Takes a unit out of its squad into the `fleeing` squad and sends it to safety; the squad's task goes on without it */
563
+ sendToSafety(unit, from, why) {
564
+ const { ai } = this;
565
+ const to = this.safety(unit, ai.view.hostile.alive());
566
+ const fleeing = ai.squads.named(FLEEING) ?? ai.squads.make(FLEEING, [], {
567
+ owner: OWNER,
568
+ retreatAt: false,
569
+ regroupWhen: false,
570
+ micro: false
571
+ });
572
+ if (!fleeing.current) fleeing.task(FLEE.id);
573
+ fleeing.add([unit.id], why === "hurt" ? "fled" : "sent to heal");
574
+ if (!fleeing.data.units.includes(unit.id)) return;
575
+ this.memory.fled[unit.id] = {
576
+ squad: from.name,
577
+ since: ai.tick,
578
+ to,
579
+ why
580
+ };
581
+ const state = fleeing.current;
582
+ if (state.phase === "starting") {
583
+ state.phase = "fleeing";
584
+ state.phaseSince = ai.tick;
585
+ }
586
+ state.memory.to ??= {};
587
+ state.memory.to[unit.id] = to;
588
+ ai.send({
589
+ type: "order",
590
+ entities: [unit.id],
591
+ order: {
592
+ type: "move",
593
+ point: to
594
+ }
595
+ });
596
+ ai.decide(why === "hurt" ? `${unit.type} ${unit.id} flees at ${percent(this.healthOf(unit))} to ${where(to)}` : `${unit.type} ${unit.id} goes to heal at ${where(to)}: ${percent(this.healthOf(unit))}`, { kind: "micro" });
597
+ }
598
+ /**
599
+ * Those that fled come back: at `returnAt` of their health, or, with nothing to heal them (or healing too slowly to
600
+ * wait for: `HEAL_WAIT`) and `ignoreInjured` not set, once safe for a while, to the pool at home. Back to the squad they left when it is still there, sent to it; else to the pool
601
+ */
602
+ back() {
603
+ const { ai } = this;
604
+ const { view } = ai;
605
+ const fleeing = ai.squads.named(FLEEING);
606
+ if (!fleeing) {
607
+ this.memory.fled = {};
608
+ return;
609
+ }
610
+ const back = this.options.returnAt ?? .8;
611
+ const hostile = view.hostile.alive();
612
+ const state = fleeing.current;
613
+ for (const unit of fleeing.units()) {
614
+ const fled = this.memory.fled[unit.id];
615
+ const health = this.healthOf(unit);
616
+ const healed = health >= back;
617
+ const stats = view.strength.statsOf(unit);
618
+ const slow = stats.healthRegen <= 0 || (back - health) * stats.health / stats.healthRegen > HEAL_WAIT;
619
+ let safe = false;
620
+ if (!healed && !this.options.ignoreInjured && slow) {
621
+ const since = fled?.since ?? fleeing.current?.since ?? ai.tick;
622
+ safe = ai.tick - since >= FLEE_SAFE * ai.session.tickRate && !hostile.near(unit, 14).length;
623
+ }
624
+ if (!healed && !safe) continue;
625
+ fleeing.remove([unit.id], "back");
626
+ if (state) delete state.memory.to?.[unit.id];
627
+ delete this.memory.fled[unit.id];
628
+ const squad = healed && fled?.squad ? ai.squads.named(fled.squad) : void 0;
629
+ if (squad && squad.alive && !squad.idle) {
630
+ squad.add([unit.id], "back from fleeing");
631
+ const join = squad.centre() ?? ai.squads.whereOf(squad);
632
+ if (squad.data.units.includes(unit.id) && join) ai.send({
633
+ type: "attack",
634
+ entities: [unit.id],
635
+ point: point(join)
636
+ });
637
+ ai.decide(`${unit.type} ${unit.id} back with ${squad.name} at ${percent(health)}`, { kind: "micro" });
638
+ } else ai.decide(`${unit.type} ${unit.id} back at ${percent(health)}`, { kind: "micro" });
639
+ }
640
+ if (!fleeing.data.units.length) fleeing.disband("no one fleeing");
641
+ }
642
+ /**
643
+ * Has units use the abilities that have to be aimed, where there is a fight near them: the brain's say first
644
+ * (`spells`), then the ability's own (`AbilityDef.ai`), then what the kit works out from the effects (`aim`). The
645
+ * ones on autocast look after themselves
646
+ */
647
+ spells() {
648
+ if (!this.begin("spells")) return;
649
+ this.cast = 0;
650
+ if (this.options.spells === false) return;
651
+ const { ai } = this;
652
+ const { view } = ai;
653
+ const { registry } = view;
654
+ const enemies = view.hostile.units().alive();
655
+ if (!enemies.length) return;
656
+ const friends = view.all.visible().units().where((entity, def) => !view.isHostile(entity) && !!def.attacks?.length);
657
+ for (const caster of view.mine) {
658
+ if (!caster.own?.abilities?.length || caster.own.hidden || caster.own.order === "cast") continue;
659
+ if (!enemies.near(caster, 12).length) continue;
660
+ for (const state of caster.own.abilities) {
661
+ const ability = registry.ability(state.id);
662
+ if (state.level < 1 || state.cooldown > 0 || state.charges === 0 || ability.target === "passive" || state.autocast) continue;
663
+ const rate = healthRate(registry, caster);
664
+ const cost = at(ability.manaCost, state.level);
665
+ if (rate > 0 ? cost * rate >= caster.health : cost > (caster.mana ?? 0)) continue;
666
+ const attacks = ability.attackRange ? view.strength.statsOf(caster).attackRange : 0;
667
+ const foes = enemies.near(caster, at(ability.range, state.level) + attacks + 4).items;
668
+ const near = friends.near(caster, 12).items;
669
+ const aim = this.aim(caster, ability, state.level, foes, near);
670
+ if (!aim) continue;
671
+ ai.send({
672
+ type: "cast",
673
+ entities: [caster.id],
674
+ ability: ability.id,
675
+ point: point(aim.point),
676
+ target: aim.target,
677
+ ...aim.to && { to: point(aim.to) }
678
+ });
679
+ this.cast++;
680
+ break;
681
+ }
682
+ }
683
+ }
684
+ /**
685
+ * Where to use an ability, or nothing when there is nothing worth it: the brain's `spells`, the ability's `ai`, then
686
+ * from its effects (a heal on the friend hurt most, something harmful on the nearest, an area where it catches most)
687
+ */
688
+ aim(caster, ability, level, enemies, friends) {
689
+ const { ai } = this;
690
+ const { view } = ai;
691
+ const { registry } = view;
692
+ const own = this.options.spells && this.options.spells[ability.id];
693
+ if (own) {
694
+ const decided = own(ai, caster, enemies, friends, level);
695
+ if (decided !== void 0) return decided ?? void 0;
696
+ }
697
+ if (ability.ai) {
698
+ const decided = ability.ai({
699
+ snapshot: ai.snapshot,
700
+ registry,
701
+ playerId: ai.playerId,
702
+ enemies: [...enemies],
703
+ friends: [...friends]
704
+ }, caster, level);
705
+ if (decided !== void 0) return decided ?? void 0;
706
+ }
707
+ if (!AIM_KINDS.includes(ability.target)) return void 0;
708
+ const harmful = (id) => !!id && !!registry.buff(id).harmful;
709
+ const now = lowerChain(ability.effects);
710
+ const hurts = now.flatMap((effect) => [effect, ...anyEffect(effect).effects ?? []]).some((effect) => effect.type === "damage" || effect.type === "buff" && harmful(effect.buff));
711
+ const layers = ability.targets?.layers ?? now.find((effect) => effect.layers)?.layers;
712
+ if (layers) enemies = enemies.filter((enemy) => layers.includes(view.def(enemy).flying ? "air" : "ground"));
713
+ const heals = now.find((effect) => effect.type === "heal");
714
+ const area = now.reduce((max, effect) => Math.max(max, declaredAt(effect.radius, level)), 0);
715
+ const maxHp = (entity) => entity.maxHealth ?? baseStats(view.def(entity), registry).health;
716
+ const nearest = (candidates) => {
717
+ let best;
718
+ let bestAt = Infinity;
719
+ for (const candidate of candidates) {
720
+ const d = distSq(caster, candidate);
721
+ if (d < bestAt) {
722
+ bestAt = d;
723
+ best = candidate;
724
+ }
725
+ }
726
+ return best;
727
+ };
728
+ if (ability.target === "unit") {
729
+ if (heals) {
730
+ const need = declaredAt(heals.amount, level) * .6;
731
+ const hurt = friends.filter((friend) => friend.id !== caster.id && maxHp(friend) - friend.health >= need).sort((a, b) => a.health / maxHp(a) - b.health / maxHp(b))[0];
732
+ return hurt && {
733
+ point: hurt,
734
+ target: hurt.id
735
+ };
736
+ }
737
+ if (hurts) {
738
+ const target = nearest(enemies);
739
+ return target && {
740
+ point: target,
741
+ target: target.id
742
+ };
743
+ }
744
+ const buff = now.find((effect) => effect.type === "buff")?.buff;
745
+ const target = friends.find((friend) => !friend.buffs?.includes(buff ?? ""));
746
+ return target && {
747
+ point: target,
748
+ target: target.id
749
+ };
750
+ }
751
+ if (ability.target === "vector") {
752
+ const target = nearest(enemies);
753
+ const reach = at(ability.range, level);
754
+ if (!target || distSq(caster, target) > reach * reach) return void 0;
755
+ const gap = Math.sqrt(distSq(caster, target)) || 1;
756
+ const on = {
757
+ x: target.x + (target.x - caster.x) / gap,
758
+ z: target.z + (target.z - caster.z) / gap
759
+ };
760
+ return {
761
+ point: {
762
+ x: target.x,
763
+ z: target.z
764
+ },
765
+ to: on
766
+ };
767
+ }
768
+ if (ability.target === "direction") {
769
+ const missile = now.find((effect) => effect.type === "missile");
770
+ const reach = at(missile?.distance, level, 10);
771
+ const target = nearest(enemies);
772
+ return target && distSq(caster, target) <= reach * reach ? { point: {
773
+ x: target.x,
774
+ z: target.z
775
+ } } : void 0;
776
+ }
777
+ if (hurts) {
778
+ const centres = ability.target === "none" ? [caster] : enemies;
779
+ const reach = area || 3;
780
+ const need = ability.ultimate || ability.requiresLevel ? 4 : 2;
781
+ let best;
782
+ let most = need - 1;
783
+ for (const centre of centres) {
784
+ const caught = enemies.filter((enemy) => distSq(centre, enemy) <= reach * reach).length;
785
+ if (caught > most) {
786
+ most = caught;
787
+ best = centre;
788
+ }
789
+ }
790
+ return best && { point: {
791
+ x: best.x,
792
+ z: best.z
793
+ } };
794
+ }
795
+ return enemies.some((enemy) => distSq(caster, enemy) < 64) ? { point: caster } : void 0;
796
+ }
797
+ /** Has units drink their potions when they need them, pick up what lies around, and heroes shop for what their list says */
798
+ items() {
799
+ if (!this.begin("items")) return;
800
+ const { ai } = this;
801
+ const { view } = ai;
802
+ const { registry } = view;
803
+ const potions = this.options.potions !== false;
804
+ const takeItems = this.options.takeItems !== false;
805
+ const hostile = view.hostile.alive();
806
+ for (const hero of view.mine) {
807
+ const inventory = hero.own && snapshotOf(hero, inventorySlots)?.slots;
808
+ if (!inventory || hero.own?.hidden) continue;
809
+ const stats = view.strength.statsOf(hero);
810
+ const maxHp = hero.maxHealth ?? stats.health;
811
+ const maxMana = hero.maxMana ?? stats.mana;
812
+ if (potions) {
813
+ let drank = false;
814
+ for (const slot of inventory) {
815
+ const ability = slot && registry.item(slot.item).ability;
816
+ if (!slot || !ability || slot.cooldown > 0 || slot.uses === 0) continue;
817
+ const effects = registry.ability(ability).effects;
818
+ const heals = effects.some((effect) => effect.type === "heal");
819
+ const restores = effects.some((effect) => effect.type === "mana");
820
+ if (heals && hero.health < maxHp * DRINK_HEALTH || restores && maxMana > 0 && (hero.mana ?? 0) < maxMana * DRINK_MANA) {
821
+ ai.send({
822
+ type: "order",
823
+ entities: [hero.id],
824
+ order: {
825
+ type: "cast",
826
+ item: slot.id
827
+ }
828
+ });
829
+ drank = true;
830
+ break;
831
+ }
832
+ }
833
+ if (drank) continue;
834
+ }
835
+ if (hero.own?.order) continue;
836
+ if (takeItems && inventory.includes(null)) {
837
+ let lying;
838
+ let lyingAt = 100;
839
+ for (const item of view.items) {
840
+ const d = distSq(item, hero);
841
+ if (d < lyingAt) {
842
+ lyingAt = d;
843
+ lying = item;
844
+ }
845
+ }
846
+ if (lying) {
847
+ ai.send({
848
+ type: "order",
849
+ entities: [hero.id],
850
+ order: {
851
+ type: "pickUp",
852
+ item: lying.id
853
+ }
854
+ });
855
+ continue;
856
+ }
857
+ }
858
+ }
859
+ this.shop(hostile);
860
+ this.hire(hostile);
861
+ }
862
+ /** What a hero shops for: its plan's list, the brain's, or the kit's (the cheapest item whose ability heals, when it carries none) */
863
+ wanted(hero) {
864
+ const { ai } = this;
865
+ const { registry } = ai.view;
866
+ const list = this.planOf(hero.type)?.items ?? this.options.shopping;
867
+ if (list === false) return void 0;
868
+ if (typeof list === "function") return list(ai, hero);
869
+ const slots = snapshotOf(hero, inventorySlots)?.slots ?? [];
870
+ const carried = (item) => slots.filter((slot) => slot?.item === item).length;
871
+ if (Array.isArray(list)) {
872
+ for (const line of list) {
873
+ if (!registry.items.has(line.item)) continue;
874
+ if (carried(line.item) >= (line.count ?? 1)) continue;
875
+ if (line.when !== void 0 && !evaluate(line.when, ai)) continue;
876
+ return line.item;
877
+ }
878
+ return;
879
+ }
880
+ const money = ai.purse.money;
881
+ const heals = (def) => !!def.ability && registry.abilities.has(def.ability) && registry.ability(def.ability).effects.some((effect) => effect.type === "heal");
882
+ if (slots.some((slot) => slot && heals(registry.item(slot.item)))) return void 0;
883
+ return registry.items.all().filter((def) => heals(def) && (def.cost[money] ?? 0) > 0).sort((a, b) => (a.cost[money] ?? 0) - (b.cost[money] ?? 0))[0]?.id;
884
+ }
885
+ /**
886
+ * Heroes with nothing to do walk to a shop in reach for what they want and buy it there: the money held in the purse
887
+ * on the way, paid as the `buy` is sent. Not in a fight, not on an errand
888
+ */
889
+ shop(hostile) {
890
+ if (this.options.buyItems === false) return;
891
+ const { ai } = this;
892
+ const { view } = ai;
893
+ const { registry } = view;
894
+ const selling = ai.cache("micro.selling", () => new Set(registry.units.all().flatMap((def) => def.sells?.length ? [def.id] : [])));
895
+ const shops = new UnitSet(view, view.all.known().filter((entity) => selling.has(entity.type) && !!snapshotOf(entity, shopStock) && !view.isHostile(entity)));
896
+ if (!shops.length) {
897
+ this.memory.shopping = {};
898
+ return;
899
+ }
900
+ const going = this.memory.shopping;
901
+ for (const hero of view.mine.heroes()) {
902
+ const own = hero.own;
903
+ const slots = own && snapshotOf(hero, inventorySlots)?.slots;
904
+ if (!own || !slots || own.hidden) continue;
905
+ const squad = ai.squads.squadOf(hero);
906
+ const busy = squad && !squad.idle || hostile.near(hero, 14).length > 0;
907
+ let errand = going[hero.id];
908
+ if (errand && (busy || !slots.includes(null))) {
909
+ delete going[hero.id];
910
+ errand = void 0;
911
+ }
912
+ if (busy) continue;
913
+ if (!errand) {
914
+ if (own.order || !slots.includes(null)) continue;
915
+ const item = this.wanted(hero);
916
+ if (!item || !registry.items.has(item)) continue;
917
+ const def = registry.item(item);
918
+ if (!ai.purse.affords(def.cost, 0, SHOPPING_PRIORITY)) continue;
919
+ const shop = shops.where((entity) => !!snapshotOf(entity, shopStock).find((stock) => stock.item === item && (stock.count === void 0 || stock.count > 0))).near(hero, SHOP_REACH).nearest(hero);
920
+ if (!shop) continue;
921
+ errand = going[hero.id] = {
922
+ shop: shop.id,
923
+ item,
924
+ since: ai.tick
925
+ };
926
+ ai.send({
927
+ type: "order",
928
+ entities: [hero.id],
929
+ order: {
930
+ type: "move",
931
+ point: point(shop)
932
+ }
933
+ });
934
+ ai.decide(`${hero.type} ${hero.id} goes to the ${shop.type} at ${where(shop)} for ${an(def.name || item)}`, { kind: "micro" });
935
+ }
936
+ const shop = view.byId(errand.shop);
937
+ const def = registry.item(errand.item);
938
+ if (!shop || !snapshotOf(shop, shopStock)?.some((stock) => stock.item === errand.item && (stock.count === void 0 || stock.count > 0))) {
939
+ delete going[hero.id];
940
+ continue;
941
+ }
942
+ const reach = AT_SHOP + view.def(shop).radius;
943
+ if (distSq(hero, shop) <= reach * reach) {
944
+ delete going[hero.id];
945
+ if (!ai.purse.spend(def.cost, SHOPPING_PRIORITY)) continue;
946
+ ai.send({
947
+ type: "buy",
948
+ shop: shop.id,
949
+ item: errand.item,
950
+ hero: hero.id
951
+ });
952
+ ai.decide(`${hero.type} ${hero.id} buys ${an(def.name || errand.item)} at the ${shop.type}`, { kind: "micro" });
953
+ continue;
954
+ }
955
+ ai.purse.reserve(`micro.shopping:${hero.id}`, def.cost, SHOPPING_PRIORITY);
956
+ if (!own.order && ai.tick - errand.since >= FLEE_RESEND * ai.session.tickRate) {
957
+ errand.since = ai.tick;
958
+ ai.send({
959
+ type: "order",
960
+ entities: [hero.id],
961
+ order: {
962
+ type: "move",
963
+ point: point(shop)
964
+ }
965
+ });
966
+ }
967
+ }
968
+ }
969
+ /** What it would hire at a place now, of what the place offers: its list's next, the function's, or the kit's (the strongest soldier for its price) */
970
+ toHire(offered) {
971
+ const { ai } = this;
972
+ const { view } = ai;
973
+ const { hiring } = this.options;
974
+ if (hiring === false || !offered.length) return void 0;
975
+ if (typeof hiring === "function") {
976
+ const id = hiring(ai, offered);
977
+ return id === void 0 ? void 0 : offered.find((def) => def.id === id);
978
+ }
979
+ if (Array.isArray(hiring)) {
980
+ for (const line of hiring) {
981
+ const def = offered.find((each) => each.id === line.unit);
982
+ if (!def) continue;
983
+ if (view.mine.ofType(def.id).length >= (line.count ?? 1)) continue;
984
+ if (line.when !== void 0 && !evaluate(line.when, ai)) continue;
985
+ return def;
986
+ }
987
+ return;
988
+ }
989
+ const money = ai.purse.money;
990
+ const soldiers = offered.filter((def) => !def.hero && view.hasRole(def.id, "soldier"));
991
+ if (view.mine.where((entity) => soldiers.some((def) => def.id === entity.type)).length >= HIRING_MOST) return void 0;
992
+ const worth = (def) => view.strength.of(def) / Math.max(1, def.cost?.[money] ?? 0);
993
+ const best = [...soldiers].sort((a, b) => worth(b) - worth(a))[0];
994
+ return best && ai.purse.affords(best.cost ?? {}, HIRING_SPARE, HIRING_PRIORITY) ? best : void 0;
995
+ }
996
+ /**
997
+ * Mercenaries: with supply free, a hero with nothing to do (or else an idle fighter of no squad's) walks to a place
998
+ * that hires in reach for what `toHire` says, the money held in the purse on the way and paid as the `hire` is sent.
999
+ * Not in a fight, not on an errand
1000
+ */
1001
+ hire(hostile) {
1002
+ if (this.options.hireUnits === false || this.options.hiring === false) return;
1003
+ const { ai } = this;
1004
+ const { view } = ai;
1005
+ const { registry } = view;
1006
+ const hiring = ai.cache("micro.hiring", () => new Set(registry.units.all().flatMap((def) => def.hires?.length ? [def.id] : [])));
1007
+ if (!hiring.size) return;
1008
+ const places = new UnitSet(view, view.all.known().filter((entity) => hiring.has(entity.type) && entity.health > 0 && !view.isHostile(entity)));
1009
+ const going = this.memory.hiring ??= {};
1010
+ if (!places.length) {
1011
+ this.memory.hiring = {};
1012
+ return;
1013
+ }
1014
+ const offeredAt = (place) => (view.def(place).hires ?? []).filter((id) => registry.units.has(id)).map((id) => registry.unit(id));
1015
+ const { me } = view;
1016
+ const busy = (unit) => {
1017
+ const squad = ai.squads.squadOf(unit);
1018
+ return squad && !squad.idle || hostile.near(unit, 14).length > 0;
1019
+ };
1020
+ for (const [id, errand] of Object.entries(going)) {
1021
+ const unit = view.byId(Number(id));
1022
+ const place = view.byId(errand.place);
1023
+ if (!unit || !place || unit.health <= 0 || busy(unit) || !(view.def(place).hires ?? []).includes(errand.unit)) {
1024
+ delete going[id];
1025
+ continue;
1026
+ }
1027
+ const def = registry.unit(errand.unit);
1028
+ const reach = AT_SHOP + view.def(place).radius;
1029
+ if (distSq(unit, place) <= reach * reach) {
1030
+ delete going[id];
1031
+ const supply = supplyOf(def);
1032
+ if (supply > 0 && me.supplyUsed + supply > me.supplyCap || !ai.purse.spend(def.cost ?? {}, HIRING_PRIORITY)) continue;
1033
+ me.supplyUsed += supply;
1034
+ ai.send({
1035
+ type: "hire",
1036
+ shop: place.id,
1037
+ unit: errand.unit
1038
+ });
1039
+ ai.decide(`hires ${an(def.name || errand.unit)} at the ${place.type}`, { kind: "micro" });
1040
+ continue;
1041
+ }
1042
+ ai.purse.reserve(`micro.hiring:${id}`, def.cost ?? {}, HIRING_PRIORITY);
1043
+ if (!unit.own?.order && ai.tick - errand.since >= FLEE_RESEND * ai.session.tickRate) {
1044
+ errand.since = ai.tick;
1045
+ ai.send({
1046
+ type: "order",
1047
+ entities: [unit.id],
1048
+ order: {
1049
+ type: "move",
1050
+ point: point(place)
1051
+ }
1052
+ });
1053
+ }
1054
+ }
1055
+ if (Object.keys(going).length) return;
1056
+ const idle = (unit) => !!unit.own && !unit.own.hidden && !unit.own.order && !busy(unit);
1057
+ const runners = [...view.mine.heroes().where(idle), ...view.mine.fighters().where((unit, def) => !def.hero && idle(unit) && !ai.squads.squadOf(unit))];
1058
+ for (const runner of runners) {
1059
+ const place = places.near(runner, SHOP_REACH).nearest(runner);
1060
+ if (!place) continue;
1061
+ const def = this.toHire(offeredAt(place));
1062
+ if (!def) return;
1063
+ const supply = supplyOf(def);
1064
+ if (supply > 0 && me.supplyUsed + supply > me.supplyCap) return;
1065
+ if (!ai.purse.affords(def.cost ?? {}, 0, HIRING_PRIORITY)) return;
1066
+ going[runner.id] = {
1067
+ place: place.id,
1068
+ unit: def.id,
1069
+ since: ai.tick
1070
+ };
1071
+ ai.send({
1072
+ type: "order",
1073
+ entities: [runner.id],
1074
+ order: {
1075
+ type: "move",
1076
+ point: point(place)
1077
+ }
1078
+ });
1079
+ ai.decide(`${runner.type} ${runner.id} goes to the ${place.type} at ${where(place)} to hire ${an(def.name || def.id)}`, { kind: "micro" });
1080
+ return;
1081
+ }
1082
+ }
1083
+ /** The plan for a hero type, where the brain's `heroes` is a list */
1084
+ planOf(type) {
1085
+ return Array.isArray(this.options.heroes) ? this.options.heroes.find((plan) => plan.type === type) : void 0;
1086
+ }
1087
+ /**
1088
+ * Which hero to make next of those that could be made (at an altar, of the player's race, not had): the first of the
1089
+ * brain's `heroes` that could be and whose chance came up, or what its function says; else the first candidate
1090
+ */
1091
+ nextHero(candidates, had) {
1092
+ const free = candidates.filter((def) => !had.includes(def.id));
1093
+ if (!free.length) return void 0;
1094
+ const { heroes } = this.options;
1095
+ if (typeof heroes === "function") {
1096
+ const picked = heroes(this.ai, free);
1097
+ if (picked === void 0) return void 0;
1098
+ return typeof picked === "string" ? free.find((def) => def.id === picked) : picked;
1099
+ }
1100
+ if (Array.isArray(heroes)) {
1101
+ for (let i = 0; i < heroes.length; i++) {
1102
+ const plan = heroes[i];
1103
+ const def = free.find((each) => each.id === plan.type);
1104
+ if (!def) continue;
1105
+ const chance = plan.chance ?? 1;
1106
+ if (chance < 1) {
1107
+ this.memory.rolled[i] ??= this.ai.rng.next() < chance;
1108
+ if (!this.memory.rolled[i]) continue;
1109
+ }
1110
+ return def;
1111
+ }
1112
+ return;
1113
+ }
1114
+ return free[0];
1115
+ }
1116
+ /**
1117
+ * Which skill a hero learns next of those it may: its plan's order (the next line not yet learned to that level),
1118
+ * else the ultimate as soon as it can be had, else whatever is furthest behind
1119
+ */
1120
+ nextSkill(hero, learnable, now = true) {
1121
+ if (!learnable.length) return void 0;
1122
+ const plan = this.planOf(hero.type);
1123
+ if (typeof plan?.skills === "function") return plan.skills(this.ai, hero, learnable);
1124
+ if (Array.isArray(plan?.skills)) {
1125
+ const counted = {};
1126
+ for (const id of plan.skills) {
1127
+ counted[id] = (counted[id] ?? 0) + 1;
1128
+ const skill = learnable.find((each) => each.id === id);
1129
+ if (!skill || skill.level >= counted[id]) continue;
1130
+ return skill.available || !now ? id : void 0;
1131
+ }
1132
+ }
1133
+ return (now ? learnable.filter((skill) => skill.available) : [...learnable]).sort((a, b) => a.maxLevel - b.maxLevel || a.level - b.level)[0]?.id;
1134
+ }
1135
+ /** Has heroes put the points they have into their skills, in the order their plan says */
1136
+ heroes() {
1137
+ if (!this.begin("heroes")) return;
1138
+ const { ai } = this;
1139
+ for (const hero of ai.view.mine.heroes()) {
1140
+ const info = heroOfState(hero);
1141
+ if (!info?.points || !info.learnable || hero.own?.hidden) continue;
1142
+ const next = this.nextSkill(hero, info.learnable);
1143
+ if (!next) continue;
1144
+ ai.send({
1145
+ type: "learn",
1146
+ entity: hero.id,
1147
+ ability: next
1148
+ });
1149
+ ai.decide(`${hero.type} ${hero.id} learns ${next}`, { kind: "micro" });
1150
+ }
1151
+ }
1152
+ /** Whether a part of the think is still to be done this think: it is, once, for whoever asks first */
1153
+ begin(part) {
1154
+ if (this.thoughtAt[part] === this.ai.tick) return false;
1155
+ this.thoughtAt[part] = this.ai.tick;
1156
+ return true;
1157
+ }
1158
+ /** Marks a part of the think done: one a brain's own turn did itself, or left to the units (a slip) */
1159
+ done(part) {
1160
+ this.thoughtAt[part] = this.ai.tick;
1161
+ }
1162
+ /** Drops what is remembered of units that are gone */
1163
+ prune() {
1164
+ const { view } = this.ai;
1165
+ const gone = (id) => !view.mine.has(Number(id));
1166
+ for (const id in this.memory.kited) if (gone(id)) delete this.memory.kited[id];
1167
+ for (const id in this.memory.siege) if (gone(id)) delete this.memory.siege[id];
1168
+ for (const id in this.memory.fled) if (gone(id)) delete this.memory.fled[id];
1169
+ for (const id in this.memory.shopping) if (gone(id)) delete this.memory.shopping[id];
1170
+ }
1171
+ /** The fights and the rest, as the report shows them */
1172
+ report() {
1173
+ const { ai } = this;
1174
+ const { view } = ai;
1175
+ const fleeing = ai.squads.named(FLEEING);
1176
+ const fled = this.memory.fled;
1177
+ return {
1178
+ fights: this.fights.map((fight) => {
1179
+ const kept = this.memory.focus[fight.squad.name];
1180
+ return {
1181
+ squad: fight.squad.name,
1182
+ foes: fight.foes.length,
1183
+ odds: Math.round(fight.odds * 100) / 100,
1184
+ ...fight.target && kept && { target: {
1185
+ id: fight.target.id,
1186
+ type: fight.target.type,
1187
+ since: kept.since
1188
+ } },
1189
+ kiting: [...fight.kiting],
1190
+ siege: [...fight.siege]
1191
+ };
1192
+ }),
1193
+ fleeing: (fleeing?.units().items ?? []).map((unit) => ({
1194
+ unit: unit.id,
1195
+ type: unit.type,
1196
+ health: Math.round(this.healthOf(unit) * 100) / 100,
1197
+ to: pair(fled[unit.id]?.to ?? unit),
1198
+ since: fled[unit.id]?.since ?? 0,
1199
+ why: fled[unit.id]?.why ?? "hurt"
1200
+ })),
1201
+ heroes: view.mine.heroes().map((hero) => {
1202
+ const info = heroOfState(hero);
1203
+ const next = info?.learnable ? this.nextSkill(hero, info.learnable, false) : void 0;
1204
+ return {
1205
+ id: hero.id,
1206
+ type: hero.type,
1207
+ level: info?.level ?? 1,
1208
+ ...next && { next }
1209
+ };
1210
+ }),
1211
+ shopping: Object.entries(this.memory.shopping).map(([hero, errand]) => ({
1212
+ hero: Number(hero),
1213
+ ...errand
1214
+ })),
1215
+ hiring: Object.entries(this.memory.hiring ?? {}).map(([by, errand]) => ({
1216
+ by: Number(by),
1217
+ ...errand
1218
+ })),
1219
+ cast: this.cast,
1220
+ ...this.slipped && { slipped: this.slipped }
1221
+ };
1222
+ }
1223
+ /** What it remembers, for a save: a copy */
1224
+ /** Whether it has anything to remember now: one that does not is left out of a save */
1225
+ remembers() {
1226
+ return this.enabled;
1227
+ }
1228
+ /** Its part of the brain's report */
1229
+ reportTo(report) {
1230
+ report.micro = this.report();
1231
+ }
1232
+ /** Gives a copy of the micro's memory, for a save of the brain */
1233
+ save() {
1234
+ return structuredClone(this.memory);
1235
+ }
1236
+ /** Takes back what `save` gave: whether it was read */
1237
+ restore(memory) {
1238
+ const given = memory;
1239
+ if (!given || typeof given !== "object" || given.v !== 1) return false;
1240
+ this.memory = {
1241
+ v: 1,
1242
+ focus: { ...given.focus ?? {} },
1243
+ kited: { ...given.kited ?? {} },
1244
+ fled: structuredClone(given.fled ?? {}),
1245
+ siege: { ...given.siege ?? {} },
1246
+ shopping: structuredClone(given.shopping ?? {}),
1247
+ ...given.hiring && { hiring: structuredClone(given.hiring) },
1248
+ rolled: { ...given.rolled ?? {} }
1249
+ };
1250
+ return true;
1251
+ }
1252
+ };
1253
+ /**
1254
+ * The task of the `fleeing` squad: each of its units on its way to its own safety (`state.memory.to`, by unit id), those
1255
+ * that stopped short sent again; never over by itself: the micro module takes the units out as they heal
1256
+ */
1257
+ var FLEE = defineTask({
1258
+ id: "flee",
1259
+ fighting: false,
1260
+ start(ai, squad, state) {
1261
+ state.phase = "fleeing";
1262
+ state.phaseSince = ai.tick;
1263
+ const to = state.memory.to ?? {};
1264
+ for (const id of squad.data.units) if (to[id]) squad.order({
1265
+ type: "move",
1266
+ point: to[id]
1267
+ }, [id]);
1268
+ },
1269
+ think(_ai, squad, state) {
1270
+ if (!squad.mayResend()) return;
1271
+ const to = state.memory.to ?? {};
1272
+ for (const unit of squad.idleUnits()) {
1273
+ const there = to[unit.id];
1274
+ if (there && distSq(unit, there) > 16) squad.order({
1275
+ type: "move",
1276
+ point: there
1277
+ }, [unit.id]);
1278
+ }
1279
+ },
1280
+ handles: [
1281
+ "retreat",
1282
+ "regroup",
1283
+ "reinforce"
1284
+ ]
1285
+ });
1286
+ /**
1287
+ * The micro module: the fights of the brain's squads each think, after the squads sent and watched their tasks
1288
+ * (`ai.micro.think`): focus fire, kiting, siege, fleeing and coming back, spells, items, the heroes' skills. With how it
1289
+ * fights where the brain's definition and the seat's options say nothing (`MicroOptions`)
1290
+ *
1291
+ * @beta
1292
+ */
1293
+ var micro = (options = {}) => defineModule({
1294
+ id: "micro",
1295
+ make: (ai) => {
1296
+ ai.area(Micro).configure(options);
1297
+ return {
1298
+ id: "micro",
1299
+ phase: "fight",
1300
+ think: () => ai.area(Micro).think()
1301
+ };
1302
+ }
1303
+ });
1304
+ /** What a unit pays in health for each point of mana, by the buffs it carries (`BuffDef.paysWithHealth`): 0 for mana */
1305
+ function healthRate(registry, unit) {
1306
+ let rate = 0;
1307
+ for (const buff of unit.buffs ?? []) {
1308
+ const pays = registry.buffs.has(buff) ? registry.buff(buff).paysWithHealth : void 0;
1309
+ if (pays) rate = Math.max(rate, pays === true ? 1 : pays);
1310
+ }
1311
+ return rate;
1312
+ }
1313
+ //#endregion
1314
+ export { Micro, micro };
1315
+
1316
+ //# sourceMappingURL=micro.js.map