@v12-engine/engine 0.0.0-stage → 0.1.1

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 (341) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abilities/buffs.d.ts +83 -0
  3. package/dist/abilities/castTold.d.ts +12 -0
  4. package/dist/abilities/charges.d.ts +28 -0
  5. package/dist/abilities/dispel.d.ts +9 -0
  6. package/dist/abilities/effectFields.d.ts +10 -0
  7. package/dist/abilities/effects/buff.d.ts +8 -0
  8. package/dist/abilities/effects/core.d.ts +1 -0
  9. package/dist/abilities/effects/damage.d.ts +1 -0
  10. package/dist/abilities/effects/heal.d.ts +2 -0
  11. package/dist/abilities/effects/missile.d.ts +1 -0
  12. package/dist/abilities/effects/moves.d.ts +11 -0
  13. package/dist/abilities/effects/passives.d.ts +15 -0
  14. package/dist/abilities/effects/sight.d.ts +4 -0
  15. package/dist/abilities/effects/spawn.d.ts +2 -0
  16. package/dist/abilities/effects/timed.d.ts +4 -0
  17. package/dist/abilities/effects/trade.d.ts +1 -0
  18. package/dist/abilities/effects.d.ts +122 -0
  19. package/dist/abilities/land.d.ts +21 -0
  20. package/dist/abilities/scaled.d.ts +21 -0
  21. package/dist/abilities/text.d.ts +113 -0
  22. package/dist/ai/area.d.ts +53 -0
  23. package/dist/ai/brain.d.ts +528 -0
  24. package/dist/ai/budget.d.ts +67 -0
  25. package/dist/ai/checks.d.ts +115 -0
  26. package/dist/ai/computer.d.ts +166 -0
  27. package/dist/ai/defence.d.ts +108 -0
  28. package/dist/ai/define.d.ts +21 -0
  29. package/dist/ai/economy.d.ts +129 -0
  30. package/dist/ai/geometry.d.ts +35 -0
  31. package/dist/ai/goals.d.ts +360 -0
  32. package/dist/ai/index.d.ts +38 -0
  33. package/dist/ai/knowledge.d.ts +418 -0
  34. package/dist/ai/lanes.d.ts +232 -0
  35. package/dist/ai/melee/build.d.ts +61 -0
  36. package/dist/ai/melee/goals.d.ts +299 -0
  37. package/dist/ai/melee/heroes.d.ts +27 -0
  38. package/dist/ai/melee/index.d.ts +14 -0
  39. package/dist/ai/melee/production.d.ts +8 -0
  40. package/dist/ai/melee/surrender.d.ts +24 -0
  41. package/dist/ai/micro.d.ts +278 -0
  42. package/dist/ai/mission.d.ts +195 -0
  43. package/dist/ai/missionRules.d.ts +18 -0
  44. package/dist/ai/module.d.ts +116 -0
  45. package/dist/ai/options.d.ts +61 -0
  46. package/dist/ai/plans/build.d.ts +280 -0
  47. package/dist/ai/plans/placement.d.ts +82 -0
  48. package/dist/ai/plans/plans.d.ts +105 -0
  49. package/dist/ai/plans/production.d.ts +210 -0
  50. package/dist/ai/plans/purse.d.ts +73 -0
  51. package/dist/ai/plans/tech.d.ts +37 -0
  52. package/dist/ai/profiles.d.ts +204 -0
  53. package/dist/ai/reach.d.ts +4 -0
  54. package/dist/ai/report.d.ts +203 -0
  55. package/dist/ai/roles.d.ts +133 -0
  56. package/dist/ai/rules.d.ts +288 -0
  57. package/dist/ai/scouting.d.ts +98 -0
  58. package/dist/ai/settings.d.ts +73 -0
  59. package/dist/ai/squads.d.ts +429 -0
  60. package/dist/ai/strength.d.ts +167 -0
  61. package/dist/ai/task.d.ts +118 -0
  62. package/dist/ai/tasks/attack.d.ts +7 -0
  63. package/dist/ai/tasks/capture.d.ts +21 -0
  64. package/dist/ai/tasks/creep.d.ts +16 -0
  65. package/dist/ai/tasks/defend.d.ts +29 -0
  66. package/dist/ai/tasks/drop.d.ts +34 -0
  67. package/dist/ai/tasks/escort.d.ts +16 -0
  68. package/dist/ai/tasks/gather.d.ts +23 -0
  69. package/dist/ai/tasks/harass.d.ts +7 -0
  70. package/dist/ai/tasks/hold.d.ts +20 -0
  71. package/dist/ai/tasks/index.d.ts +32 -0
  72. package/dist/ai/tasks/move.d.ts +19 -0
  73. package/dist/ai/tasks/patrol.d.ts +8 -0
  74. package/dist/ai/tasks/retreat.d.ts +20 -0
  75. package/dist/ai/tasks/scout.d.ts +29 -0
  76. package/dist/ai/tasks/shared.d.ts +74 -0
  77. package/dist/ai/team.d.ts +155 -0
  78. package/dist/ai/threat.d.ts +91 -0
  79. package/dist/ai/view.d.ts +366 -0
  80. package/dist/ai/waves.d.ts +126 -0
  81. package/dist/ai.js +6239 -0
  82. package/dist/ai.js.map +1 -0
  83. package/dist/aiTesting.d.ts +179 -0
  84. package/dist/areas.d.ts +149 -0
  85. package/dist/attacks.d.ts +66 -0
  86. package/dist/attributes.d.ts +66 -0
  87. package/dist/brain-BvVdUhX8.js +7659 -0
  88. package/dist/brain-BvVdUhX8.js.map +1 -0
  89. package/dist/builds-C6LfgvEU.js +460 -0
  90. package/dist/builds-C6LfgvEU.js.map +1 -0
  91. package/dist/bytes.d.ts +6 -0
  92. package/dist/camps.d.ts +95 -0
  93. package/dist/capture.d.ts +131 -0
  94. package/dist/cellLayers.d.ts +75 -0
  95. package/dist/cinematics.d.ts +194 -0
  96. package/dist/clock.d.ts +32 -0
  97. package/dist/commands.d.ts +235 -0
  98. package/dist/components.d.ts +184 -0
  99. package/dist/computers.d.ts +108 -0
  100. package/dist/concealment.d.ts +61 -0
  101. package/dist/coreComponents-syuh2fPG.js +5149 -0
  102. package/dist/coreComponents-syuh2fPG.js.map +1 -0
  103. package/dist/coreComponents.d.ts +1 -0
  104. package/dist/dashing.d.ts +8 -0
  105. package/dist/debug.d.ts +36 -0
  106. package/dist/debug.js +3 -0
  107. package/dist/debugCommands-CzjrSm66.js +14739 -0
  108. package/dist/debugCommands-CzjrSm66.js.map +1 -0
  109. package/dist/debugCommands.d.ts +213 -0
  110. package/dist/debugging.d.ts +10 -0
  111. package/dist/definitions.d.ts +43 -0
  112. package/dist/defs.d.ts +1162 -0
  113. package/dist/denying.d.ts +81 -0
  114. package/dist/destructibles.d.ts +27 -0
  115. package/dist/determinism-BCymQwiE.js +518 -0
  116. package/dist/determinism-BCymQwiE.js.map +1 -0
  117. package/dist/determinism.d.ts +121 -0
  118. package/dist/dialog.d.ts +94 -0
  119. package/dist/effectRefs.d.ts +16 -0
  120. package/dist/effects.d.ts +80 -0
  121. package/dist/endings.d.ts +22 -0
  122. package/dist/engagement.d.ts +108 -0
  123. package/dist/engineEvents.d.ts +710 -0
  124. package/dist/entity.d.ts +409 -0
  125. package/dist/entityIndex.d.ts +50 -0
  126. package/dist/errors.d.ts +85 -0
  127. package/dist/events.d.ts +97 -0
  128. package/dist/exactMath.d.ts +63 -0
  129. package/dist/features.d.ts +10 -0
  130. package/dist/fields.d.ts +114 -0
  131. package/dist/fixture.d.ts +17 -0
  132. package/dist/fog.d.ts +110 -0
  133. package/dist/formation.d.ts +111 -0
  134. package/dist/friendlyFire.d.ts +26 -0
  135. package/dist/game-DiJEN-Ks.js +5800 -0
  136. package/dist/game-DiJEN-Ks.js.map +1 -0
  137. package/dist/game.d.ts +501 -0
  138. package/dist/gameData.d.ts +325 -0
  139. package/dist/gameFiles.d.ts +26 -0
  140. package/dist/gates.d.ts +28 -0
  141. package/dist/generate.d.ts +403 -0
  142. package/dist/generateWorker.d.ts +39 -0
  143. package/dist/grid.d.ts +53 -0
  144. package/dist/ground.d.ts +127 -0
  145. package/dist/groundSpeed.d.ts +22 -0
  146. package/dist/hero.d.ts +177 -0
  147. package/dist/home.d.ts +14 -0
  148. package/dist/hooks.d.ts +780 -0
  149. package/dist/hotReload.d.ts +76 -0
  150. package/dist/ids.d.ts +26 -0
  151. package/dist/index.d.ts +227 -0
  152. package/dist/index.js +4701 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/inspect-D9dWHmZ0.js +491 -0
  155. package/dist/inspect-D9dWHmZ0.js.map +1 -0
  156. package/dist/inspect.d.ts +176 -0
  157. package/dist/inventory.d.ts +18 -0
  158. package/dist/items.d.ts +91 -0
  159. package/dist/lanes.d.ts +213 -0
  160. package/dist/life.d.ts +53 -0
  161. package/dist/local-Dkovq42k.js +1379 -0
  162. package/dist/local-Dkovq42k.js.map +1 -0
  163. package/dist/log.d.ts +140 -0
  164. package/dist/manaBurn.d.ts +39 -0
  165. package/dist/map/file.d.ts +114 -0
  166. package/dist/map/images.d.ts +18 -0
  167. package/dist/map/look.d.ts +47 -0
  168. package/dist/map/pathProfile.d.ts +13 -0
  169. package/dist/map/resize.d.ts +54 -0
  170. package/dist/map/schema.d.ts +10 -0
  171. package/dist/map/terrain.d.ts +32 -0
  172. package/dist/map/types.d.ts +613 -0
  173. package/dist/map.d.ts +7 -0
  174. package/dist/mapCheck/cells.d.ts +19 -0
  175. package/dist/mapCheck/rule.d.ts +30 -0
  176. package/dist/mapCheck/rules/names.d.ts +3 -0
  177. package/dist/mapCheck/rules/objects.d.ts +3 -0
  178. package/dist/mapCheck/rules/paths.d.ts +3 -0
  179. package/dist/mapCheck/rules/players.d.ts +3 -0
  180. package/dist/mapCheck/rules/races.d.ts +3 -0
  181. package/dist/mapCheck/rules/random.d.ts +3 -0
  182. package/dist/mapCheck/rules/regions.d.ts +3 -0
  183. package/dist/mapCheck/rules/targets.d.ts +3 -0
  184. package/dist/mapCheck/rules/walking.d.ts +3 -0
  185. package/dist/mapCheck.d.ts +23 -0
  186. package/dist/mapFields.d.ts +364 -0
  187. package/dist/mapFile.d.ts +23 -0
  188. package/dist/mapMeasure.d.ts +95 -0
  189. package/dist/mapMerge.d.ts +19 -0
  190. package/dist/mapObjectives.d.ts +82 -0
  191. package/dist/mapObjects.d.ts +1 -0
  192. package/dist/math.d.ts +44 -0
  193. package/dist/messages.d.ts +150 -0
  194. package/dist/missionRules-C-bGxm0Q.js +523 -0
  195. package/dist/missionRules-C-bGxm0Q.js.map +1 -0
  196. package/dist/missionRules.d.ts +179 -0
  197. package/dist/mods.d.ts +146 -0
  198. package/dist/names.d.ts +93 -0
  199. package/dist/navigation/agentParams.d.ts +4 -0
  200. package/dist/navigation/air.d.ts +89 -0
  201. package/dist/navigation/builds.d.ts +140 -0
  202. package/dist/navigation/groundAreas.d.ts +23 -0
  203. package/dist/navigation/navigation.d.ts +127 -0
  204. package/dist/navigation/recast.d.ts +214 -0
  205. package/dist/navigation/sidePaths.d.ts +69 -0
  206. package/dist/navigation/sized.d.ts +1 -0
  207. package/dist/navigation-worker.js +11 -0
  208. package/dist/navigation-worker.js.map +1 -0
  209. package/dist/nearest.d.ts +8 -0
  210. package/dist/noise.d.ts +12 -0
  211. package/dist/objectives.d.ts +93 -0
  212. package/dist/orders/basic.d.ts +96 -0
  213. package/dist/orders/build.d.ts +91 -0
  214. package/dist/orders/cast.d.ts +105 -0
  215. package/dist/orders/facts.d.ts +14 -0
  216. package/dist/orders/harvest.d.ts +94 -0
  217. package/dist/orders/idle.d.ts +7 -0
  218. package/dist/orders/items.d.ts +14 -0
  219. package/dist/orders/queue.d.ts +24 -0
  220. package/dist/pack.schema.json +6621 -0
  221. package/dist/packs/director/index.d.ts +81 -0
  222. package/dist/packs/heroes/campaign.d.ts +137 -0
  223. package/dist/packs/heroes/carry.d.ts +59 -0
  224. package/dist/packs/heroes/commands.d.ts +6 -0
  225. package/dist/packs/heroes/hire.d.ts +9 -0
  226. package/dist/packs/heroes/index.d.ts +12 -0
  227. package/dist/packs/heroes/making.d.ts +16 -0
  228. package/dist/packs/heroes/respawn.d.ts +42 -0
  229. package/dist/packs/moba/index.d.ts +34 -0
  230. package/dist/packs/pack.d.ts +84 -0
  231. package/dist/packs-g5thvmGn.js +3199 -0
  232. package/dist/packs-g5thvmGn.js.map +1 -0
  233. package/dist/packs.d.ts +84 -0
  234. package/dist/paths.d.ts +51 -0
  235. package/dist/plain.d.ts +17 -0
  236. package/dist/player.d.ts +117 -0
  237. package/dist/portals.d.ts +66 -0
  238. package/dist/prefabs.d.ts +139 -0
  239. package/dist/presetBuildings.d.ts +52 -0
  240. package/dist/presetGround.d.ts +22 -0
  241. package/dist/profiles-B3NS9jwk.js +335 -0
  242. package/dist/profiles-B3NS9jwk.js.map +1 -0
  243. package/dist/races.d.ts +136 -0
  244. package/dist/randomGroups.d.ts +2 -0
  245. package/dist/registry.d.ts +464 -0
  246. package/dist/remains.d.ts +119 -0
  247. package/dist/replication.d.ts +103 -0
  248. package/dist/rng.d.ts +17 -0
  249. package/dist/rules.d.ts +395 -0
  250. package/dist/rulesCheck.d.ts +37 -0
  251. package/dist/runes.d.ts +41 -0
  252. package/dist/save.d.ts +277 -0
  253. package/dist/scenario.d.ts +56 -0
  254. package/dist/scheduler.d.ts +67 -0
  255. package/dist/score.d.ts +306 -0
  256. package/dist/sequences.d.ts +132 -0
  257. package/dist/server/doorman.d.ts +21 -0
  258. package/dist/server/gameServer.d.ts +346 -0
  259. package/dist/server/index.d.ts +24 -0
  260. package/dist/server/lobby.d.ts +1 -0
  261. package/dist/server/log.d.ts +13 -0
  262. package/dist/server/match.d.ts +24 -0
  263. package/dist/server/mode.d.ts +168 -0
  264. package/dist/server/navigation-worker.d.ts +1 -0
  265. package/dist/server/navigation.d.ts +11 -0
  266. package/dist/server/ops.d.ts +78 -0
  267. package/dist/server/packs.d.ts +15 -0
  268. package/dist/server/ratings.d.ts +62 -0
  269. package/dist/server/relay.d.ts +34 -0
  270. package/dist/server/rooms.d.ts +162 -0
  271. package/dist/server/seat.d.ts +2 -0
  272. package/dist/server/seatSettings.d.ts +15 -0
  273. package/dist/server/secret.d.ts +5 -0
  274. package/dist/server/start.d.ts +54 -0
  275. package/dist/server/websocket.d.ts +74 -0
  276. package/dist/server.js +2861 -0
  277. package/dist/server.js.map +1 -0
  278. package/dist/session/can.d.ts +20 -0
  279. package/dist/session/commandReplay.d.ts +92 -0
  280. package/dist/session/debug.d.ts +65 -0
  281. package/dist/session/delay.d.ts +15 -0
  282. package/dist/session/delta.d.ts +98 -0
  283. package/dist/session/entityState.d.ts +1 -0
  284. package/dist/session/local.d.ts +214 -0
  285. package/dist/session/memory.d.ts +27 -0
  286. package/dist/session/protocol.d.ts +1155 -0
  287. package/dist/session/remote.d.ts +530 -0
  288. package/dist/session/replay.d.ts +114 -0
  289. package/dist/session/seed.d.ts +7 -0
  290. package/dist/session/share.d.ts +78 -0
  291. package/dist/session/socket.d.ts +8 -0
  292. package/dist/session/wire.d.ts +153 -0
  293. package/dist/session/worker.d.ts +227 -0
  294. package/dist/shared.d.ts +171 -0
  295. package/dist/sides.d.ts +75 -0
  296. package/dist/sight.d.ts +27 -0
  297. package/dist/simulate-oXBiw1Ff.js +167 -0
  298. package/dist/simulate-oXBiw1Ff.js.map +1 -0
  299. package/dist/simulate-worker.d.ts +1 -0
  300. package/dist/simulate-worker.js +28 -0
  301. package/dist/simulate-worker.js.map +1 -0
  302. package/dist/simulate.d.ts +154 -0
  303. package/dist/smart.d.ts +9 -0
  304. package/dist/spatial.d.ts +62 -0
  305. package/dist/spawning.d.ts +33 -0
  306. package/dist/stances.d.ts +76 -0
  307. package/dist/start.d.ts +71 -0
  308. package/dist/stats.d.ts +122 -0
  309. package/dist/summons.d.ts +63 -0
  310. package/dist/systems/abilities.d.ts +3 -0
  311. package/dist/systems/combat.d.ts +71 -0
  312. package/dist/systems/combatTold.d.ts +14 -0
  313. package/dist/systems/construction.d.ts +34 -0
  314. package/dist/systems/economy.d.ts +21 -0
  315. package/dist/systems/fog.d.ts +19 -0
  316. package/dist/systems/life.d.ts +3 -0
  317. package/dist/systems/movement.d.ts +105 -0
  318. package/dist/systems/orders.d.ts +7 -0
  319. package/dist/systems/production.d.ts +49 -0
  320. package/dist/systems/productionQueue.d.ts +40 -0
  321. package/dist/systems/victory.d.ts +14 -0
  322. package/dist/talk.d.ts +65 -0
  323. package/dist/tech.d.ts +62 -0
  324. package/dist/techTree.d.ts +38 -0
  325. package/dist/terrain.d.ts +173 -0
  326. package/dist/terrainSave.d.ts +29 -0
  327. package/dist/testing.d.ts +58 -0
  328. package/dist/testing.js +822 -0
  329. package/dist/testing.js.map +1 -0
  330. package/dist/tiles.d.ts +34 -0
  331. package/dist/timers.d.ts +146 -0
  332. package/dist/tomes.d.ts +48 -0
  333. package/dist/trade.d.ts +28 -0
  334. package/dist/transport.d.ts +76 -0
  335. package/dist/tunables.d.ts +45 -0
  336. package/dist/upkeep.d.ts +16 -0
  337. package/dist/veterancy.d.ts +80 -0
  338. package/dist/walls.d.ts +86 -0
  339. package/dist/world.d.ts +1118 -0
  340. package/package.json +80 -5
  341. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brain-BvVdUhX8.js","names":["LIMITS","at"],"sources":["../src/ai/module.ts","../src/ai/budget.ts","../src/ai/report.ts","../src/ai/roles.ts","../src/ai/strength.ts","../src/ai/reach.ts","../src/ai/threat.ts","../src/ai/view.ts","../src/ai/goals.ts","../src/ai/knowledge.ts","../src/ai/rules.ts","../src/ai/plans/placement.ts","../src/ai/plans/tech.ts","../src/ai/geometry.ts","../src/ai/plans/build.ts","../src/ai/plans/production.ts","../src/ai/plans/plans.ts","../src/ai/plans/purse.ts","../src/ai/checks.ts","../src/ai/task.ts","../src/ai/tasks/shared.ts","../src/ai/tasks/attack.ts","../src/ai/tasks/harass.ts","../src/ai/tasks/creep.ts","../src/ai/tasks/defend.ts","../src/ai/tasks/hold.ts","../src/ai/tasks/move.ts","../src/ai/tasks/capture.ts","../src/ai/tasks/retreat.ts","../src/ai/tasks/escort.ts","../src/ai/tasks/scout.ts","../src/ai/tasks/patrol.ts","../src/ai/tasks/gather.ts","../src/ai/tasks/drop.ts","../src/ai/tasks/index.ts","../src/ai/squads.ts","../src/ai/brain.ts"],"sourcesContent":["/**\n * A module of a brain (`AiModule`): one part of a think, made for each brain (`defineModule`). Apart from the brain\n * (`brain.ts`), which is made of them, so that a module and an area of the kit import this and the brain's type only,\n * and the brain imports no module back\n */\nimport type { Brain } from './brain'\nimport type { AiReport } from './report'\n\n/**\n * One named part of a computer player's think (`defineBrain`'s `modules`). Modules run in their order each think, over\n * the same picture of the game, each reading it through the brain it is handed (`ai.snapshot`, later `ai.view`) and\n * acting through `ai.send`. A module is made for each brain (`AiModuleDef`: a function of the brain), so that what it\n * keeps in itself is one seat's. What it remembers between thinks goes through `save` and `restore`, as plain data\n *\n * @beta\n */\nexport interface AiModule {\n\t/** Unique in a brain: what its memory is kept under, what the timing and the debug tools name it by */\n\tid: string\n\t/**\n\t * The version of what it remembers (`save`): 1 when left out. Raised when the shape of it changes; a load that finds\n\t * memory of another version gives it to `migrate`, or starts the module afresh where there is none\n\t */\n\tversion?: number\n\t/** Runs once in so many thinks, for work that does not need doing every think. Every think when left out */\n\teveryThinks?: number\n\t/** With `everyThinks`, the think in each round it runs at: modules with the same `every` and other offsets spread the work */\n\toffset?: number\n\t/**\n\t * When in a think it runs (`AiPhase`): the brain runs its modules phase by phase, as listed within each. Left out,\n\t * in the phase of the module listed before it (the first phase for the first)\n\t */\n\tphase?: AiPhase\n\t/**\n\t * Ids of modules of the brain this one runs ahead of, for what one phase needs within itself. Ids of modules the\n\t * brain does not have are passed over\n\t */\n\tbefore?: string[]\n\t/** Ids of modules of the brain this one runs after, within its phase */\n\tafter?: string[]\n\t/**\n\t * Ids this module's memory was kept under before it was called what it is: a save made then gives it back under\n\t * the old id, and it is read as this module's (through `migrate` where the version differs too)\n\t */\n\twasCalled?: string[]\n\t/** Its part of the think */\n\tthink(ai: Brain): void\n\t/** What it remembers between thinks, as plain data for a save. Nothing (`undefined`) for a module that remembers nothing */\n\tsave?(): unknown\n\t/** Takes back what `save` gave, in a game loaded from a save */\n\trestore?(data: unknown): void\n\t/**\n\t * Brings what an earlier version of the module saved (`from`: its version) up to what this one takes. Nothing\n\t * (`undefined`) says it cannot be brought up, and the module starts afresh; so does a module without `migrate`\n\t */\n\tmigrate?(data: unknown, from: number): unknown\n\t/**\n\t * What it is thinking, as plain data, for the debug tools: what the report has no part for, kept under the module's\n\t * id in its `sections` (`Brain.report`)\n\t */\n\tinspect?(): unknown\n\t/**\n\t * Writes its part of the report (`Brain.report`), where the report has a part for it: a kit's module fills the part\n\t * it names (its squads, its plans). Plain data only\n\t */\n\treport?(report: AiReport): void\n\t/** Lets go of what it holds outside the brain when the computer is unseated */\n\tdispose?(): void\n}\n\n/**\n * The phases of a think, in the order they run (`AiModule.phase`): `hear` what it was told and its rules, `sense`\n * what threatens it and its team, `plan` its economy, buildings and training, `decide` what its own goals are, `act`\n * the picker, the squads and the waves, `fight` the micro\n *\n * @beta\n */\nexport const AI_PHASES = ['hear', 'sense', 'plan', 'decide', 'act', 'fight'] as const\n\n/**\n * A phase of a think (`AI_PHASES`)\n *\n * @beta\n */\nexport type AiPhase = (typeof AI_PHASES)[number]\n\n/**\n * What finds a module of a brain with its shape (`ai.module(key)`): its id, typed. The kit's are `MELEE_ARMY` and\n * `LANES`; a game makes its own with `moduleKey`\n *\n * @beta\n */\nexport interface ModuleKey<M extends AiModule> {\n\treadonly id: string\n\t/** The shape the module has: never set, for the type alone */\n\treadonly shape?: M\n}\n\n/**\n * A key to a module of a game's own (`ai.module(key)` gives it with its shape)\n *\n * @beta\n */\nexport function moduleKey<M extends AiModule>(id: string): ModuleKey<M> {\n\treturn { id }\n}\n\n/**\n * A module of a brain: made for each brain by a function of it, so that two brains never share one; or one as it is,\n * for a module that keeps nothing. A function made with `defineModule` carries the module's id before it is made,\n * which is how `BrainDef.without` names it\n *\n * @beta\n */\nexport type AiModuleDef = AiModule | (((ai: Brain) => AiModule) & { id?: string })\n\n/**\n * A module made for each brain by a function of it, with its id known before it is made: what a brain's `without`\n * leaves out by name (`meleeBrain.with({ without: ['scouting'] })`). The kit's modules are all defined so\n *\n * @beta\n */\nexport function defineModule(id: string, make: (ai: Brain) => AiModule): AiModuleDef {\n\treturn Object.assign(make, { id })\n}\n","/*\n * The budget of a think (AI plan, F2): how much of a think may be done in one tick, so that twelve computers thinking\n * in the same second do not all think in the same tick. A think is a list of modules run in order over one picture of\n * the game (`brain.ts`); the budget says how many of them a tick may run (`modulesPerTick`) and how many units a tick's\n * modules may look at (`unitsPerTick`, as the modules say: `ai.budget.spent(n)`), and the think goes on at the next\n * tick from where it stopped, over the same picture. A think with no budget is done in one tick, as it always was.\n *\n * **Why work and never milliseconds.** A budget in milliseconds would make the game differ by machine: a slow one would\n * stop a think a module earlier, and an order would land a tick later than on a fast one; the same seed and the same\n * commands would no longer give the same game, and a replay would come apart (`determinism-plan`). Work (a module, a\n * unit looked at) is the same on every machine, so a sliced think is sliced the same way everywhere. Milliseconds are\n * measured all the same, for the report and the Stats panel, and a module over `warnAfterMs` is said in the log; it is\n * never cut short.\n *\n * **A sliced think is stale by design.** A module that runs on a later tick of a think acts on a picture a few ticks\n * old; that is why every task and goal of the kit reads its targets in the view again before sending (C1), and why a\n * brain's default is no slicing. A game sets a budget where its numbers ask for one (`AiOptions.budget`, or the\n * profile's), which the bench says is at eight or twelve computers.\n */\n\n/**\n * How much of a think one tick may do (`AiOptions.budget`, `AiProfile.budget`, `ComputerSeatOptions.budget`), counted in\n * work and never in milliseconds: the same on every machine, so that a game with a sliced think is the same game\n * everywhere. Nothing is limited where a field is left out\n *\n * @beta\n */\nexport interface ThinkBudgetOptions {\n\t/**\n\t * Modules of a brain a think may run in one tick: a think with more goes on at the next tick, over the same picture of\n\t * the game. All of them in one tick when left out\n\t */\n\tmodulesPerTick?: number\n\t/**\n\t * Units a tick's modules may look at, as the modules say (`ai.budget.spent(n)`): a module that walks the squads or the\n\t * bases stops once the tick has looked at this many, and goes on at the next tick from where it was (`later`). No\n\t * limit when left out. A module that says nothing of what it looks at is never stopped by it\n\t */\n\tunitsPerTick?: number\n\t/**\n\t * Milliseconds a module may take before the log says so (once a module, a warning): what to measure first. A module\n\t * is never cut short for it. 4 when left out; `false` for never\n\t */\n\twarnAfterMs?: number | false\n}\n\n/** Milliseconds a module takes before the log says so, where nothing was said */\nconst WARN_AFTER_MS = 4\n\n/**\n * The budget of the think under way, as a module reads it (`ai.budget`): what this tick may still do, and the way to say\n * what was looked at (`spent`) and to go on at the next tick (`later`). A module that walks units looks at them a few at\n * a time:\n *\n * for (; this.cursor < squads.length; this.cursor++) {\n * look(squads[this.cursor])\n * if (!ai.budget.spent(squads[this.cursor].size) && this.cursor + 1 < squads.length) return ai.budget.later()\n * }\n *\n * @beta\n */\nexport class ThinkBudget {\n\t/** Modules a tick may run: `Infinity` where unlimited */\n\treadonly modulesPerTick: number\n\t/** Units a tick's modules may look at, as they say: `Infinity` where unlimited */\n\treadonly unitsPerTick: number\n\t/** Milliseconds a module may take before the log says so: none for never */\n\treadonly warnAfterMs: number | undefined\n\t/** Units looked at this tick, as the modules said (`spent`) */\n\tunits = 0\n\t/** Whether the module running asked to go on at the next tick (`later`) */\n\tdeferred = false\n\n\tconstructor(options?: number | ThinkBudgetOptions) {\n\t\t// a number is the first form the budget had: modules a tick\n\t\tconst given: ThinkBudgetOptions = typeof options === 'number' ? { modulesPerTick: options } : (options ?? {})\n\t\tthis.modulesPerTick = given.modulesPerTick !== undefined && given.modulesPerTick > 0 ? Math.floor(given.modulesPerTick) : Infinity\n\t\tthis.unitsPerTick = given.unitsPerTick !== undefined && given.unitsPerTick > 0 ? given.unitsPerTick : Infinity\n\t\tthis.warnAfterMs = given.warnAfterMs === false ? undefined : (given.warnAfterMs ?? WARN_AFTER_MS)\n\t}\n\n\t/** Whether the budget may slice a think over ticks at all: one that limits nothing never does, and nothing is kept for it */\n\tget slices(): boolean {\n\t\treturn this.modulesPerTick !== Infinity || this.unitsPerTick !== Infinity\n\t}\n\n\t/** Whether this tick may look at more: a module that walks units stops where it may not, and says `later` */\n\tget room(): boolean {\n\t\treturn this.units < this.unitsPerTick\n\t}\n\n\t/**\n\t * Says the module looked at so many units (one when left out). Gives whether this tick may look at more: where it may\n\t * not, a module with more to do remembers where it was and says `later`\n\t */\n\tspent(units = 1): boolean {\n\t\tthis.units += units\n\t\treturn this.room\n\t}\n\n\t/**\n\t * The module running stops here for this tick and is run again at the next, going on from where it remembers it was,\n\t * over the same picture. Honoured where the module looked at something this tick (`spent`): one that looked at\n\t * nothing and asks to go on would never end, so it is taken to be done, and the log says so\n\t */\n\tlater(): void {\n\t\tthis.deferred = true\n\t}\n\n\t/** The budget as the report shows it: the limits, where there are any */\n\treport(): ThinkBudgetOptions | undefined {\n\t\tif (!this.slices) return undefined\n\t\treturn {\n\t\t\t...(this.modulesPerTick !== Infinity && { modulesPerTick: this.modulesPerTick }),\n\t\t\t...(this.unitsPerTick !== Infinity && { unitsPerTick: this.unitsPerTick })\n\t\t}\n\t}\n\n\t/** @internal A new tick of the think: nothing looked at yet, or as much as a pass run again had before it (`units`) */\n\tbegin(units = 0): void {\n\t\tthis.units = units\n\t\tthis.deferred = false\n\t}\n}\n","import type { PlayerId } from '#engine/entity'\nimport type { ComputerTiming } from './computer'\nimport type { ThinkBudgetOptions } from './budget'\nimport type { GoalReport } from './goals'\nimport type { PlansReport } from './plans/plans'\nimport type { SquadReport } from './squads'\nimport type { MicroReport } from './micro'\nimport type { DefenceReport } from './defence'\nimport type { EconomyReport } from './economy'\nimport type { ScoutingReport } from './scouting'\nimport type { TeamReport } from './team'\nimport type { AiProfile } from './profiles'\nimport type { WavesReport } from './waves'\n\n/*\n * What a computer player is thinking, written down (AI plan, E1): the answer to \"why did it do that\", read rather than\n * guessed. Two things live here:\n *\n * - **The report** (`AiReport`): plain data, put together from the brain when someone looks (`Brain.report`, what\n * `Brain.inspect` gives, and what the debug panel's AI tab draws). The brain writes its own parts (its goals with\n * every consideration's raw and curved value, what it knows, its roles, what it was told), and each module writes\n * its section: a module's `report` hook fills a part of the report the kit names (squads, plans, as those items\n * come), its `inspect` goes under its id in `sections`. Plain data, so it crosses a worker and could cross a wire:\n * the panel draws data, it never reaches a brain.\n * - **The decision log** (`Decisions`): the last fifty things it decided, as a line of text each, with the tick: \"attack\n * picked at 0.80: its time has come 1.00 · the wave is ready 1.00\". The goals' picker writes a line when a goal\n * starts or stops, and a module writes its own (`ai.decide`): a wave sent, a building put up. Each line goes to the\n * world's log too (`debug`, category `ai`) where the logger's level lets it through. The log is kept in a save, so\n * that a save sent with a bug report says what the computer had in mind.\n *\n * Nothing in here decides anything: the report is made only when asked, and the milliseconds in it are for reading.\n */\n\n/**\n * One thing a computer player decided, as a line of text: what it did and the reason that weighed most\n *\n * @beta\n */\nexport interface AiDecision {\n\t/** The tick of the think it was decided at */\n\ttick: number\n\t/** What it is about: `goal` for the goals' picker, or the module's word (`army`, `build`, `research`, `hero`) */\n\tkind: string\n\t/** What was decided, in words: \"attack picked at 0.80 (8 units): its time has come 1.00 · the wave is ready 1.00\" */\n\tline: string\n\t/** The goal it is about, where it is about one */\n\tgoal?: string\n}\n\n/**\n * What a computer player remembers of what it saw, in short, for the report: its rivals' bases and their army as last\n * seen, with how many seconds ago, and the tech seen\n *\n * @beta\n */\nexport interface KnowledgeReport {\n\tbases: { owner: PlayerId; at: [number, number]; structures: number; seen: number; gone?: true }[]\n\tarmy: { at: [number, number]; count: number; seen: number }[]\n\ttech: string[]\n\tlost: number\n}\n\n/**\n * What a computer player's play adds up to since it was seated (`Brain.stats`, `AiReport.stats`): the numbers\n * `simulate` reports beside who won, and a test reads to see that the squads send an order once and watch it. Counted,\n * never decided on\n *\n * @beta\n */\nexport interface AiStats {\n\t/** Commands sent */\n\tcommands: number\n\t/** Commands held back past what a think may send (`AiProfile.commandsPerThink`) */\n\theld: number\n\t/** Commands the game refused (a unit that could not do it, a place it could not build at) */\n\trefused: number\n\t/** Seconds its fighters stood idle, summed over the fighters: ten footmen idle for a minute are six hundred */\n\tidleArmySeconds: number\n\t/** Orders sent to a unit again for the same thing within a few seconds: a unit told the same every think stops and starts */\n\tchurn: number\n\t/** Seconds its building waited on money: a want saving up */\n\tblockedOnMoney: number\n\t/** Thinks counted */\n\tthinks: number\n}\n\n/**\n * The threat map as a computer player read it last think (`ThreatMap.cells`, on the ground, the enemy structures it\n * remembers counted): what the game view's AI overlay draws as heat over the ground. The size of a cell, the grid's\n * cells across and down, and each cell with something in it as `[col, row, friendly, enemy]`\n *\n * @beta\n */\nexport interface ThreatReport {\n\tcell: number\n\tcols: number\n\trows: number\n\tcells: [col: number, row: number, friendly: number, enemy: number][]\n}\n\n/**\n * What a computer player is thinking, as plain data (`Brain.report`, `Brain.inspect`): what the debug panel's AI tab\n * draws, and what a test reads. Each module adds its section (`AiModule.report`, `AiModule.inspect`)\n *\n * @beta\n */\nexport interface AiReport {\n\t/** The version of this shape */\n\tv: 1\n\t/** The brain's id (`core.melee`) */\n\tbrain: string\n\t/** The player it plays */\n\tplayer: PlayerId\n\t/** The tick of its last picture of the game */\n\ttick: number\n\t/** Seconds into the game, as of its last picture */\n\ttime: number\n\t/** Ticks a second: what turns a decision's tick into the game's time */\n\ttickRate: number\n\t/** How many times it has thought */\n\tthinks: number\n\t/** Whether it sits still (`world.computers.pause`) */\n\tpaused?: true\n\t/** What it was seated with: the data of its options (`AiOptions`: the difficulty, the numbers); code left out */\n\tprofile: Record<string, unknown>\n\t/** What it plays by (`Brain.profile`): the profile resolved, layer over layer; code (a flag's function) left out */\n\tplaying?: AiProfile\n\t/** The goal that scored highest above the minimum this think: what the army is on. None when nothing is worth doing */\n\tgoal?: string\n\t/** Every goal as the picker last saw it: its score, each consideration's raw and curved value, what it holds, why not */\n\tgoals: GoalReport[]\n\t/** What it remembers of the enemy: left out by a brain that keeps no knowledge */\n\tknowledge?: KnowledgeReport\n\t/** The roles it found among the types it can make: `{ worker: ['peasant'] }` */\n\troles: Record<string, string[]>\n\t/**\n\t * What it has to spend and how it comes in: its resources, its income a minute, its supply; and its economy's say\n\t * (`EconomyReport`): each base with its workers on each resource against what it wants and what is served, the\n\t * workers that fled a raid, the workers had against wanted, where the next hall stands\n\t */\n\teconomy: { resources: Record<string, number>; income: Record<string, number>; supply: [used: number, cap: number] } & Partial<EconomyReport>\n\t/** The raids on its bases with what answers each, every base's raids so far, the towers it wants (`DefenceReport`) */\n\tdefence?: DefenceReport\n\t/** Its plan of looks with how long since each was in sight and whether it is due, its scout and where it goes (`ScoutingReport`) */\n\tscouting?: ScoutingReport\n\t/** Its team: the computers of it, the requests on its board, the plan of an attack together (`TeamReport`) */\n\tteam?: TeamReport\n\t/** Its waves: the one whose turn it is, its group as it stands and when it may go, the waves sent (`WavesReport`) */\n\twaves?: WavesReport\n\t/** Its plans: the purse (what is free, promised, held), and every want of the build plan with what it waits for */\n\tplans: PlansReport\n\t/** Its squads: whose each is, its units and their strength, where it is, its task and how it goes, its last change */\n\tsquads: SquadReport[]\n\t/** Where the strength is, as its threat map read it last think (`ThreatReport`): what the AI overlay draws as heat */\n\tthreat?: ThreatReport\n\t/** Its fights: each squad in one and whom it hits, the units that fled, its heroes and what each learns next, who shops for what */\n\tmicro?: MicroReport\n\t/** The words the game told it that no module has taken yet */\n\ttold: { word: string; tick: number }[]\n\t/** Commands it sent its last think */\n\tsent: number\n\t/** Commands it would have sent its last think past what its profile lets a think send (`commandsPerThink`) */\n\theld?: number\n\t/** How much of a think one tick may do, where its budget slices it (`ThinkBudget`), and the ticks its last think took. Left out where a think is one tick */\n\tbudget?: ThinkBudgetOptions & { ticks: number }\n\t/** What its play adds up to since it was seated (`AiStats`): commands, idle army seconds, churn, seconds blocked on money */\n\tstats: AiStats\n\t/**\n\t * Milliseconds its thinks take, for reading only: the last, an average, the longest, and by module while the world\n\t * profiles. Given by the seat (`inspect` of the player), which times the thinks\n\t */\n\ttiming?: ComputerTiming\n\t/** What it decided, the last fifty, oldest first */\n\tdecisions: AiDecision[]\n\t/** What each module says of itself that the report has no part for (`AiModule.inspect`), under the module's id */\n\tsections: Record<string, unknown>\n}\n\n/**\n * How many decisions the log keeps\n *\n * @internal\n */\nexport const DECISIONS_KEPT = 50\n\n/**\n * The last fifty things a computer player decided (`Brain.decisions`, written by `ai.decide`), oldest first: kept in a\n * save, plain data\n *\n * @beta\n */\nexport class Decisions {\n\tprivate lines: AiDecision[] = []\n\n\tconstructor(private readonly limit = DECISIONS_KEPT) {}\n\n\t/** Writes one down: the oldest goes once there are more than the log keeps */\n\tadd(decision: AiDecision): void {\n\t\tthis.lines.push(decision)\n\t\tif (this.lines.length > this.limit) this.lines.splice(0, this.lines.length - this.limit)\n\t}\n\n\t/** What it decided, oldest first */\n\tlist(): readonly AiDecision[] {\n\t\treturn this.lines\n\t}\n\n\t/** The last decision about a goal, or of a kind */\n\tlast(about: { goal?: string; kind?: string }): AiDecision | undefined {\n\t\tfor (let i = this.lines.length - 1; i >= 0; i--) {\n\t\t\tconst line = this.lines[i]\n\t\t\tif ((about.goal === undefined || line.goal === about.goal) && (about.kind === undefined || line.kind === about.kind)) return line\n\t\t}\n\t\treturn undefined\n\t}\n\n\t/** For a save: a copy */\n\tsave(): AiDecision[] {\n\t\treturn this.lines.map((line) => ({ ...line }))\n\t}\n\n\t/** Takes back what `save` gave: what is not a decision is passed over */\n\trestore(lines: unknown): void {\n\t\tthis.lines = Array.isArray(lines)\n\t\t\t? lines.filter((line): line is AiDecision => !!line && typeof line.line === 'string' && typeof line.tick === 'number').slice(-this.limit)\n\t\t\t: []\n\t}\n}\n\n/** A number as the report writes it: two places */\nconst fixed = (x: number) => x.toFixed(2)\n\n/** A goal's considerations in one line: \"its time has come 1.00 · the wave is ready 0.50\", what was not asked left out */\nexport function considerationsLine(goal: Pick<GoalReport, 'considerations'>): string {\n\treturn goal.considerations\n\t\t.filter((each) => each.asked !== false)\n\t\t.map((each) => `${each.name} ${fixed(each.curved)}`)\n\t\t.join(' · ')\n}\n\n/**\n * The consideration that held a goal back most: the one with the least curved value of those asked (a score is their\n * product, so the least is what kept it low), and none for a goal with no considerations\n */\nexport function weakest(goal: GoalReport): GoalReport['considerations'][number] | undefined {\n\tlet least: GoalReport['considerations'][number] | undefined\n\tfor (const each of goal.considerations) if (each.asked !== false && (!least || each.curved < least.curved)) least = each\n\treturn least\n}\n\n/** A raw value as a sentence writes it: a whole number as it is, the rest to two places */\nconst raw = (x: number) => (Number.isInteger(x) ? String(x) : fixed(x))\n\n/**\n * A goal's row of the report as a sentence (`Brain.explain`): its score, what each question answered and how much that\n * mattered, whether it runs and with what, or why not. `seconds` turns a tick into seconds of the game\n *\n * @internal\n */\nexport function explainGoal(goal: GoalReport, seconds: (tick: number) => number, now: number): string {\n\tconst asked = goal.considerations.filter((each) => each.asked !== false)\n\tconst unasked = goal.considerations.length - asked.length\n\tconst questions = asked.length\n\t\t? `: ${asked.map((each) => `${each.name} is ${raw(each.value)} (${fixed(each.curved)})`).join(', ')}${unasked ? `; ${unasked} more not asked, the goal vetoed already` : ''}`\n\t\t: ''\n\tconst score = `${goal.id} scores ${fixed(goal.score)}${questions}.`\n\tif (goal.picked && goal.held) {\n\t\tconst left = Math.max(0, Math.round(seconds(goal.held.until) - now))\n\t\tconst since = Math.max(0, Math.round(now - seconds(goal.held.since)))\n\t\tconst units = goal.held.units === 1 ? '1 unit' : `${goal.held.units} units`\n\t\treturn `${score} It runs with ${units} (strength ${Math.round(goal.held.strength)}), for ${since} s now${left ? `, committed for ${left} s more` : ''}${goal.urgent ? ', urgent' : ''}.`\n\t}\n\tif (goal.picked) return `${score} It runs.`\n\tif (goal.why) return `${score} It does not run: ${goal.why}.`\n\tconst limit = weakest(goal)\n\tif (goal.score <= 0 && limit) return `${score} It does not run: ${limit.name} vetoes it.`\n\treturn `${score} It does not run: it scores too little${limit ? `, held back most by ${limit.name}` : ''}.`\n}\n","import { baseStats, type UnitTypeDef, upgradesOf } from '#engine/defs'\nimport type { PlayerId } from '#engine/entity'\nimport type { Registry } from '#engine/registry'\nimport { availableToPlayer } from '#engine/shared'\nimport type { PlacementName } from './plans/placement'\nimport type { CounterHint } from './strength'\n\n/*\n * What unit types are for, to a computer player (AI plan, A2). The kit knows nothing of any one game: it does not know what\n * a \"farm\" or a \"town hall\" is. It knows roles: the worker is what gathers and builds, the hall is where what is\n * gathered is brought and workers come from, supply is the cheapest building that provides supply and trains nothing,\n * and so on. A game declares a type's roles where it wants to (`UnitTypeDef.ai.role`), and what it does not declare is\n * inferred here from the definition, by the rules written down in `inferRoles`, each with its reason, the one place\n * those inferences live. When a role is wrong in a game, the fix is a declaration in the game, not a special case in\n * the kit. The inferences are visible in the report (`Roles.explain`), so that a wrong one is seen, not guessed at.\n *\n * Roles are of a type, not of a player: an enemy's hall is a hall. What of the roles is a player's own (the types it\n * has or can make, as its race and the game's `available` hook say) is the view's to say (`AiView.typesOf`)\n */\n\n/**\n * What a unit type is for, to a computer player: the engine's roles, or a word of the game's own. A type can have\n * several (a ghoul is a `gatherer` and a `soldier`)\n *\n * - `worker`: gathers and builds; `gatherer`: gathers (a worker is one too); `topper`: what is put up on a deposit of\n * the money to gather it there (`builtOn`)\n * - `hall`: takes deposits and trains workers; `supply`: provides supply and trains nothing; `barracks`: trains\n * soldiers; `altar`: trains or revives heroes; `workshop`: researches; `tower`: a building that attacks; `shop`:\n * sells or hires\n * - `soldier`: a unit that fights and is no hero; `hero`; `caster`: fights with mana; `healer`: has an ability that\n * heals; `siege`: attacks that splash, fell or are aimed at the ground; `air`: flies; `scout`: the fastest of the\n * soldiers; `detector`: finds the invisible\n *\n * @beta\n */\nexport type AiRole =\n\t| 'worker'\n\t| 'gatherer'\n\t| 'topper'\n\t| 'hall'\n\t| 'supply'\n\t| 'barracks'\n\t| 'altar'\n\t| 'workshop'\n\t| 'tower'\n\t| 'shop'\n\t| 'soldier'\n\t| 'hero'\n\t| 'caster'\n\t| 'healer'\n\t| 'siege'\n\t| 'air'\n\t| 'scout'\n\t| 'detector'\n\t| (string & {})\n\n/**\n * What a game declares of a unit type for the computer player (`UnitTypeDef.ai`), where what the kit infers from the\n * definition is wrong or cannot be known: its roles, words of the game's own about it, what it answers, how much it\n * is worth hitting. A declared role is in place of the inferred ones, not beside them\n *\n * @beta\n */\nexport interface AiHints {\n\t/** What it is for (`AiRole`), one or several: in place of what the kit would infer */\n\trole?: AiRole | AiRole[]\n\t/** Words of the game's own about it (`'ranged'`, `'cavalry'`), for a brain's queries (`UnitSet.withTag`). Beside the inferred ones */\n\ttags?: string[]\n\t/**\n\t * What it is good against: tags, roles or type ids (`['air', 'siege']`), each with a weight where a word is not enough\n\t * (`{ target: 'air', weight: 1 }`). Read by the matchups (`Strength.matchup`, `odds`, `counterFor`)\n\t */\n\tcounters?: CounterHint[]\n\t/**\n\t * How strong it is at full health, in place of the kit's formula (`defaultStrength`) and of any formula the brain was\n\t * given: for a type whose numbers mislead (a unit that is all spells). Scaled by the health a unit has left\n\t */\n\tstrength?: number\n\t/** How much it is worth hitting first, in a fight: 1 when left out. Read by the micro of C2 */\n\tpriority?: number\n\t/**\n\t * Where the build plan puts it (`PlacementName`): `atEdge` for a tower, `behind` for supply, `cluster` beside its\n\t * own kind. Over the brain's table; the role's default when left out\n\t */\n\tplacement?: PlacementName\n}\n\n/**\n * The roles and tags of one unit type, with why (`why`: a line per inferred role, for the report; none for a declared\n * one)\n *\n * @beta\n */\nexport interface RoleEntry {\n\troles: AiRole[]\n\ttags: string[]\n\twhy?: string[]\n}\n\n/**\n * The roles and tags of every unit type of a game, by type id: what `inferRoles` gives, and what a game's own\n * `AiOptions.roles` gives in its place\n *\n * @beta\n */\nexport type RoleTable = Record<string, RoleEntry>\n\n/**\n * The player the roles are found for, where finding them depends on who asks (`AiOptions.roles`)\n *\n * @beta\n */\nexport interface RolesPlayer {\n\tid: PlayerId\n\t/** The race it plays, where the game has races */\n\trace?: string\n\t/** What the game's `available` hook decided for it, by type (`PlayerState.own.availability`) */\n\tavailability?: Record<string, boolean>\n}\n\n/**\n * A game's own way of saying what unit types are for, in place of the kit's inference (`AiOptions.roles`): every type\n * it has a role for, with its roles and tags. What is declared on a type (`UnitTypeDef.ai`) still goes over it\n *\n * @beta\n */\nexport type RolesFinder = (registry: Registry, player: RolesPlayer) => RoleTable\n\n/** The tags the kit infers from an attack: for a brain that asks for the ranged or for what hits the air */\nconst RANGED = 'ranged'\nconst MELEE = 'melee'\nconst HITS_AIR = 'hitsAir'\n\n/** What fights: a unit with an attack that is not a worker (a worker that builds does not fight; a ghoul, which only gathers, does) */\nconst fights = (def: UnitTypeDef): boolean => def.kind === 'unit' && !!def.attacks?.length && !(def.harvester && def.builds?.length)\n\n/** Whether a building takes deposits of a resource: all of them, or that one among those it lists */\nconst takes = (def: UnitTypeDef, kind: string | undefined): boolean =>\n\tkind !== undefined && (def.dropOff === true || (Array.isArray(def.dropOff) && def.dropOff.includes(kind)))\n\n/** What a race's types are, for the rules that look across a race: those of its race, and those of none */\nconst ofRace = (def: UnitTypeDef, race: string | undefined): boolean => def.race === undefined || def.race === race\n\n/**\n * Infers what every unit type of the game is for, from its definition: the rules, written down once, each with its\n * reason (`RoleEntry.why`). What a game declares (`UnitTypeDef.ai.role`) is not looked at here: `findRoles` puts it\n * over what is inferred\n *\n * @beta\n */\nexport function inferRoles(registry: Registry): RoleTable {\n\tconst table: RoleTable = {}\n\tconst all = registry.units.all()\n\tconst money = registry.currency ?? registry.resources[0]?.id\n\tconst heals = (def: UnitTypeDef) =>\n\t\t(def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === 'heal'))\n\tconst detects = (def: UnitTypeDef) =>\n\t\t(def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === 'detect'))\n\t// a worker's kind: the units that gather and build. A race has one; the rules about halls look for it\n\tconst workers = all.filter((def) => def.kind === 'unit' && def.harvester && def.builds?.length)\n\tconst trainsWorker = (def: UnitTypeDef) => !!def.trains?.some((id) => workers.some((worker) => worker.id === id))\n\t// a hall is where deposits go and workers come from. A race with no building that does both (a lanes game with a\n\t// drop-off and no workers) has its drop-offs for halls, whatever they train\n\tconst hallsOf = (race: string | undefined) =>\n\t\tall.filter((def) => def.kind === 'building' && def.dropOff && !def.builtOn && ofRace(def, race) && trainsWorker(def))\n\t// the soldiers of a race, for the scout: the fastest of them\n\tconst soldiers = all.filter((def) => fights(def) && !def.hero)\n\tconst speed = (def: UnitTypeDef) => baseStats(def, registry).moveSpeed\n\t// of its own race alone: a creep of no race is no one's scout\n\tconst scoutOf = (race: string | undefined): UnitTypeDef | undefined => {\n\t\tlet best: UnitTypeDef | undefined\n\t\tfor (const def of soldiers) if (def.race === race && (!best || speed(def) > speed(best))) best = def\n\t\treturn best\n\t}\n\n\tfor (const def of all) {\n\t\tconst roles: AiRole[] = []\n\t\tconst why: string[] = []\n\t\tconst tags: string[] = []\n\t\tconst give = (role: AiRole, reason: string) => {\n\t\t\troles.push(role)\n\t\t\twhy.push(`${role}: ${reason}`)\n\t\t}\n\t\tif (def.kind === 'unit') {\n\t\t\tif (def.harvester && def.builds?.length) give('worker', 'gathers and builds')\n\t\t\tif (def.harvester) give('gatherer', 'gathers')\n\t\t\tif (def.hero) give('hero', 'a hero')\n\t\t\telse if (fights(def)) give('soldier', 'fights and is no hero')\n\t\t\tif (fights(def) && !def.hero && def.abilities?.length && baseStats(def, registry).mana > 0) give('caster', 'fights with mana and abilities')\n\t\t\tif (heals(def)) give('healer', 'has an ability that heals')\n\t\t\tif (def.attacks?.some((attack) => attack.splash || attack.fells || attack.ground))\n\t\t\t\tgive('siege', 'its attacks splash, fell or are aimed at the ground')\n\t\t\tif (def.flying) give('air', 'flies')\n\t\t\tif (!def.hero && fights(def) && scoutOf(def.race) === def) give('scout', 'the fastest of its soldiers')\n\t\t\tif (detects(def)) give('detector', 'has an ability that finds the invisible')\n\t\t} else if (def.kind === 'building') {\n\t\t\tif (def.builtOn !== undefined && def.builtOn === money && takes(def, money))\n\t\t\t\tgive('topper', 'put up on a deposit of the money, where it is gathered')\n\t\t\telse if (def.dropOff && !def.builtOn) {\n\t\t\t\tconst halls = hallsOf(def.race)\n\t\t\t\tif (trainsWorker(def)) give('hall', 'takes deposits and trains workers')\n\t\t\t\telse if (halls.length === 0) give('hall', 'takes deposits, and nothing of its race takes them and trains workers')\n\t\t\t}\n\t\t\tif (def.supplyProvided && !def.trains?.length) give('supply', 'provides supply and trains nothing')\n\t\t\tif (def.trains?.some((id) => registry.units.has(id) && fights(registry.unit(id)) && !registry.unit(id).hero))\n\t\t\t\tgive('barracks', 'trains soldiers')\n\t\t\tif (def.revives || def.trains?.some((id) => registry.units.has(id) && registry.unit(id).hero)) give('altar', 'trains or revives heroes')\n\t\t\tif (def.researches?.length) give('workshop', 'researches')\n\t\t\t// not one that shoots only with units inside it (a burrow): that is shelter, not a defence to put up\n\t\t\tif (def.attacks?.length && !def.transport?.armed) give('tower', 'a building that attacks by itself')\n\t\t\tif (def.sells?.length || def.hires?.length) give('shop', 'sells or hires')\n\t\t\tif (detects(def)) give('detector', 'has an ability that finds the invisible')\n\t\t}\n\t\t// of each of its attacks: one that shoots, one that strikes, one that hits the air\n\t\tconst attacks = def.attacks ?? []\n\t\tif (attacks.some((attack) => attack.projectileSpeed)) tags.push(RANGED)\n\t\tif (attacks.some((attack) => !attack.projectileSpeed)) tags.push(MELEE)\n\t\tif (attacks.some((attack) => attack.targets?.includes('air'))) tags.push(HITS_AIR)\n\t\ttable[def.id] = { roles, tags, why }\n\t}\n\treturn table\n}\n\n/**\n * What the unit types of a game are for (`AiView.roles`): the inferred roles (`inferRoles`, or a game's own finder\n * in its place) with what the game declares on a type over them (`UnitTypeDef.ai`), and the queries over them\n *\n * @beta\n */\nexport class Roles {\n\tprivate readonly byRole = new Map<string, UnitTypeDef[]>()\n\tprivate readonly byTag = new Map<string, UnitTypeDef[]>()\n\n\tconstructor(\n\t\t/** Every unit type's roles and tags, by id */\n\t\treadonly table: RoleTable,\n\t\tprivate readonly registry: Registry\n\t) {}\n\n\t/** The roles of a unit type: none for one that has none, or is not a unit type at all */\n\tof(type: string): readonly AiRole[] {\n\t\treturn this.table[type]?.roles ?? NONE\n\t}\n\n\t/** Whether a unit type has a role */\n\thas(type: string, role: AiRole): boolean {\n\t\treturn this.of(type).includes(role)\n\t}\n\n\t/** The tags of a unit type: the kit's (`ranged`, `melee`, `hitsAir`) and the game's (`UnitTypeDef.ai.tags`) */\n\ttags(type: string): readonly string[] {\n\t\treturn this.table[type]?.tags ?? NONE\n\t}\n\n\t/** Whether a unit type has a tag */\n\thasTag(type: string, tag: string): boolean {\n\t\treturn this.tags(type).includes(tag)\n\t}\n\n\t/** The unit types with a role, in the game's order (the first of a kind is the one meant first) */\n\ttypes(role: AiRole): readonly UnitTypeDef[] {\n\t\tlet found = this.byRole.get(role)\n\t\tif (!found) this.byRole.set(role, (found = this.registry.units.all().filter((def) => this.has(def.id, role))))\n\t\treturn found\n\t}\n\n\t/** The unit types with a tag, in the game's order */\n\ttagged(tag: string): readonly UnitTypeDef[] {\n\t\tlet found = this.byTag.get(tag)\n\t\tif (!found) this.byTag.set(tag, (found = this.registry.units.all().filter((def) => this.hasTag(def.id, tag))))\n\t\treturn found\n\t}\n\n\t/** What a game declared of a type (`UnitTypeDef.ai`): nothing where it declared nothing */\n\thints(type: string): AiHints | undefined {\n\t\treturn this.registry.units.has(type) ? this.registry.unit(type).ai : undefined\n\t}\n\n\t/**\n\t * Why a type has the roles it has, in words, for the report: `declared: worker` for what the game said, a line per\n\t * inferred role otherwise\n\t */\n\texplain(type: string): string {\n\t\tconst entry = this.table[type]\n\t\tif (!entry) return 'no roles'\n\t\tif (!entry.roles.length) return 'none'\n\t\treturn entry.why?.length ? entry.why.join('; ') : `declared: ${entry.roles.join(', ')}`\n\t}\n\n\t/** Every role and the types that have it, for the report (the debug tools) */\n\treport(): Record<string, string[]> {\n\t\tconst report: Record<string, string[]> = {}\n\t\tfor (const [type, entry] of Object.entries(this.table)) for (const role of entry.roles) (report[role] ??= []).push(type)\n\t\treturn report\n\t}\n}\n\nconst NONE: readonly never[] = []\n\n/**\n * Finds what the unit types of a game are for, for a player: inferred from the definitions (`inferRoles`), or by\n * the game's own finder where it gives one (`AiOptions.roles`), with what the game declares on a type\n * (`UnitTypeDef.ai.role`) over either, and the game's tags beside the inferred ones. What the view does once per\n * brain (`AiView.roles`), again only when the game's definitions change\n *\n * @internal\n */\nexport function findRoles(registry: Registry, player: RolesPlayer, finder?: RolesFinder): Roles {\n\tconst table = finder ? finder(registry, player) : inferRoles(registry)\n\tfor (const def of registry.units.all()) {\n\t\tconst hints = def.ai\n\t\tif (!hints) continue\n\t\tconst entry = (table[def.id] ??= { roles: [], tags: [] })\n\t\tif (hints.role !== undefined) {\n\t\t\tentry.roles = Array.isArray(hints.role) ? [...hints.role] : [hints.role]\n\t\t\tdelete entry.why\n\t\t}\n\t\tif (hints.tags) entry.tags = [...new Set([...entry.tags, ...hints.tags])]\n\t}\n\treturn new Roles(table, registry)\n}\n\n/**\n * The unit types a player has or can come to make, from what it has (`owned`): what its units build, its buildings\n * train and what they turn into, followed through, of what its race and the game's `available` hook let it make.\n * Of the whole game, for a player with nothing yet. What the view narrows the roles to for the player (`AiView.typesOf`)\n *\n * @internal\n */\nexport function reachableTypes(registry: Registry, player: RolesPlayer, owned: Iterable<string>): Set<string> {\n\tconst mine = new Set(owned)\n\tconst may = (def: UnitTypeDef) => availableToPlayer(def, { race: player.race, availability: player.availability }, def.id)\n\tconst reach = new Set<string>()\n\tconst next = [...mine]\n\twhile (next.length) {\n\t\tconst id = next.pop()!\n\t\tif (reach.has(id) || !registry.units.has(id)) continue\n\t\tconst def = registry.unit(id)\n\t\t// what it may not make (another race's) is not reached through, but what it has is its own\n\t\tif (!mine.has(id) && !may(def)) continue\n\t\treach.add(id)\n\t\tfor (const made of [...(def.builds ?? []), ...(def.trains ?? []), ...upgradesOf(def)]) if (!reach.has(made)) next.push(made)\n\t}\n\tif (reach.size) return reach\n\tfor (const def of registry.units.all()) if (may(def)) reach.add(def.id)\n\treturn reach\n}\n","import { baseStats, type DamageType, type EntityKind, type Layer, type Stats, type UnitTypeDef } from '#engine/defs'\nimport type { Registry } from '#engine/registry'\nimport type { EntityState } from '#engine/session/protocol'\nimport type { AiView, UnitSet } from './view'\nimport { heroOfState } from '#engine/hero'\nimport { attackStat, farthestReach } from '#engine/attacks'\n\n/*\n * How strong things are, to a computer player (AI plan, A4). A brain asks three questions of a fight: how strong is this\n * unit, how strong is this group, and who would win. The old melee player answered the first two with health alone and\n * the third with three ifs; this file answers them from the definitions, one documented formula a game can replace.\n *\n * The idea, in plain words. A unit's **strength** is how much it can take times how much it deals, under a square root\n * so that the number adds up: two footmen are twice one. That is Lanchester's square law in a form a brain can sum: when\n * two groups of linear strength A and B fight to the end, the odds of A are A² / (A² + B²), and the mirror is 0.5. What\n * a unit can take is its health, more of it where its armour turns damage away (the engine's `mitigation`); what it\n * deals is its damage a second, a little more where it reaches farther and moves faster (it picks fights and leaves\n * them). A hero is worth more than its numbers for the spells it brings, and more as it levels. Nothing here is of\n * one game: the numbers are the engine's stats as the definitions give them, with what the snapshot shows of a seen\n * unit's own (its upgrades, items, levels and buffs are in `EntityState.stats`), scaled by the health it has left.\n *\n * A **matchup** reads the same numbers against an opponent: what a unit cannot hit (footmen under gryphons) counts for\n * nothing of its damage; what its damage meets is the opponent's armour or magic resist, by the engine's own formula;\n * what hits it is the opponent's mix of damage, against its own armour; and what a game declares a type good against\n * (`UnitTypeDef.ai.counters`) weighs it up. `odds(a, b)` turns two matchups into a chance of winning, an **estimate**\n * said so in its doc: it knows nothing of spells, terrain, focus fire or who shoots first (E3 checks it against fights\n * played out; a game that knows better replaces the formula with `AiOptions.strength`, or declares a type's strength\n * with `UnitTypeDef.ai.strength`). `counterFor` ranks what to train against what was seen, by the same arithmetic\n */\n\n/**\n * A force to weigh: a set of entities as the view gives them (`view.enemies.fighters()`), a plain array of them, or\n * types with counts (`{ footman: 6, gryphon: 2 }`), as the knowledge keeps an army it saw (`ArmySighting.types`,\n * `TypeSeen`): those are taken at full health with the stats their type starts with\n *\n * @beta\n */\nexport type Force = UnitSet | readonly EntityState[] | Readonly<Record<string, number>>\n\n/**\n * What a strength formula is given of one unit or type: its definition, its stats as they stand (the type's, with what\n * the snapshot shows of a seen unit's own: upgrades, items, levels, buffs), the entity where there is one (its health,\n * its level) and the view, for the roles and the registry\n *\n * @beta\n */\nexport interface StrengthInput {\n\t/** The unit type */\n\tdef: UnitTypeDef\n\t/** The stats as they stand: the type's, with a seen unit's own over them */\n\tstats: Readonly<Stats>\n\t/** The unit, where one is weighed; none for a type */\n\tentity?: EntityState\n\t/** 0..1: the health it has left, as a part of its most; 1 for a type */\n\thealth: number\n\t/** The picture it is weighed in: for the roles (`view.roles`) and the definitions (`view.registry`) */\n\tview: AiView\n}\n\n/**\n * How strong a unit or a type is, as a number that adds up over a group: the kit's formula (`defaultStrength`), or a\n * game's own in its place (`AiOptions.strength`, `BrainDef.strength`). Given the unit's definition and stats as they\n * stand, the entity where there is one, and the health it has left as a part of its most. Must give a finite number,\n * 0 for what does not fight\n *\n * @beta\n */\nexport type StrengthFormula = (input: StrengthInput) => number\n\n/**\n * What one side of a matchup is worth against the other, with how (`Strength.matchup`): the strength of each of its\n * units against the opponent, summed\n *\n * @beta\n */\nexport interface Matchup {\n\t/** The side's strength against the opponent: 0 where none of it can hit any of them */\n\tstrength: number\n\t/** The side's strength on its own, against no one in particular */\n\tplain: number\n\t/** How many fought: units with health left and an attack */\n\tcount: number\n}\n\n/**\n * How well a type answers a force (`Strength.counterFor`): its strength against them over its plain strength. 1 is as\n * good as it is against anyone, 0 is useless (it cannot hit them), above 1 it is the answer\n *\n * @beta\n */\nexport interface Counter {\n\t/** The type ranked */\n\tdef: UnitTypeDef\n\t/** Its strength against the force over its plain strength */\n\tscore: number\n}\n\n/**\n * What a game declares a type good against (`UnitTypeDef.ai.counters`): a tag (`'air'`), a role (`'siege'`) or a type\n * id, as a word, or with how much it counts (`weight`, 0.5 when left out: a unit whose whole opponent it counters is\n * worth half again)\n *\n * @beta\n */\nexport type CounterHint = string | { target: string; weight?: number }\n\n/** How much a hero is worth over its numbers at level 1, and what each level adds: the spells and the items it brings */\nconst HERO = 1.1\nconst HERO_LEVEL = 0.1\n/** How far reach counts, and how much: a unit that shoots this far deals a quarter more, for the first hits are its */\nconst REACH = 10\nconst REACH_WORTH = 0.25\n/** The same for speed: it picks its fights and leaves them */\nconst SPEED = 8\nconst SPEED_WORTH = 0.1\n/** What a declared counter is worth when its weight is left out */\nconst COUNTER_WEIGHT = 0.5\n\n/**\n * The kit's formula for how strong a unit is, under a square root so that it adds up over a group (Lanchester):\n *\n * `sqrt(toughness × offence) × hero`, where\n *\n * - `toughness` is the health it has left, more by its armour and magic resist (the middle of the two, since no\n * opponent is in question: 100 of armour doubles it, as the engine's `mitigation` halves what arrives),\n * - `offence` is its damage a second (`attackDamage × attackSpeed`), up to a quarter more for reach (at 10 of range)\n * and a tenth for speed (at 8),\n * - `hero` is 1 for a unit, and `1.1 + 0.1 × (level − 1)` for a hero: its spells, and more as they level.\n *\n * 0 for what has no attack: a building that does not shoot, a worker with no weapon. A declared strength\n * (`UnitTypeDef.ai.strength`) is taken in its place by `Strength`, before this is asked\n *\n * @beta\n */\nexport const defaultStrength: StrengthFormula = ({ def, stats, entity, health }) => {\n\tif (!def.attacks?.length) return 0\n\t// of its attacks, the one that deals the most\n\tlet dps = 0\n\tfor (const attack of def.attacks) dps = Math.max(dps, attackStat(stats, attack, 'damage') * attackStat(stats, attack, 'speed'))\n\tif (dps <= 0 || stats.health <= 0) return 0\n\tconst resist = Math.max(0, (stats.armor + stats.magicResist) / 2)\n\tconst toughness = stats.health * health * (1 + resist / 100)\n\tconst offence = dps * reachFactor(def, stats)\n\tlet strength = Math.sqrt(toughness * offence)\n\tif (def.hero) strength *= HERO + HERO_LEVEL * (((entity && heroOfState(entity)?.level) ?? def.level ?? 1) - 1)\n\treturn strength\n}\n\n/** What reach (of its farthest attack) and speed add to what a unit deals: the first hits, the fights it picks */\nconst reachFactor = (def: UnitTypeDef, stats: Readonly<Stats>): number =>\n\t(1 + (Math.min(farthestReach(def, stats), REACH) / REACH) * REACH_WORTH) * (1 + (Math.min(stats.moveSpeed, SPEED) / SPEED) * SPEED_WORTH)\n\nconst KINDS: readonly EntityKind[] = ['unit', 'building', 'resource']\n\n/** What of a type a matchup reads, worked out once a type and kept (`Strength`): where it is, what it hits, how */\ninterface Profile {\n\tdef: UnitTypeDef\n\tstats: Readonly<Stats>\n\tlayer: Layer\n\tkind: EntityKind\n\t/** Its attacks, in the order of its type's: none for what does not fight */\n\tweapons: readonly Weapon[]\n\t/** What the game declares it good against, by target word */\n\tcounters: readonly { target: string; weight: number }[]\n}\n\n/** One of a profile's attacks, for a matchup */\ninterface Weapon {\n\t/** Whether it reaches the ground, the air */\n\thitsGround: boolean\n\thitsAir: boolean\n\t/** The kinds it names, where it names any: a worker that hits units and buildings, not trees */\n\tkinds: readonly EntityKind[] | undefined\n\tdamageType: DamageType\n\t/** Damage a second */\n\tdps: number\n}\n\n/** One group of a force: a profile, how many of it, their health left as a part of their most, summed, and their strength */\ninterface Group {\n\tprofile: Profile\n\tcount: number\n\t/** Σ health left, 0..1 each: what the group can take, as a part of `count` */\n\thealth: number\n\t/** Σ strength by the formula: with the health each has left and its own stats */\n\tstrength: number\n}\n\n/** The first of an attacker's attacks that reaches something where it is and of its kind: the engine's `reaches` and `defaultPickAttack`, over profiles */\nfunction hits(attacker: Profile, target: Profile): Weapon | undefined {\n\tfor (const weapon of attacker.weapons) {\n\t\tif (target.layer === 'air' ? !weapon.hitsAir : !weapon.hitsGround) continue\n\t\tif (!weapon.kinds || weapon.kinds.includes(target.kind)) return weapon\n\t}\n\treturn undefined\n}\n\n/**\n * How strong things are, to a brain (`AiView.strength`, `Brain.strength`): one unit or type (`of`), a group (`sum`,\n * what `UnitSet.strength()` asks), one force against another (`matchup`, `odds`), and what to train against what was\n * seen (`counterFor`). The formula is the kit's (`defaultStrength`) unless the brain was given one\n * (`AiOptions.strength`, `BrainDef.strength`); a type's declared strength (`UnitTypeDef.ai.strength`) goes before\n * either. What a type's numbers come to is worked out once and kept across thinks; a seen unit's own stats\n * (`EntityState.stats`: its upgrades, items, levels, buffs) are read each time\n *\n * @beta\n */\nexport class Strength {\n\tprivate readonly profiles = new Map<string, Profile>()\n\tprivate readonly plainByType = new Map<string, number>()\n\n\tconstructor(\n\t\t/** The game's definitions */\n\t\treadonly registry: Registry,\n\t\t/** The formula a unit's strength comes from: the kit's unless the brain was given one */\n\t\treadonly formula: StrengthFormula = defaultStrength\n\t) {}\n\n\t/** @internal The view the questions are asked through: set by the view that holds this, each think */\n\tview!: AiView\n\n\t/**\n\t * How strong a unit is, with the health it has left and its own stats as the snapshot shows them; or a type at full\n\t * health with the stats it starts with. 0 for what does not fight. A finite number always\n\t */\n\tof(what: EntityState | UnitTypeDef | string): number {\n\t\tif (typeof what === 'string') return this.ofType(this.registry.unit(what))\n\t\tif ('id' in what && typeof what.id === 'string') return this.ofType(what as UnitTypeDef)\n\t\tconst entity = what as EntityState\n\t\tconst def = this.registry.unit(entity.type)\n\t\tif (!def.attacks?.length) return 0\n\t\tconst stats = this.statsOf(entity, def)\n\t\treturn this.evaluate(def, stats, entity, healthOf(entity, stats))\n\t}\n\n\t/** A type at full health: worked out once */\n\tprivate ofType(def: UnitTypeDef): number {\n\t\tlet found = this.plainByType.get(def.id)\n\t\tif (found === undefined) this.plainByType.set(def.id, (found = this.evaluate(def, baseStats(def, this.registry), undefined, 1)))\n\t\treturn found\n\t}\n\n\t/** The formula asked, the declared strength first; whatever comes back made finite */\n\tprivate evaluate(def: UnitTypeDef, stats: Readonly<Stats>, entity: EntityState | undefined, health: number): number {\n\t\tconst declared = def.ai?.strength\n\t\tconst strength = declared !== undefined ? declared * Math.sqrt(health) : this.formula({ def, stats, entity, health, view: this.view })\n\t\treturn Number.isFinite(strength) && strength > 0 ? strength : 0\n\t}\n\n\t/** The stats of a seen unit as they stand: its type's, with its own over them (`EntityState.stats`: upgrades, items, levels, buffs) */\n\tstatsOf(entity: EntityState, def = this.registry.unit(entity.type)): Readonly<Stats> {\n\t\tconst base = baseStats(def, this.registry)\n\t\treturn entity.stats ? ({ ...base, ...entity.stats } as Stats) : base\n\t}\n\n\t/** How strong a group is: the strength of each, summed */\n\tsum(force: Force): number {\n\t\tlet total = 0\n\t\tif (isCounts(force)) {\n\t\t\tfor (const type in force) if (this.registry.units.has(type)) total += this.of(type) * force[type]\n\t\t\treturn total\n\t\t}\n\t\tfor (const entity of force) total += this.of(entity)\n\t\treturn total\n\t}\n\n\t/**\n\t * One force against another: the strength of each of `a`'s units against `b` (what it cannot hit counts for nothing\n\t * of its damage; its damage meets their armour, theirs meets its; what it is declared to counter weighs it up),\n\t * summed. `matchup(a, b).strength / matchup(b, a).strength` is how `a` compares; `odds` turns it into a chance\n\t */\n\tmatchup(a: Force, b: Force): Matchup {\n\t\tconst mine = this.groups(a)\n\t\tconst theirs = this.groups(b)\n\t\tlet strength = 0\n\t\tlet plain = 0\n\t\tlet count = 0\n\t\tfor (const group of mine) {\n\t\t\tcount += group.count\n\t\t\tplain += group.strength\n\t\t\tif (group.strength > 0) strength += group.strength * this.edge(group.profile, theirs)\n\t\t}\n\t\treturn { strength, plain, count }\n\t}\n\n\t/**\n\t * The chance that `a` beats `b` in a fight to the end, 0..1: `A² / (A² + B²)` of the two matchups (Lanchester's\n\t * square law: numbers count twice, since each unit both deals and takes). 0.5 for a mirror, and when neither can hit\n\t * the other. **An estimate**: it reads stats, layers, armour and declared counters, and knows nothing of spells,\n\t * terrain, focus fire, who shoots first or who runs; the plan's E3 checks it against fights played out, and a game\n\t * that knows better gives its own formula (`AiOptions.strength`)\n\t */\n\todds(a: Force, b: Force): number {\n\t\tconst mine = this.matchup(a, b).strength\n\t\tconst theirs = this.matchup(b, a).strength\n\t\tconst total = mine * mine + theirs * theirs\n\t\treturn total > 0 ? (mine * mine) / total : 0.5\n\t}\n\n\t/**\n\t * What answers a force best among some types: each with its strength against them over its plain strength (1 is as\n\t * good as against anyone, 0 cannot hit them, above 1 is the answer), the best first, equals in the order given.\n\t * Against nothing, every type scores 1\n\t */\n\tcounterFor(enemies: Force, candidates: readonly (UnitTypeDef | string)[]): Counter[] {\n\t\tconst theirs = this.groups(enemies)\n\t\tconst ranked = candidates.map((candidate) => {\n\t\t\tconst def = typeof candidate === 'string' ? this.registry.unit(candidate) : candidate\n\t\t\tconst profile = this.profile(def)\n\t\t\tconst score = this.ofType(def) > 0 ? (theirs.length ? this.edge(profile, theirs) : 1) : 0\n\t\t\treturn { def, score }\n\t\t})\n\t\treturn ranked.sort((x, y) => y.score - x.score)\n\t}\n\n\t/** What a game declares a type good against, as `{ target, weight }` each */\n\tcountersOf(type: UnitTypeDef | string): readonly { target: string; weight: number }[] {\n\t\treturn this.profile(typeof type === 'string' ? this.registry.unit(type) : type).counters\n\t}\n\n\t/**\n\t * A profile's strength against a force over its plain strength: what its damage comes to against them (what it can\n\t * hit, through their armour) and what theirs comes to against it (through its armour), each as a part of the\n\t * plain, under the same square root, times what it is declared to counter. 1 against nothing\n\t */\n\tprivate edge(profile: Profile, theirs: readonly Group[]): number {\n\t\tif (!theirs.length) return 1\n\t\tconst { rules } = this.registry\n\t\t// what its damage meets: the share of them it can hit, each through their armour, weighted by the health to chew\n\t\tlet health = 0\n\t\tlet hittable = 0\n\t\tlet countered = 0\n\t\t// what hits it: their damage, each through its armour, as a part of all their damage\n\t\tlet dps = 0\n\t\tlet through = 0\n\t\tfor (const group of theirs) {\n\t\t\tconst other = group.profile\n\t\t\tconst weight = other.stats.health * group.health\n\t\t\thealth += weight\n\t\t\tconst mine = hits(profile, other)\n\t\t\tif (mine) {\n\t\t\t\thittable += weight * rules.combat.mitigation(mine.damageType, other.stats, profile.stats)\n\t\t\t\tfor (const counter of profile.counters) if (this.matches(counter.target, other)) countered += weight * counter.weight\n\t\t\t}\n\t\t\tconst theirs = hits(other, profile)\n\t\t\tif (theirs && theirs.dps > 0) {\n\t\t\t\tconst theirDps = theirs.dps * group.count\n\t\t\t\tdps += theirDps\n\t\t\t\tthrough += theirDps * rules.combat.mitigation(theirs.damageType, profile.stats, other.stats)\n\t\t\t}\n\t\t}\n\t\tif (!health) return 1\n\t\t// its damage against them, as a part of the plain (the plain met the middle of armour and magic resist)\n\t\tconst plainResist = Math.max(0, (profile.stats.armor + profile.stats.magicResist) / 2)\n\t\tconst offence = hittable / health\n\t\t// what it can take against them, as a part of the plain: what they get through, against the middle it was read at\n\t\tconst toughness = dps > 0 ? 1 / (through / dps) / (1 + plainResist / 100) : 1\n\t\treturn Math.sqrt(offence * toughness) * (1 + countered / health)\n\t}\n\n\t/** Whether a declared counter's word is one of a profile's: its type, a role or a tag of it */\n\tprivate matches(target: string, profile: Profile): boolean {\n\t\tconst { roles } = this.view\n\t\treturn profile.def.id === target || roles.has(profile.def.id, target) || roles.hasTag(profile.def.id, target)\n\t}\n\n\t/** What a type comes to for a matchup, kept */\n\tprivate profile(def: UnitTypeDef, stats?: Readonly<Stats>): Profile {\n\t\tconst own = stats !== undefined\n\t\tif (!own) {\n\t\t\tconst found = this.profiles.get(def.id)\n\t\t\tif (found) return found\n\t\t}\n\t\tconst read = stats ?? baseStats(def, this.registry)\n\t\tconst profile: Profile = {\n\t\t\tdef,\n\t\t\tstats: read,\n\t\t\tlayer: def.flying ? 'air' : 'ground',\n\t\t\tkind: def.kind,\n\t\t\tweapons: (def.attacks ?? []).map((attack) => {\n\t\t\t\tconst { targets } = attack\n\t\t\t\tconst kinds = targets?.filter((entry): entry is EntityKind => KINDS.includes(entry as EntityKind))\n\t\t\t\treturn {\n\t\t\t\t\thitsGround: !targets || targets.some((entry) => entry !== 'air'),\n\t\t\t\t\thitsAir: !!targets?.includes('air'),\n\t\t\t\t\tkinds: kinds?.length ? kinds : undefined,\n\t\t\t\t\tdamageType: attack.damageType ?? 'physical',\n\t\t\t\t\tdps: attackStat(read, attack, 'damage') * attackStat(read, attack, 'speed')\n\t\t\t\t}\n\t\t\t}),\n\t\t\tcounters: (def.ai?.counters ?? []).map((hint) =>\n\t\t\t\ttypeof hint === 'string' ? { target: hint, weight: COUNTER_WEIGHT } : { target: hint.target, weight: hint.weight ?? COUNTER_WEIGHT }\n\t\t\t)\n\t\t}\n\t\tif (!own) this.profiles.set(def.id, profile)\n\t\treturn profile\n\t}\n\n\t/** A force as groups: a profile and how many, those with health left and an attack. Units with stats of their own stand apart */\n\tprivate groups(force: Force): Group[] {\n\t\tconst groups: Group[] = []\n\t\tif (isCounts(force)) {\n\t\t\tfor (const type in force) {\n\t\t\t\tconst count = force[type]\n\t\t\t\tif (!(count > 0) || !this.registry.units.has(type)) continue\n\t\t\t\tconst def = this.registry.unit(type)\n\t\t\t\tif (def.attacks?.length) groups.push({ profile: this.profile(def), count, health: count, strength: this.ofType(def) * count })\n\t\t\t}\n\t\t\treturn groups\n\t\t}\n\t\tconst byType = new Map<string, Group>()\n\t\tfor (const entity of force) {\n\t\t\tif (entity.hp <= 0) continue\n\t\t\tconst def = this.registry.unit(entity.type)\n\t\t\tif (!def.attacks?.length) continue\n\t\t\tif (entity.stats) {\n\t\t\t\tconst stats = this.statsOf(entity, def)\n\t\t\t\tconst health = healthOf(entity, stats)\n\t\t\t\tgroups.push({ profile: this.profile(def, stats), count: 1, health, strength: this.evaluate(def, stats, entity, health) })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlet group = byType.get(def.id)\n\t\t\tif (!group) {\n\t\t\t\tbyType.set(def.id, (group = { profile: this.profile(def), count: 0, health: 0, strength: 0 }))\n\t\t\t\tgroups.push(group)\n\t\t\t}\n\t\t\tconst health = healthOf(entity, group.profile.stats)\n\t\t\tgroup.count++\n\t\t\tgroup.health += health\n\t\t\tgroup.strength += this.evaluate(def, group.profile.stats, entity, health)\n\t\t}\n\t\treturn groups\n\t}\n}\n\n/** Whether a force is given as types with counts */\nconst isCounts = (force: Force): force is Readonly<Record<string, number>> => !(Symbol.iterator in force)\n\n/** The health a seen unit has left, as a part of its most: 1 for one at full health or whose most is not known */\nfunction healthOf(entity: EntityState, stats: Readonly<Stats>): number {\n\tconst most = entity.maxHp ?? stats.health\n\tif (!(most > 0)) return 1\n\treturn Math.max(0, Math.min(1, entity.hp / most))\n}\n","/**\n * The distances and times the AI kit measures by (design review B13), each named once with why it is what it is\n */\n\n/**\n * The side of a cell of the view's grid, in units of the map: a few units, so that \"near\" looks at a few cells. The\n * threat map and the knowledge share it\n *\n * @internal\n */\nexport const CELL = 8\n\n/**\n * How far from its centre a building is still of a base: the view's own and the knowledge's of an enemy\n *\n * @internal\n */\nexport const BASE_REACH = 24\n\n/**\n * How far from a mine a hall is that mine's: the economy's deposits, the hall built by a mine, the way kept clear\n * between them\n *\n * @internal\n */\nexport const HALL_REACH = 16\n\n/**\n * How near the middle of a squad a fight is: what is this near is in it (the squads' and the micro's measure)\n *\n * @internal\n */\nexport const FIGHT_REACH = 14\n\n/**\n * How near one of its units a foe is for it to be in a fight: a squad that may turn back, a unit in the fight, a\n * worker a raid is on\n *\n * @internal\n */\nexport const ENGAGED = 8\n\n/**\n * How near one of theirs a lanes hero is in a fight (a hero with nothing this near walks on): a lane is wider than a\n * squad's reach\n *\n * @internal\n */\nexport const LANE_ENGAGED = 9\n\n/**\n * Seconds before an order that was lost is sent again: what keeps a stuck unit from being told every think\n *\n * @internal\n */\nexport const RESEND = 3\n","import type { Layer } from '#engine/defs'\nimport { attackStat } from '#engine/attacks'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport type { AiView } from './view'\nimport { CELL } from './reach'\n\n/*\n * The threat map: where the strength is (AI plan, A4). An **influence map**, the standard idea written plainly: a\n * coarse grid over the map where each cell holds the strength of the friendly units and of the enemy units that can\n * reach it. A brain's questions about places become reads of a few cells: \"is my expansion in danger\" is the enemy\n * strength at its cell, \"where is it safe\" is where the net is friendly, \"where are they raiding\" is the hot cells\n * near what is mine. It is cheap to make (one pass over what is in sight, each unit painted onto the cells it reaches)\n * and made only when something asks, once a think (`AiView.threat`): the view is of one think, and so is this.\n *\n * Reach is the unit's range, and a little more for its speed: what it could be hitting within a moment. Strength is\n * painted in full within range and fades to nothing at the edge of reach. Two layers are kept, for what a unit can\n * hit: `ground` holds the strength of what reaches things on the ground, `air` of what reaches things in the air, so\n * that gryphons over footmen read as safe in the air and a tower reads on both. Built from what is in sight only;\n * `remembered: true` adds the enemy structures seen before and out of sight (their towers), which may be gone\n */\n\n/** Seconds of movement that count towards a unit's reach: what it could be hitting within a moment */\nconst SPREAD = 1.5\n\n/**\n * How much of a unit's strength a cell `d` away gets, for an attack reaching `range` (its size in): all of it within, fading\n * to nothing over `spread` past it\n */\nfunction reachWeight(d: number, range: number, spread: number): number {\n\tconst half = CELL / 2\n\tconst reach = range + spread\n\tconst fade = reach - range\n\tif (d <= range + half) return 1\n\treturn fade > 0 && d < reach + half ? (reach + half - d) / fade : 0\n}\n\n/**\n * What the threat map reads at a place: the strength of the friendly units (one's own and allies') and of the enemy\n * units (rivals' and creeps') that can reach it, and the difference\n *\n * @beta\n */\nexport interface Threat {\n\t/** The strength of one's own and allies' units that reach the place */\n\tfriendly: number\n\t/** The strength of rivals' and creeps' units that reach it */\n\tenemy: number\n\t/** `friendly - enemy`: above 0 where one's own side is stronger */\n\tnet: number\n}\n\n/**\n * A cell of the threat map with what it reads (`ThreatMap.hot`, `cells`)\n *\n * @beta\n */\nexport interface ThreatCell extends Threat {\n\t/** The middle of the cell */\n\tat: Vec2\n\tcol: number\n\trow: number\n}\n\n/**\n * What a read of the map is for: the layer the thing asked about is on (`ground` when left out: what can reach things\n * on the ground), and whether the enemy structures remembered and out of sight count too (a tower seen before)\n *\n * @beta\n */\nexport interface ThreatQuery {\n\tlayer?: Layer\n\tremembered?: boolean\n}\n\nconst ZERO: Threat = Object.freeze({ friendly: 0, enemy: 0, net: 0 })\n\n/** The two grids of one reading: what can reach the ground, what can reach the air */\ninterface Grids {\n\tfriendly: Record<Layer, Float64Array>\n\tenemy: Record<Layer, Float64Array>\n}\n\n/**\n * Where the strength is, on a coarse grid over the map (`AiView.threat`, `Brain.threat`): `at(point)` reads a place,\n * `around(point, radius)` the worst cell near it, `hot()` the cells where the enemy is strongest near what is one's\n * own, `cells()` every cell with something in it (for a drawing of it). Made from the view's picture when first asked,\n * once a think; all zeros for no point, or one off the map, so that a question about \"the first base known\" needs no\n * guard\n *\n * @beta\n */\nexport class ThreatMap {\n\t/** Cells across and down, and the side of one */\n\treadonly cols: number\n\treadonly rows: number\n\treadonly cell = CELL\n\tprivate seen: Grids | undefined\n\tprivate withRemembered: Grids | undefined\n\n\tconstructor(\n\t\t/** The picture it is made from */\n\t\treadonly view: AiView\n\t) {\n\t\tconst { terrain } = view.session\n\t\tthis.cols = Math.max(1, Math.ceil(terrain.width / CELL))\n\t\tthis.rows = Math.max(1, Math.ceil(terrain.depth / CELL))\n\t}\n\n\t/** The grids of a reading, made when first asked */\n\tprivate grids(remembered: boolean): Grids {\n\t\tif (remembered) return (this.withRemembered ??= this.build(true))\n\t\treturn (this.seen ??= this.build(false))\n\t}\n\n\t/** One pass over the picture: each fighter painted onto the cells it reaches, on the layers it can hit */\n\tprivate build(remembered: boolean): Grids {\n\t\tconst size = this.cols * this.rows\n\t\tconst grids: Grids = {\n\t\t\tfriendly: { ground: new Float64Array(size), air: new Float64Array(size) },\n\t\t\tenemy: { ground: new Float64Array(size), air: new Float64Array(size) }\n\t\t}\n\t\tconst { view } = this\n\t\tfor (const entity of view.mine) this.paint(grids.friendly, entity)\n\t\tfor (const entity of view.allies) this.paint(grids.friendly, entity)\n\t\tconst hostile = remembered ? view.hostile.known() : view.hostile\n\t\tfor (const entity of hostile) this.paint(grids.enemy, entity)\n\t\treturn grids\n\t}\n\n\t/** A unit's strength onto the cells within its reach: in full within its range, fading to nothing at the edge */\n\tprivate paint(side: Record<Layer, Float64Array>, entity: EntityState): void {\n\t\tif (entity.hp <= 0) return\n\t\tconst { view } = this\n\t\tconst def = view.def(entity)\n\t\tconst attacks = def.attacks\n\t\tif (!attacks?.length) return\n\t\tconst strength = view.strength.of(entity)\n\t\tif (!(strength > 0)) return\n\t\tconst stats = view.strength.statsOf(entity, def)\n\t\t// how far it reaches each layer: the farthest of its attacks that hit there, -1 for none\n\t\tlet ground = -1\n\t\tlet air = -1\n\t\tfor (const attack of attacks) {\n\t\t\tconst { targets } = attack\n\t\t\tconst range = attackStat(stats, attack, 'range')\n\t\t\tif (!targets || targets.some((entry) => entry !== 'air')) ground = Math.max(ground, range)\n\t\t\tif (targets?.includes('air')) air = Math.max(air, range)\n\t\t}\n\t\tif (ground < 0 && air < 0) return\n\t\tconst spread = stats.moveSpeed * SPREAD\n\t\tconst far = Math.max(ground, air) + def.radius + spread\n\t\tconst c0 = this.col(entity.x - far)\n\t\tconst c1 = this.col(entity.x + far)\n\t\tconst r0 = this.row(entity.z - far)\n\t\tconst r1 = this.row(entity.z + far)\n\t\tfor (let r = r0; r <= r1; r++) {\n\t\t\tfor (let c = c0; c <= c1; c++) {\n\t\t\t\t// the nearest point of the cell to the unit: a cell it stands in or touches with its range is within it in full\n\t\t\t\tconst nx = Math.max(c * CELL, Math.min(entity.x, (c + 1) * CELL))\n\t\t\t\tconst nz = Math.max(r * CELL, Math.min(entity.z, (r + 1) * CELL))\n\t\t\t\tconst d = Math.sqrt(distSq({ x: nx, z: nz }, entity))\n\t\t\t\tconst index = r * this.cols + c\n\t\t\t\tif (ground >= 0) side.ground[index] += strength * reachWeight(d, ground + def.radius, spread)\n\t\t\t\tif (air >= 0) side.air[index] += strength * reachWeight(d, air + def.radius, spread)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate col(x: number): number {\n\t\treturn Math.min(this.cols - 1, Math.max(0, Math.floor(x / CELL)))\n\t}\n\n\tprivate row(z: number): number {\n\t\treturn Math.min(this.rows - 1, Math.max(0, Math.floor(z / CELL)))\n\t}\n\n\t/** Whether a point is on the map */\n\tprivate onMap(point: Vec2): boolean {\n\t\tconst { terrain } = this.view.session\n\t\treturn point.x >= 0 && point.z >= 0 && point.x < terrain.width && point.z < terrain.depth\n\t}\n\n\tprivate read(grids: Grids, layer: Layer, index: number): Threat {\n\t\tconst friendly = grids.friendly[layer][index]\n\t\tconst enemy = grids.enemy[layer][index]\n\t\treturn { friendly, enemy, net: friendly - enemy }\n\t}\n\n\t/**\n\t * What reaches a place: the friendly and the enemy strength at its cell, on a layer (`ground` when left out). All\n\t * zeros for no point or one off the map\n\t */\n\tat(point: Vec2 | undefined, query: ThreatQuery = {}): Threat {\n\t\tif (!point || !this.onMap(point)) return ZERO\n\t\tconst grids = this.grids(!!query.remembered)\n\t\treturn this.read(grids, query.layer ?? 'ground', this.row(point.z) * this.cols + this.col(point.x))\n\t}\n\n\t/** The worst cell within a distance of a point: the one the most enemy strength reaches. Zeros off the map */\n\taround(point: Vec2 | undefined, radius: number, query: ThreatQuery = {}): Threat {\n\t\tif (!point || !this.onMap(point)) return ZERO\n\t\tconst grids = this.grids(!!query.remembered)\n\t\tconst layer = query.layer ?? 'ground'\n\t\tlet worst = ZERO\n\t\tconst c0 = this.col(point.x - radius)\n\t\tconst c1 = this.col(point.x + radius)\n\t\tconst r0 = this.row(point.z - radius)\n\t\tconst r1 = this.row(point.z + radius)\n\t\tfor (let r = r0; r <= r1; r++) {\n\t\t\tfor (let c = c0; c <= c1; c++) {\n\t\t\t\tconst found = this.read(grids, layer, r * this.cols + c)\n\t\t\t\tif (found.enemy > worst.enemy || (worst === ZERO && found.friendly > 0)) worst = found\n\t\t\t}\n\t\t}\n\t\treturn worst\n\t}\n\n\t/**\n\t * Where the enemy is strongest near what is one's own: the cells that enemy strength reaches and that hold a unit or\n\t * building of the player's (an ally's with `owner`), the hottest first. A raid at an expansion reads here while the\n\t * main is quiet\n\t */\n\thot(query: ThreatQuery & { owner?: number } = {}): ThreatCell[] {\n\t\tconst grids = this.grids(!!query.remembered)\n\t\tconst layer = query.layer ?? 'ground'\n\t\tconst own = query.owner === undefined ? this.view.mine : this.view.all.ofOwner(query.owner)\n\t\tconst held = new Set<number>()\n\t\tfor (const entity of own) held.add(this.row(entity.z) * this.cols + this.col(entity.x))\n\t\tconst cells: ThreatCell[] = []\n\t\t// in the grid's order, so that equals come out the same every time\n\t\tfor (let index = 0; index < this.cols * this.rows; index++) {\n\t\t\tif (!held.has(index)) continue\n\t\t\tconst found = this.read(grids, layer, index)\n\t\t\tif (found.enemy > 0) cells.push(this.cellOf(index, found))\n\t\t}\n\t\treturn cells.sort((a, b) => b.enemy - a.enemy)\n\t}\n\n\t/** Every cell that any strength reaches on a layer, in the grid's order: for a drawing of the map */\n\tcells(query: ThreatQuery = {}): ThreatCell[] {\n\t\tconst grids = this.grids(!!query.remembered)\n\t\tconst layer = query.layer ?? 'ground'\n\t\tconst cells: ThreatCell[] = []\n\t\tfor (let index = 0; index < this.cols * this.rows; index++) {\n\t\t\tconst found = this.read(grids, layer, index)\n\t\t\tif (found.friendly > 0 || found.enemy > 0) cells.push(this.cellOf(index, found))\n\t\t}\n\t\treturn cells\n\t}\n\n\tprivate cellOf(index: number, found: Threat): ThreatCell {\n\t\tconst col = index % this.cols\n\t\tconst row = Math.floor(index / this.cols)\n\t\treturn { ...found, at: { x: (col + 0.5) * CELL, z: (row + 0.5) * CELL }, col, row }\n\t}\n\n\t/** Whether a reading has been made this think: for the timing and the debug tools */\n\tget built(): boolean {\n\t\treturn this.seen !== undefined || this.withRemembered !== undefined\n\t}\n}\n","import { inShape } from '#engine/areas'\nimport { builtSoFar } from '#engine/systems/construction'\nimport type { Component } from '#engine/components'\nimport type { ResourceKind, UnitTypeDef } from '#engine/defs'\nimport type { PlayerId } from '#engine/entity'\nimport type { EventKey } from '#engine/events'\nimport type { Lane } from '#engine/lanes'\nimport type { MapRegion } from '#engine/map'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { Message } from '#engine/messages'\nimport type { ObjectiveState } from '#engine/objectives'\nimport type { Registry } from '#engine/registry'\nimport type {\n\tCampInfo,\n\tEntityState,\n\tGameSession,\n\tGroundItemState,\n\tHeroSummary,\n\tMineInfo,\n\tPlayerState,\n\tSessionEvent,\n\tSnapshot\n} from '#engine/session/protocol'\nimport { type AiRole, findRoles, reachableTypes, type Roles, type RolesFinder } from './roles'\nimport { Strength, type StrengthFormula } from './strength'\nimport { ThreatMap } from './threat'\nimport { BASE_REACH, CELL } from './reach'\n\n/*\n * The view: a computer player's reading of its snapshot (AI plan, A2). A snapshot is plain data, one flat list of\n * entities (`Snapshot.entities`), and every question a brain asks of it (\"my idle workers\", \"enemies near home\", \"the\n * nearest mine\") would be a walk over the whole list; the old melee player walked it dozens of times a think. The view\n * walks it once, as the think begins, and sorts what it finds: by owner and relation (`mine`, `allies`, `enemies`,\n * `creeps`, `neutral`, `resources`), by id (`byId`), and by place (a coarse grid of cells over the map, which answers\n * \"what is near here\" from a few cells instead of everything). What it gives back are `UnitSet`s: arrays of entity\n * states with the questions as methods (`idle()`, `withRole('worker')`, `near(home, 20)`), each giving a set again, so\n * that a goal's author writes `ai.view.enemies.near(home, 20).fighters()` and reads what they meant.\n *\n * The view is of one think: made from the snapshot as the think begins, thrown away with it. Entities move, so the\n * grid is never kept between thinks, and neither is the threat map (`threat`, made when first asked). What is kept is\n * what costs and does not change: the roles of the game's unit types (`roles.ts`), found once and kept while the\n * game's definitions stand, and what the types' numbers come to (`strength`, `strength.ts`).\n *\n * Nothing here takes the world itself (a test asserts it): the view reads the session's snapshot, cut to the player's\n * fog, and the map's facts everyone knows (regions, mines, camps, the ground for `canPlace` and `findPath`)\n */\n\n/** A set this small is scanned for what is near rather than asked of the grid: the grid pays for itself only on big sets */\nconst SCAN = 24\n\n/**\n * A set of entities as the view gives them, in the snapshot's order, with the questions a brain asks as methods, each\n * giving a set again, so that they chain: `ai.view.mine.withRole('worker').idle()`, `ai.view.enemies.near(home,\n * 20).fighters()`. It reads as an array (`length`, `for..of`, `map`, `filter`, `find`, `some`, `every`, `forEach`,\n * `first`, `at`; `items` is the plain array) but is not one: `map` and `filter` give plain arrays, `where` gives a set.\n * (Not an `Array` subclass on purpose: the engines run `filter` and `find` on one several times slower, species\n * lookup, and a think asks dozens.) A set is of one think: it reads the view it came from\n *\n * @beta\n */\nexport class UnitSet implements Iterable<EntityState> {\n\t/** What this set remembers beside what is in sight (`known`): the structures seen before, for the view's own sets */\n\tprivate readonly remembered: EntityState[] | undefined\n\t/** The answers to the questions that are asked again and again, by their name */\n\tprivate memo: Map<string, UnitSet> | undefined\n\tprivate idSet: Set<number> | undefined\n\tprivate strengthSum: number | undefined\n\n\tconstructor(\n\t\t/** The view the set reads: the definitions, the roles, the grid */\n\t\treadonly view: AiView,\n\t\t/** The entities, as a plain array, in the snapshot's order */\n\t\treadonly items: readonly EntityState[] = [],\n\t\tremembered?: EntityState[]\n\t) {\n\t\tthis.remembered = remembered\n\t}\n\n\t/** How many */\n\tget length(): number {\n\t\treturn this.items.length\n\t}\n\n\t[Symbol.iterator](): Iterator<EntityState> {\n\t\treturn this.items[Symbol.iterator]()\n\t}\n\n\t/** The first of them: none in an empty set */\n\tfirst(): EntityState | undefined {\n\t\treturn this.items[0]\n\t}\n\n\t/** Some of them, as an array's `slice` takes them: as a set */\n\tslice(start?: number, end?: number): UnitSet {\n\t\treturn this.make(this.items.slice(start, end))\n\t}\n\n\t/** The one at an index, from the end for a negative one */\n\tat(index: number): EntityState | undefined {\n\t\treturn this.items.at(index)\n\t}\n\n\t/** As an array does: a plain array */\n\tmap<T>(fn: (entity: EntityState, index: number) => T): T[] {\n\t\treturn this.items.map(fn)\n\t}\n\n\t/** As an array does: a plain array. `where` gives a set */\n\tfilter(fn: (entity: EntityState, index: number) => unknown): EntityState[] {\n\t\treturn this.items.filter(fn)\n\t}\n\n\tfind(fn: (entity: EntityState, index: number) => unknown): EntityState | undefined {\n\t\treturn this.items.find(fn)\n\t}\n\n\tsome(fn: (entity: EntityState, index: number) => unknown): boolean {\n\t\treturn this.items.some(fn)\n\t}\n\n\tevery(fn: (entity: EntityState, index: number) => unknown): boolean {\n\t\treturn this.items.every(fn)\n\t}\n\n\tforEach(fn: (entity: EntityState, index: number) => void): void {\n\t\tthis.items.forEach(fn)\n\t}\n\n\t/** A set of these, of the same view */\n\tprivate make(items: readonly EntityState[]): UnitSet {\n\t\treturn new UnitSet(this.view, items)\n\t}\n\n\t/** The answer to a question asked by name, worked out once */\n\tprivate cached(key: string, answer: () => UnitSet): UnitSet {\n\t\tthis.memo ??= new Map()\n\t\tlet found = this.memo.get(key)\n\t\tif (!found) this.memo.set(key, (found = answer()))\n\t\treturn found\n\t}\n\n\t/** Those that satisfy a predicate, as a set */\n\twhere(predicate: (entity: EntityState, def: UnitTypeDef) => boolean): UnitSet {\n\t\tconst { view } = this\n\t\treturn this.make(this.items.filter((entity) => predicate(entity, view.def(entity))))\n\t}\n\n\t/** Those of a unit type, or that count as it (`UnitTypeDef.provides`: a keep is a town hall too) */\n\tofType(type: string): UnitSet {\n\t\treturn this.cached(`type:${type}`, () => this.where((entity, def) => entity.type === type || !!def.provides?.includes(type)))\n\t}\n\n\t/** Those whose type has a role (`AiRole`: `'worker'`, `'hall'`, a game's own word) */\n\twithRole(role: AiRole): UnitSet {\n\t\treturn this.cached(`role:${role}`, () => {\n\t\t\tconst { roles } = this.view\n\t\t\treturn this.make(this.items.filter((entity) => roles.has(entity.type, role)))\n\t\t})\n\t}\n\n\t/** Those whose type has a tag: the kit's (`ranged`, `melee`, `hitsAir`) or the game's (`UnitTypeDef.ai.tags`) */\n\twithTag(tag: string): UnitSet {\n\t\treturn this.cached(`tag:${tag}`, () => {\n\t\t\tconst { roles } = this.view\n\t\t\treturn this.make(this.items.filter((entity) => roles.hasTag(entity.type, tag)))\n\t\t})\n\t}\n\n\t/** Those that fight: soldiers and heroes */\n\tfighters(): UnitSet {\n\t\treturn this.cached('fighters', () => {\n\t\t\tconst { roles } = this.view\n\t\t\treturn this.make(this.items.filter((entity) => roles.has(entity.type, 'soldier') || roles.has(entity.type, 'hero')))\n\t\t})\n\t}\n\n\t/** Those that gather and build (role `worker`) */\n\tworkers(): UnitSet {\n\t\treturn this.withRole('worker')\n\t}\n\n\t/** The heroes among them */\n\theroes(): UnitSet {\n\t\treturn this.withRole('hero')\n\t}\n\n\t/** The buildings among them, under construction too (`finished` leaves those out) */\n\tbuildings(): UnitSet {\n\t\treturn this.cached('buildings', () => this.where((_, def) => def.kind === 'building'))\n\t}\n\n\t/** The units among them: what moves, buildings and resources left out */\n\tunits(): UnitSet {\n\t\treturn this.cached('units', () => this.where((_, def) => def.kind === 'unit'))\n\t}\n\n\t/** Those that stand finished: not under construction (a building turning into another type stands) */\n\tfinished(): UnitSet {\n\t\treturn this.cached('finished', () => this.make(this.items.filter((entity) => builtSoFar(entity) === undefined)))\n\t}\n\n\t/** Those of mine with nothing to do: no order, and not inside something (a worker in a mine). Only one's own say what they do */\n\tidle(): UnitSet {\n\t\treturn this.cached('idle', () => this.make(this.items.filter((entity) => !!entity.own && !entity.own.order && !entity.own.hidden)))\n\t}\n\n\t/** Those in sight now: a structure seen before and out of sight is not (`EntityState.visible`) */\n\tvisible(): UnitSet {\n\t\treturn this.cached('visible', () => this.make(this.items.filter((entity) => entity.visible)))\n\t}\n\n\t/** Those with health left */\n\talive(): UnitSet {\n\t\treturn this.cached('alive', () => this.make(this.items.filter((entity) => entity.hp > 0)))\n\t}\n\n\t/** Deposits of a resource with something left in them (a gold mine, a tree): for the view's `resources` */\n\tofResource(kind: ResourceKind): UnitSet {\n\t\treturn this.cached(`resource:${kind}`, () => this.where((entity, def) => (entity.resource ?? 0) > 0 && def.resource?.kind === kind))\n\t}\n\n\t/** Those of a player */\n\tofOwner(player: PlayerId): UnitSet {\n\t\treturn this.cached(`owner:${player}`, () => this.make(this.items.filter((entity) => entity.owner === player)))\n\t}\n\n\t/**\n\t * Those within a distance of a point, in the snapshot's order. A big set is asked of the view's grid, a small one is\n\t * scanned: the answer is the same\n\t */\n\tnear(point: Vec2, radius: number): UnitSet {\n\t\tconst reach = radius * radius\n\t\tif (this.items.length <= SCAN) return this.make(this.items.filter((entity) => distSq(entity, point) <= reach))\n\t\tconst ids = this.ids()\n\t\treturn this.make(this.view.gridNear(point, radius).filter((entity) => ids.has(entity.id) && distSq(entity, point) <= reach))\n\t}\n\n\t/** The one nearest a point: none in an empty set. The first of two as near */\n\tnearest(point: Vec2): EntityState | undefined {\n\t\tlet best: EntityState | undefined\n\t\tlet bestDistance = Infinity\n\t\tfor (const entity of this.items) {\n\t\t\tconst d = distSq(entity, point)\n\t\t\tif (d < bestDistance) {\n\t\t\t\tbestDistance = d\n\t\t\t\tbest = entity\n\t\t\t}\n\t\t}\n\t\treturn best\n\t}\n\n\t/** The middle of them: none for an empty set */\n\tcentre(): Vec2 | undefined {\n\t\tconst { items } = this\n\t\tif (!items.length) return undefined\n\t\tlet x = 0\n\t\tlet z = 0\n\t\tfor (const entity of items) {\n\t\t\tx += entity.x\n\t\t\tz += entity.z\n\t\t}\n\t\treturn { x: x / items.length, z: z / items.length }\n\t}\n\n\t/**\n\t * How strong they are together: the strength of each (`Strength.of`: by its stats and the health it has left),\n\t * summed. 0 for what does not fight. Against someone in particular, ask `view.strength.odds(these, those)`\n\t */\n\tstrength(): number {\n\t\treturn (this.strengthSum ??= this.view.strength.sum(this.items))\n\t}\n\n\t/** Their ids, as a set: for \"is it one of these\" */\n\tids(): ReadonlySet<number> {\n\t\treturn (this.idSet ??= new Set(this.items.map((entity) => entity.id)))\n\t}\n\n\t/** Whether an entity, by id, is one of these */\n\thas(id: number): boolean {\n\t\treturn this.ids().has(id)\n\t}\n\n\t/** These and another set's, together, in the snapshot's order, each once */\n\tand(other: UnitSet): UnitSet {\n\t\tconst { view } = this\n\t\tconst all = [...this.items, ...other.items.filter((entity) => !this.has(entity.id))]\n\t\tall.sort((a, b) => view.indexOf(a) - view.indexOf(b))\n\t\treturn this.make(all)\n\t}\n\n\t/**\n\t * These and what is remembered of them beside what is in sight: for `view.enemies`, the enemy structures seen before\n\t * and out of sight now (`visible: false`), which may be gone. Ask it of the view's set before narrowing it\n\t * (`view.enemies.known().buildings()`): a narrowed set remembers nothing more\n\t */\n\tknown(): UnitSet {\n\t\tif (!this.remembered?.length) return this\n\t\treturn this.cached('known', () => this.and(this.make(this.remembered!)))\n\t}\n}\n\n/**\n * The player a brain plays, as its picture of the game shows them: what the snapshot has of one's own player\n * (`PlayerState.own`), beside who they are. Mutable for the think: a module that sends a `train` bumps `supplyUsed`\n * itself, so that the next module does not queue past the cap before the command lands\n *\n * @beta\n */\nexport interface Me {\n\tid: PlayerId\n\tname: string\n\tteam: number\n\t/** The race they play (`raceOf`): left out in a game without races */\n\trace?: string\n\tdefeated: boolean\n\t/** What they have of each resource, by resource id */\n\tresources: Record<ResourceKind, number>\n\tsupplyUsed: number\n\tsupplyCap: number\n\t/** The game's other pools of supply, by name (`GameRules.supply.pools`) */\n\tsupplies?: Record<string, { used: number; cap: number }>\n\t/** What the size of the army costs in income */\n\tupkeep: { tier: number; name: string; income: number }\n\tupgrades: Record<string, number>\n\tresearching: string[]\n\t/** Types of the finished buildings the player has, with what those count as */\n\ttech: string[]\n\theroes: HeroSummary[]\n\t/** What the player is set to do, in a mission. Empty in a game without objectives */\n\tobjectives: ObjectiveState[]\n\t/** What the game's `requirement` hook decided, where it differs from what the requirements say (`PlayerState.own.unlocks`) */\n\tunlocks?: Record<string, Message | null>\n\t/** What the game's `available` hook decided, where it differs from what their race says (`PlayerState.own.availability`) */\n\tavailability?: Record<string, boolean>\n\t/**\n\t * What the player gathers of each resource a minute, of late, as the brain's knowledge works it out\n\t * (`Knowledge.own.income`): set by the brain after the view is made; left out for a view of no brain's\n\t */\n\tincome?: Record<ResourceKind, number>\n\t/**\n\t * What is free to spend this think, by resource: the resources less what is promised and held, less what the think\n\t * spent so far (the brain's purse, `ai.purse`). Set by the brain after the view is made; left out for a view of no brain's\n\t */\n\tpurse?: Readonly<Record<ResourceKind, number>>\n}\n\n/**\n * One of a player's bases, as the view clusters its buildings: around each building that takes deposits (a hall, what\n * stands on a mine), or around any building where none does\n *\n * @beta\n */\nexport interface Base {\n\t/** Where it is: the building it is around */\n\tat: Vec2\n\t/** The building it is around: a hall where there is one */\n\tcentre: EntityState\n\t/** Its buildings, the centre among them */\n\tbuildings: UnitSet\n}\n\n/** The coarse grid of the view: every entity in the cell its place falls in, for what is near a point */\nclass Grid {\n\tprivate readonly cells: (EntityState[] | undefined)[]\n\tprivate readonly cols: number\n\tprivate readonly rows: number\n\n\tconstructor(\n\t\twidth: number,\n\t\tdepth: number,\n\t\t/** Where each entity comes in the snapshot, by id: what `near` gives its answer in the order of */\n\t\tprivate readonly index: ReadonlyMap<number, number>\n\t) {\n\t\tthis.cols = Math.max(1, Math.ceil(width / CELL))\n\t\tthis.rows = Math.max(1, Math.ceil(depth / CELL))\n\t\tthis.cells = new Array(this.cols * this.rows)\n\t}\n\n\tprivate col(x: number): number {\n\t\treturn Math.min(this.cols - 1, Math.max(0, Math.floor(x / CELL)))\n\t}\n\n\tprivate row(z: number): number {\n\t\treturn Math.min(this.rows - 1, Math.max(0, Math.floor(z / CELL)))\n\t}\n\n\tadd(entity: EntityState): void {\n\t\tconst index = this.row(entity.z) * this.cols + this.col(entity.x)\n\t\t;(this.cells[index] ??= []).push(entity)\n\t}\n\n\t/** Everything in the cells a circle touches, in the snapshot's order: more than what is within the circle */\n\tnear(point: Vec2, radius: number): EntityState[] {\n\t\tconst found: EntityState[] = []\n\t\tconst c0 = this.col(point.x - radius)\n\t\tconst c1 = this.col(point.x + radius)\n\t\tconst r0 = this.row(point.z - radius)\n\t\tconst r1 = this.row(point.z + radius)\n\t\tfor (let r = r0; r <= r1; r++) {\n\t\t\tfor (let c = c0; c <= c1; c++) {\n\t\t\t\tconst cell = this.cells[r * this.cols + c]\n\t\t\t\tif (cell) for (const entity of cell) found.push(entity)\n\t\t\t}\n\t\t}\n\t\t// cells came row by row: back into the snapshot's order, so that the answer is the same as a scan's\n\t\tconst { index } = this\n\t\tfound.sort((a, b) => index.get(a.id)! - index.get(b.id)!)\n\t\treturn found\n\t}\n}\n\n/**\n * The events of a think, by kind (`AiView.events`): what happened in the tick of the picture that cannot be read from\n * the state (deaths, damage, pings, the game's own)\n *\n * @beta\n */\nexport class ViewEvents {\n\tprivate byType: Map<string, SessionEvent[]> | undefined\n\n\tconstructor(\n\t\t/** Every event of the tick, in order */\n\t\treadonly all: readonly SessionEvent[]\n\t) {}\n\n\t/** The events of one kind, typed: `events.of('death')`, `events.of('ping')` */\n\tof<T extends SessionEvent['type']>(type: T): Extract<SessionEvent, { type: T }>[] {\n\t\tif (!this.byType) {\n\t\t\tthis.byType = new Map()\n\t\t\tfor (const event of this.all) {\n\t\t\t\tlet list = this.byType.get(event.type)\n\t\t\t\tif (!list) this.byType.set(event.type, (list = []))\n\t\t\t\tlist.push(event)\n\t\t\t}\n\t\t}\n\t\treturn (this.byType.get(type) ?? []) as Extract<SessionEvent, { type: T }>[]\n\t}\n\n\t/** What an event of the game's own said this tick (`defineEvent`, replicated to this player), each time it was emitted */\n\tgame<T>(key: EventKey<T>): T[] {\n\t\treturn this.of('game')\n\t\t\t.filter((event) => event.event === key.id)\n\t\t\t.map((event) => event.payload as T)\n\t}\n}\n\n/**\n * What the view is handed beside the snapshot: the last think's view, whose roles it keeps where the game's\n * definitions stand, and a game's own way of finding the roles (`AiOptions.roles`)\n *\n * @beta\n */\nexport interface ViewOptions {\n\t/** The view of the think before: what cost and did not change is kept from it (the roles, the player's reach) */\n\tbefore?: AiView\n\t/** A game's own say on what unit types are for, in place of the kit's inference (`AiOptions.roles`) */\n\troles?: RolesFinder\n\t/** A game's own formula for how strong a unit is, in place of the kit's (`AiOptions.strength`, `BrainDef.strength`) */\n\tstrength?: StrengthFormula\n}\n\n/**\n * A computer player's reading of its picture of the game (`Brain.view`): the snapshot of its seat, indexed once a\n * think and queried as sets (`UnitSet`): `mine`, `allies`, `enemies` (what is in sight now; `enemies.known()` adds\n * the structures remembered), `hostile` (enemies and creeps), `creeps`, `neutral`, `resources`, `all`; the player's\n * own state (`me`); what unit types are for (`roles`, `typesOf`); where things are (`near`, `home`, `bases`, `mines`,\n * `camps`, `regions`); how strong things are (`strength`: `odds`, `matchup`, `counterFor`) and where the strength\n * is (`threat`, the map made when first asked); what the game tells this player (`report`, `component`,\n * `events.game`); and the map's facts (`canPlace`, `findPath`, `cellAt`). Made from the snapshot as the think begins; a set of\n * it is good for the think\n *\n * @beta\n */\nexport class AiView {\n\t/** The game's definitions, as the seat has them */\n\treadonly registry: Registry\n\t/** The player it reads for */\n\treadonly playerId: PlayerId\n\t/** Every entity the player knows of, in the snapshot's order: in sight, and the structures remembered */\n\treadonly all: UnitSet\n\t/** The player's own units and buildings */\n\treadonly mine: UnitSet\n\t/** The allies' units and buildings (one's own left out) */\n\treadonly allies: UnitSet\n\t/** The enemies' units and buildings in sight now, creeps left out. `enemies.known()` adds their structures seen before */\n\treadonly enemies: UnitSet\n\t/** Whatever attacks the player and is in sight: enemies and creeps */\n\treadonly hostile: UnitSet\n\t/** The creeps in sight: hostile to everyone, no one's rival */\n\treadonly creeps: UnitSet\n\t/** What is nobody's and not a resource, in sight: a shop, a neutral building. `neutral.known()` adds those seen before */\n\treadonly neutral: UnitSet\n\t/** The deposits the player knows of: mines and trees in sight, and those seen before (`ofResource(kind)` for one kind) */\n\treadonly resources: UnitSet\n\t/** Every player, as the snapshot has them */\n\treadonly players: readonly PlayerState[]\n\t/** The player a brain plays: resources, supply, tech, heroes, objectives. Mutable for the think */\n\treadonly me: Me\n\t/** What happened in the tick of the picture, by kind */\n\treadonly events: ViewEvents\n\t/** What unit types are for, by the game's definitions: found once, kept while they stand */\n\treadonly roles: Roles\n\t/** The unit types the player has or can come to make: what the roles are narrowed to for it (`typesOf`) */\n\treadonly reachable: ReadonlySet<string>\n\t/**\n\t * How strong things are: a unit, a group, one force against another (`odds`), what answers what (`counterFor`). The\n\t * kit's formula unless the brain was given one; what a type's numbers come to is kept between thinks\n\t */\n\treadonly strength: Strength\n\tprivate threatMap: ThreatMap | undefined\n\tprivate readonly grid: Grid\n\tprivate readonly byIdMap = new Map<number, EntityState>()\n\tprivate readonly indexById = new Map<number, number>()\n\tprivate readonly playerById = new Map<PlayerId, PlayerState>()\n\tprivate readonly namesMap = new Map<string, EntityState>()\n\tprivate readonly typesByRole: Map<string, readonly UnitTypeDef[]>\n\t/** The race the view's reach was found for: a player given another race finds it anew */\n\tprivate readonly race: string | undefined\n\tprivate basesFound: Base[] | undefined\n\tprivate lanesFound: readonly Lane[] | undefined\n\n\tconstructor(\n\t\t/** The picture it reads: the snapshot of the seat, plain data, the only input a brain has */\n\t\treadonly snapshot: Snapshot,\n\t\t/** The seat, for the map's facts: the ground, the regions, the mines, the camps */\n\t\treadonly session: GameSession,\n\t\toptions: ViewOptions = {}\n\t) {\n\t\tconst { registry, playerId, terrain } = session\n\t\tthis.registry = registry\n\t\tthis.playerId = playerId\n\t\tthis.players = snapshot.players\n\t\tfor (const player of snapshot.players) this.playerById.set(player.id, player)\n\t\tconst self = this.playerById.get(playerId)\n\t\tthis.me = meOf(self, playerId)\n\t\tthis.events = new ViewEvents(snapshot.events)\n\t\tthis.grid = new Grid(terrain.width, terrain.depth, this.indexById)\n\n\t\t// the one pass over the picture: every entity to its sets, its cell, its index, its name\n\t\tconst mine: EntityState[] = []\n\t\tconst allies: EntityState[] = []\n\t\tconst enemies: EntityState[] = []\n\t\tconst enemiesRemembered: EntityState[] = []\n\t\tconst hostile: EntityState[] = []\n\t\tconst hostileRemembered: EntityState[] = []\n\t\tconst creeps: EntityState[] = []\n\t\tconst creepsRemembered: EntityState[] = []\n\t\tconst neutral: EntityState[] = []\n\t\tconst neutralRemembered: EntityState[] = []\n\t\tconst resources: EntityState[] = []\n\t\tconst ownedTypes = new Set<string>()\n\t\tsnapshot.entities.forEach((entity, index) => {\n\t\t\tthis.byIdMap.set(entity.id, entity)\n\t\t\tthis.indexById.set(entity.id, index)\n\t\t\tthis.grid.add(entity)\n\t\t\tif (entity.name !== undefined) this.namesMap.set(entity.name, entity)\n\t\t\tif (entity.owner === playerId) {\n\t\t\t\tmine.push(entity)\n\t\t\t\townedTypes.add(entity.type)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (registry.units.has(entity.type) && registry.unit(entity.type).kind === 'resource') {\n\t\t\t\tresources.push(entity)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst owner = this.playerById.get(entity.owner)\n\t\t\tif (!owner) return\n\t\t\t// creeps are hostile to everyone and no one's rival: with the enemies in `hostile`, apart in `creeps`; a creep\n\t\t\t// made friendly (`setRelation`) is in `creeps` alone\n\t\t\tif (owner.creeps) (entity.visible ? creeps : creepsRemembered).push(entity)\n\t\t\tswitch (owner.relation) {\n\t\t\t\tcase 'ally':\n\t\t\t\t\tif (!owner.creeps) allies.push(entity)\n\t\t\t\t\tbreak\n\t\t\t\tcase 'enemy':\n\t\t\t\t\t;(entity.visible ? hostile : hostileRemembered).push(entity)\n\t\t\t\t\tif (!owner.creeps) (entity.visible ? enemies : enemiesRemembered).push(entity)\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (!owner.creeps) (entity.visible ? neutral : neutralRemembered).push(entity)\n\t\t\t}\n\t\t})\n\t\tthis.all = new UnitSet(this, snapshot.entities)\n\t\tthis.mine = new UnitSet(this, mine)\n\t\tthis.allies = new UnitSet(this, allies)\n\t\tthis.enemies = new UnitSet(this, enemies, enemiesRemembered)\n\t\tthis.hostile = new UnitSet(this, hostile, hostileRemembered)\n\t\tthis.creeps = new UnitSet(this, creeps, creepsRemembered)\n\t\tthis.neutral = new UnitSet(this, neutral, neutralRemembered)\n\t\tthis.resources = new UnitSet(this, resources)\n\n\t\t// what costs and does not change between thinks is kept from the view before: the roles of the game's types,\n\t\t// and the player's reach, found again when it has a type it could not make (given one, a race of two) or when\n\t\t// what the game lets it make changed (a type a mission unlocks)\n\t\tconst before = options.before\n\t\tconst player = { id: playerId, race: self?.race, availability: self?.own?.availability }\n\t\tthis.race = self?.race\n\t\tthis.roles = before?.roles ?? findRoles(registry, player, options.roles)\n\t\tlet kept = before && before.race === this.race && sameAvailability(before.me.availability, player.availability) ? before : undefined\n\t\tif (kept) {\n\t\t\tconst reach = kept.reachable\n\t\t\tfor (const type of ownedTypes) if (!reach.has(type)) kept = undefined\n\t\t}\n\t\tthis.reachable = kept?.reachable ?? reachableTypes(registry, player, ownedTypes)\n\t\tthis.typesByRole = kept?.typesByRole ?? new Map()\n\t\t// what the types' numbers come to is kept too, as long as the formula is the one it was found by\n\t\tconst formula = options.strength ?? before?.strength.formula\n\t\tthis.strength = before && before.strength.formula === formula ? before.strength : new Strength(registry, formula)\n\t\tthis.strength.view = this\n\t}\n\n\t/**\n\t * Where the strength is: an influence map over the picture, the friendly and the enemy strength that reaches each\n\t * cell of a coarse grid, by layer (`threat.at(point)`, `around`, `hot`). Made when first asked, once a think\n\t */\n\tget threat(): ThreatMap {\n\t\treturn (this.threatMap ??= new ThreatMap(this))\n\t}\n\n\t/** @internal What is in the cells of the grid a circle touches, in the snapshot's order: for a set's `near` */\n\tgridNear(point: Vec2, radius: number): EntityState[] {\n\t\treturn this.grid.near(point, radius)\n\t}\n\n\t/** The tick of the picture */\n\tget tick(): number {\n\t\treturn this.snapshot.tick\n\t}\n\n\t/** Seconds into the game, as of the picture */\n\tget time(): number {\n\t\treturn this.snapshot.tick / this.session.tickRate\n\t}\n\n\t/** Items lying on the ground where the player sees it */\n\tget items(): readonly GroundItemState[] {\n\t\treturn this.snapshot.items\n\t}\n\n\t/** What the game tells the player about itself (`GameModule.report`): a wave number, a score */\n\tget report(): Record<string, unknown> | undefined {\n\t\treturn this.snapshot.report\n\t}\n\n\t/** An entity the player knows of, by id: none for one gone, or never seen */\n\tbyId(id: number | undefined): EntityState | undefined {\n\t\treturn id === undefined ? undefined : this.byIdMap.get(id)\n\t}\n\n\t/** @internal Where an entity comes in the snapshot: for sets to keep its order */\n\tindexOf(entity: EntityState): number {\n\t\treturn this.indexById.get(entity.id) ?? Infinity\n\t}\n\n\t/** The definition of an entity's type */\n\tdef(entity: EntityState): UnitTypeDef {\n\t\treturn this.registry.unit(entity.type)\n\t}\n\n\t/** A player, by id */\n\tplayer(id: PlayerId): PlayerState | undefined {\n\t\treturn this.playerById.get(id)\n\t}\n\n\t/** What an entity's owner is to the player: `self`, `ally`, `enemy`, `neutral`. Creeps are `enemy` */\n\trelation(entity: EntityState): PlayerState['relation'] | undefined {\n\t\treturn this.playerById.get(entity.owner)?.relation\n\t}\n\n\t/** Whether an entity is a rival's, or a creep */\n\tisHostile(entity: EntityState): boolean {\n\t\treturn this.relation(entity) === 'enemy'\n\t}\n\n\t/** Whether an entity is a creep's */\n\tisCreep(entity: EntityState): boolean {\n\t\treturn !!this.playerById.get(entity.owner)?.creeps\n\t}\n\n\t/** Whether an entity is the player's own or an ally's */\n\tisFriendly(entity: EntityState): boolean {\n\t\tconst relation = this.relation(entity)\n\t\treturn relation === 'self' || relation === 'ally'\n\t}\n\n\t/** The roles of an entity's type, or of a type by id */\n\troleOf(entity: EntityState | string): readonly AiRole[] {\n\t\treturn this.roles.of(typeof entity === 'string' ? entity : entity.type)\n\t}\n\n\t/** Whether an entity's type, or a type by id, has a role */\n\thasRole(entity: EntityState | string, role: AiRole): boolean {\n\t\treturn this.roles.has(typeof entity === 'string' ? entity : entity.type, role)\n\t}\n\n\t/**\n\t * The unit types with a role that are the player's own: those it has or can come to make (`reachable`), in the\n\t * game's order, so that the first of a kind is the one meant first. A game of two races gives each player its own\n\t */\n\ttypesOf(role: AiRole): readonly UnitTypeDef[] {\n\t\tlet found = this.typesByRole.get(role)\n\t\tif (!found) this.typesByRole.set(role, (found = this.roles.types(role).filter((def) => this.reachable.has(def.id))))\n\t\treturn found\n\t}\n\n\t/** Whether the player has the finished buildings something asks for (`UnitTypeDef.requires`) */\n\thas(requires: readonly string[] | undefined): boolean {\n\t\treturn (requires ?? []).every((id) => this.me.tech.includes(id))\n\t}\n\n\t/** The player's home: its first hall, or its first building where it has no hall. None with no buildings */\n\thome(): EntityState | undefined {\n\t\treturn this.mine.withRole('hall').first() ?? this.mine.buildings().first()\n\t}\n\n\t/**\n\t * The player's bases: its buildings clustered around what takes deposits (halls, what stands on a mine), each to\n\t * the nearest of those within reach; and where there is nothing that takes deposits (a game with no economy), around\n\t * any building, the clusters made as the buildings come. Home first\n\t */\n\tbases(): readonly Base[] {\n\t\tif (this.basesFound) return this.basesFound\n\t\tconst buildings = this.mine.buildings()\n\t\tconst reach = BASE_REACH * BASE_REACH\n\t\t// what takes deposits is the middle of a base; one within reach of an earlier one is of that base (a hall and what\n\t\t// stands on the mine beside it), not a base of its own\n\t\tconst centres: EntityState[] = []\n\t\tfor (const building of buildings) {\n\t\t\tif (!this.def(building).dropOff || centres.some((centre) => distSq(building, centre) < reach)) continue\n\t\t\tcentres.push(building)\n\t\t}\n\t\tconst members = new Map<number, EntityState[]>()\n\t\tfor (const centre of centres) members.set(centre.id, [])\n\t\tfor (const building of buildings) {\n\t\t\tlet best: EntityState | undefined\n\t\t\tlet bestDistance = reach\n\t\t\tfor (const centre of centres) {\n\t\t\t\tconst d = distSq(building, centre)\n\t\t\t\tif (d < bestDistance) {\n\t\t\t\t\tbestDistance = d\n\t\t\t\t\tbest = centre\n\t\t\t\t}\n\t\t\t}\n\t\t\t// too far from every base to be of one: a base of its own, around it\n\t\t\tif (!best) {\n\t\t\t\tbest = building\n\t\t\t\tcentres.push(building)\n\t\t\t\tmembers.set(building.id, [])\n\t\t\t}\n\t\t\tmembers.get(best.id)!.push(building)\n\t\t}\n\t\treturn (this.basesFound = centres.map((centre) => ({\n\t\t\tat: { x: centre.x, z: centre.z },\n\t\t\tcentre,\n\t\t\tbuildings: new UnitSet(this, members.get(centre.id))\n\t\t})))\n\t}\n\n\t/** The deposits near a base, in sight or remembered: what it gathers from */\n\tresourcesNear(base: Base | Vec2, radius = BASE_REACH): UnitSet {\n\t\treturn this.resources.near('at' in base ? base.at : base, radius)\n\t}\n\n\t/**\n\t * Where the game's money is mined, as the map shows them, under the fog too (`GameSession.mines`): what a computer\n\t * player looks to for another hall. Where the session does not say, the deposits of the money it knows of\n\t */\n\tmines(): readonly MineInfo[] {\n\t\tconst known = this.session.can.computer?.mines()\n\t\tif (known) return known\n\t\tconst money = this.registry.currency ?? this.registry.resources[0]?.id ?? ''\n\t\treturn this.resources.ofResource(money).map((mine) => ({ id: mine.id, x: mine.x, z: mine.z }))\n\t}\n\n\t/** The creep camps of the map: where they are is part of the map, which everyone knows */\n\tcamps(): readonly CampInfo[] {\n\t\treturn this.session.camps()\n\t}\n\n\t/**\n\t * The lanes of the map (`GameSession.lanes`: its paths with a spawner of each side at their ends), as the map shows\n\t * them: none where the session does not say, or the map has none. Read once a think\n\t */\n\tlanes(): readonly Lane[] {\n\t\treturn (this.lanesFound ??= this.session.can.computer?.lanes() ?? [])\n\t}\n\n\t/** The regions of the map, by name, as the map was made */\n\tget regions(): readonly MapRegion[] {\n\t\treturn this.session.regions\n\t}\n\n\t/** A region of the map, by name */\n\tregion(name: string): MapRegion | undefined {\n\t\treturn this.session.regions.find((region) => region.name === name)\n\t}\n\n\t/** Whether a point is in a named region of the map. False for a region the map does not have */\n\tinRegion(name: string, point: Vec2): boolean {\n\t\tconst region = this.region(name)\n\t\treturn !!region && inShape(region.shape, point)\n\t}\n\n\t/** An entity the map or the rules named (`world.named`), where the player knows of it: \"the gate\", \"the hero\" */\n\tnamed(name: string): EntityState | undefined {\n\t\treturn this.namesMap.get(name)\n\t}\n\n\t/** What the game replicates to this player of an entity (`Component.replicate`), with the component's type */\n\tcomponent<T, S = T>(entity: EntityState, component: Component<T, S>): S | undefined {\n\t\treturn entity.components?.[component.id] as S | undefined\n\t}\n\n\t/** Whether the player could build this here, as far as it can tell: no on ground it has not explored */\n\tcanPlace(unitType: string, point: Vec2): boolean {\n\t\treturn this.session.canPlace(unitType, point)\n\t}\n\n\t/** The value of one of the game's layers of cells at a point (`Terrain.cells`, `CellLayerDef`): 0 where it is not painted */\n\tcellAt(layer: string, x: number, z: number): number {\n\t\treturn this.session.terrain.cellAt(layer, x, z)\n\t}\n\n\t/** One of the game's layers of cells whole, row by row (`Terrain.cells`), to read and not to change: none where nothing is painted */\n\tcells(layer: string): Readonly<Uint8Array> | undefined {\n\t\treturn this.session.terrain.cells[layer]\n\t}\n\n\t/** The route a unit would take, over the ground the player knows */\n\tfindPath(from: Vec2, to: Vec2, flying?: boolean): Vec2[] | null {\n\t\treturn this.session.findPath(from, to, flying)\n\t}\n\n\t/** What the view found of the roles, for the debug tools: each role and its types among the player's own */\n\tinspect(): Record<string, unknown> {\n\t\tconst roles: Record<string, string[]> = {}\n\t\tfor (const [role, types] of Object.entries(this.roles.report())) {\n\t\t\tconst own = types.filter((type) => this.reachable.has(type))\n\t\t\tif (own.length) roles[role] = own\n\t\t}\n\t\treturn { roles }\n\t}\n}\n\n/** The player's own state out of the snapshot: empty where the snapshot has none (a seat out of the game) */\nfunction meOf(self: PlayerState | undefined, id: PlayerId): Me {\n\tconst own = self?.own\n\treturn {\n\t\tid,\n\t\tname: self?.name ?? '',\n\t\tteam: self?.team ?? 0,\n\t\t...(self?.race !== undefined && { race: self.race }),\n\t\tdefeated: self?.defeated ?? true,\n\t\tresources: own?.resources ?? {},\n\t\tsupplyUsed: own?.supplyUsed ?? 0,\n\t\tsupplyCap: own?.supplyCap ?? 0,\n\t\t...(own?.supplies && { supplies: own.supplies }),\n\t\tupkeep: own?.upkeep ?? { tier: 0, name: '', income: 1 },\n\t\tupgrades: own?.upgrades ?? {},\n\t\tresearching: own?.researching ?? [],\n\t\ttech: own?.tech ?? [],\n\t\theroes: own?.heroes ?? [],\n\t\tobjectives: own?.objectives ?? [],\n\t\t...(own?.unlocks && { unlocks: own.unlocks }),\n\t\t...(own?.availability && { availability: own.availability })\n\t}\n}\n\n/** Whether two of what the game's `available` hook decided are the same: by type, either left out as none */\nfunction sameAvailability(a: Record<string, boolean> | undefined, b: Record<string, boolean> | undefined): boolean {\n\tif (a === b) return true\n\tconst keys = Object.keys(a ?? {})\n\tif (keys.length !== Object.keys(b ?? {}).length) return false\n\treturn keys.every((key) => a![key] === b?.[key])\n}\n","import type { Cost } from '#engine/defs'\nimport type { AiArea } from './area'\nimport { exp } from '#engine/exactMath'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { considerationsLine } from './report'\nimport type { Squad, SquadOptions } from './squads'\nimport { UnitSet } from './view'\n\n/*\n * Goals that score themselves (AI plan, B1): how a computer player decides what to do with what it has. The old way\n * was a ladder of ifs (`if (underAttack) defend() else if (ready) attack()`), and the first version of the melee\n * player's goals was a constant each (defend 1, attack 0.8): one ran, for the whole army, and nothing weighed \"a small\n * raid at my expansion while my army is away\" against \"their army at my gate\". This is the **utility** pattern,\n * written down once:\n *\n * - A **goal** is something the computer could do (`defineGoal`): defend, attack, creep, scout, raid their workers.\n * - It scores itself from **considerations**: each a question over what it sees that gives a number (how many enemies\n * at my buildings; the strength of my idle army over my whole army; seconds since their base was looked at), passed\n * through a **curve** that says how much that number matters, as 0..1 (`curve.linear`, `saturate`, `inverse`,\n * `step`, `band`, `custom`). The goal's **score** is the product of its considerations times its `weight`: a product\n * is a soft AND, so a goal that wants several things at once scores high only when it has them all, and a\n * consideration at 0 vetoes it outright (no worker seen: no raid), which saves every goal an `if`.\n * - The **picker** (`Goals.think`, once a think) scores every goal, takes them best first, and gives each what it\n * **claims**: units from the pool (what no goal holds) and money; the next goal sees what is left, until nothing\n * scores above `min`. So several goals run at once on different units, and a goal that claims nothing of what it\n * asked for is not picked.\n * - **Commitment**, or hysteresis: two goals at 0.61 and 0.60 would swap every think and the army would walk in\n * circles. A picked goal keeps its claim for `commitment` seconds unless another scores more than it by `margin`;\n * after that, anything that scores more may take from it. `urgent` goals (the melee player's defend, when the raid is\n * stronger than what the army out holds) break any commitment the moment they score above the committed goal.\n * - **Who may move a unit, in one place.** A unit is held by one goal at a time (`holder`), taken from the pool when\n * the goal is picked and given back when it stops; a rule (B2) or the defence (C4) that wants a unit takes it\n * through `take`, and the goal that held it is told (`stop('told')`). Squads (C1) are made of what a goal holds.\n *\n * The report of it all (`report`: every goal's score, its considerations with their raw and curved values, what it\n * holds and why it was not picked) is what the debug tools show, so \"why did it do that\" is read, not guessed. What\n * is held is plain data kept in the brain's memory (`save`, `restore`), ticks and ids: a save keeps the army's goal\n */\n\n/**\n * A response curve: a number (how many, how strong, how long) to how much it matters, 0..1\n *\n * @beta\n */\nexport type Curve = (x: number) => number\n\nconst clamp01 = (x: number) => (x > 1 ? 1 : x > 0 ? x : 0)\n\n/**\n * The usual response curves, each a line (`consider(name, read, curve.saturate(6))`): how a raw number becomes \"how\n * much do I care\". A curve gives 0..1; what gives nonsense (NaN) counts as 0\n *\n * @beta\n */\nexport const curve = {\n\t/** A straight line from 0 at 0 to 1 at `max` (1 when left out: for a ratio), flat beyond: twice the units, twice the care, up to a point */\n\tlinear:\n\t\t(max = 1): Curve =>\n\t\t(x) =>\n\t\t\tclamp01(x / max),\n\t/** 1 − e^(−x/k): rises fast, then levels off at 1 (0.63 at `k`, 0.86 at `2k`): the sixth worker seen matters less than the first */\n\tsaturate:\n\t\t(k: number): Curve =>\n\t\t(x) =>\n\t\t\tx <= 0 ? 0 : 1 - exp(-x / k),\n\t/** k / (k + x): 1 at 0, falling to a half at `k` and towards 0: the less there is of it, the better (how held their base is) */\n\tinverse:\n\t\t(k: number): Curve =>\n\t\t(x) =>\n\t\t\tx <= 0 ? 1 : k / (k + x),\n\t/** 0 below `at`, 1 from it on: a threshold (a wave is ready at so many units), an on-off (any intruder at all: `step(1)`) */\n\tstep:\n\t\t(at: number): Curve =>\n\t\t(x) =>\n\t\t\tx >= at ? 1 : 0,\n\t/** 1 between `low` and `high`, 0 outside: a window (an army of between 4 and 12) */\n\tband:\n\t\t(low: number, high: number): Curve =>\n\t\t(x) =>\n\t\t\tx >= low && x <= high ? 1 : 0,\n\t/** A shape of the game's own: whatever the function gives, kept to 0..1 */\n\tcustom:\n\t\t(fn: (x: number) => number): Curve =>\n\t\t(x) =>\n\t\t\tclamp01(fn(x))\n} as const\n\n/**\n * One question a goal asks of what it sees, and how much the answer matters: `read` gives the raw number, `curve`\n * turns it into 0..1. The report keeps both\n *\n * @beta\n */\nexport interface Consideration {\n\t/** What it asks, for the report: \"intruders at my buildings\" */\n\tname: string\n\t/** The raw number, read from the brain each think: cheap, or cached for the think (`ai.cache`) */\n\tread: (ai: Brain) => number\n\t/** How much the number matters, 0..1 */\n\tcurve: Curve\n}\n\n/**\n * A consideration: a question with a name, and the curve that says how much its answer matters (`curve.linear()`\n * when left out: the number is a ratio already)\n *\n * @beta\n */\nexport function consider(name: string, read: (ai: Brain) => number, shape: Curve = curve.linear()): Consideration {\n\treturn { name, read, curve: shape }\n}\n\n/**\n * What a goal is about, and so what it competes with: `army` goals claim units, `economy` goals money, `squad` and\n * `hero` goals are about one of those (scored once each until squads (C1) and heroes (C2) score them apiece), or a\n * game's own word\n *\n * @beta\n */\nexport type GoalScope = 'army' | 'economy' | 'squad' | 'hero' | (string & {})\n\n/**\n * Why a goal lost its claim (`GoalDef.stop`): `beaten` by one that scored more by the margin, `urgent` by an urgent\n * one, `done` as its own score fell to nothing, `told` by a rule or a module that took its units, `removed` from the\n * brain\n *\n * @beta\n */\nexport type StopReason = 'beaten' | 'urgent' | 'done' | 'told' | 'removed'\n\n/**\n * What a goal claims to run: units from the pool and money from the purse. The picker gives each goal what it asks\n * of what is left, best goal first\n *\n * @beta\n */\nexport interface GoalClaims {\n\t/**\n\t * The units it takes, chosen from what it may have (`available`: the pool, and what goals it may take from hold):\n\t * the nearest six fighters, one scout, everything. A goal that asks for units and gets none is not picked\n\t */\n\tunits?: (ai: Brain, available: UnitSet) => Iterable<EntityState>\n\t/**\n\t * The money it holds while it runs, in the game's money (`Registry.currency`) as a number, or as a cost by resource;\n\t * a function for one that depends. Held against the purse (`Goals.reserved`), given back when the goal stops\n\t */\n\tmoney?: number | Cost | ((ai: Brain) => number | Cost | undefined)\n}\n\n/**\n * What a picked goal was given (`GoalDef.run`): the units it holds this think (the dead and the lost dropped), the\n * money, when it was picked, and whether this is the first think it runs\n *\n * @beta\n */\nexport interface Claimed {\n\t/** The units it holds, as of this think's picture */\n\tunits: UnitSet\n\t/** The money it holds, where it asked for any */\n\tmoney?: Cost\n\t/** The tick it was picked at */\n\tbegan: number\n\t/** Whether this is the first think it runs: when its orders are to be sent, once */\n\tfirst: boolean\n\t/**\n\t * Makes a squad the goal owns (`ai.squads.make` with the goal as its `owner`): when the goal stops, its squads go.\n\t * Called again for a name the goal has a squad of already (a run each think), it is that squad, kept as it is (its\n\t * task, its `size`), the units given added to it and its options those given now\n\t */\n\tsquad(name: string, units: Iterable<EntityState | number>, options?: SquadOptions): Squad\n}\n\n/**\n * A goal: something the computer could do, scored by its considerations, run with what it claims (`defineGoal`)\n *\n * @beta\n */\nexport interface GoalDef {\n\t/** Unique among the brain's goals, prefixed as components are (the engine's `ai.defend`, a game's `mygame.raid`) */\n\tid: string\n\t/** What it is about: `army` when left out */\n\tscope?: GoalScope\n\t/** Its questions: the score is their product (a soft AND: one at 0 vetoes the goal), times the weight */\n\tconsiderations: Consideration[]\n\t/** What it is worth against the other goals at their best: 1 when left out */\n\tweight?: number\n\t/** The score under which it is not picked: the picker's (`PickingOptions.min`) when left out */\n\tmin?: number\n\t/** What it takes to run: units, money. None: it runs on its score alone, holding nothing */\n\tclaims?: GoalClaims\n\t/**\n\t * Seconds it keeps its claim once picked, unless another scores more than it by the margin, or an urgent one scores\n\t * more at all. The picker's default when left out. Hysteresis: without it two close goals swap every think\n\t */\n\tcommitment?: number\n\t/** How much more another goal must score to take from this one within its commitment: the picker's when left out */\n\tmargin?: number\n\t/** Whether it may break another goal's commitment as soon as it scores more: a raid that cannot wait */\n\turgent?: boolean | ((ai: Brain) => boolean)\n\t/** Seconds after it stops before it may be picked again */\n\tcooldown?: number\n\t/** What it does, each think it holds its claim: `claimed.first` on the first, where its orders are sent once and then watched */\n\trun(ai: Brain, claimed: Claimed): void\n\t/** Told when it loses its claim, and why: to let go of what it was doing */\n\tstop?(ai: Brain, why: StopReason, claimed: Claimed): void\n}\n\n/**\n * Defines a goal: checked, and given back as it is, for a brain's `goals`, `meleeBrain.with({ goals })`, or\n * `ai.goals.add`\n *\n * @beta\n */\nexport function defineGoal(def: GoalDef): GoalDef {\n\tif (!def.id) throw new Error('A goal needs an id')\n\tif (!Array.isArray(def.considerations)) throw new Error(`The goal \"${def.id}\" needs its considerations, as a list`)\n\tif (typeof def.run !== 'function') throw new Error(`The goal \"${def.id}\" needs a run`)\n\treturn def\n}\n\n/**\n * How a brain picks among its goals, where a goal does not say for itself (`BrainDef.picking`)\n *\n * @beta\n */\nexport interface PickingOptions {\n\t/** The score under which a goal is not picked: 0.05 when left out */\n\tmin?: number\n\t/** How much more a goal must score than a committed one to take from it: 0.15 when left out */\n\tmargin?: number\n\t/** Seconds a picked goal keeps its claim: 5 when left out */\n\tcommitment?: number\n}\n\n/**\n * What a goal holds while it runs: its units (ids, of the player's), its money, when it was picked and until when it\n * is committed. Plain data, kept in the brain's memory\n *\n * @beta\n */\nexport interface Hold {\n\t/** The units it holds, by id, in the picture's order */\n\tunits: number[]\n\t/** The money it holds (`GoalClaims.money`) */\n\tmoney?: Cost\n\t/** The tick it was picked at */\n\tsince: number\n\t/** The tick its commitment ends at: for a rule's or a module's hold (`take` with `by`), the tick it lets go at */\n\tuntil: number\n\t/** For a rule's or a module's hold: kept until let go of (`release`), whatever `until` says. A squad of one's own holds so */\n\tkept?: true\n\t/** What it scored when picked */\n\tscore: number\n}\n\n/**\n * What the goals remember between thinks: what each holds, and until when each is on cooldown\n *\n * @beta\n */\nexport interface GoalsMemory {\n\t/** The version of this shape */\n\tv: 1\n\t/** What each goal holds, by goal id */\n\tholds: Record<string, Hold>\n\t/** The tick each goal on cooldown may be picked again at, by goal id */\n\tcooldowns: Record<string, number>\n}\n\n/**\n * One goal as the picker last saw it: for the debug tools, and for \"why did it do that\"\n *\n * @beta\n */\nexport interface GoalReport {\n\t/** The goal */\n\tid: string\n\t/** What it is about */\n\tscope: GoalScope\n\t/** Its score: the considerations' product, weighed */\n\tscore: number\n\t/**\n\t * Each question, its raw answer and how much that mattered. One after a question answered 0 is not asked (the goal\n\t * is vetoed already): `asked: false`, its numbers 0\n\t */\n\tconsiderations: { name: string; value: number; curved: number; asked?: false }[]\n\t/** Whether it ran this think */\n\tpicked: boolean\n\t/** Whether it may break a commitment now */\n\turgent: boolean\n\t/** What it holds: how many units (and which, `ids`), how strong together, the money, since when and until when (ticks) */\n\theld?: { units: number; ids: number[]; strength: number; money?: Cost; since: number; until: number }\n\t/** Why it did not run, where it scored enough: `cooldown`, `nothing to claim`, or what it lost its claim to */\n\twhy?: string\n}\n\n/** Where a goal's definition is kept, with what the picker found of it this think */\ninterface Entry {\n\tdef: GoalDef\n\t/** Its place in the order added: the tie-breaker among equal scores, so that two thinks pick alike */\n\torder: number\n\tscore: number\n\turgent: boolean\n\tconsiderations: GoalReport['considerations']\n\tpicked: boolean\n\twhy?: string\n\t/** Why it lost units this think, where it did: its stop reason once it has none left */\n\tlost?: StopReason\n\t/** The goal it lost units to this think, for the decision log */\n\tlostTo?: string\n}\n\nconst MIN = 0.05\nconst MARGIN = 0.15\nconst COMMITMENT = 5\n\n/**\n * The brain's goals and their picker (`ai.goals`): what the computer could do, scored each think, the best given what\n * they claim (`think`, once a think: run by the `goals()` module, or by a module of the brain's own in its place among\n * the others). What each holds is read here (`held`, `holds`, `holder`, `pool`), taken by a rule or a module\n * (`take`), and reported (`report`)\n *\n * @beta\n */\nexport class Goals implements AiArea {\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'goals'\n\t/** What the log says where a save's memory of it is of a shape it does not read */\n\treadonly afresh = 'the save remembers what the computer player’s goals held in a shape this brain does not read: they start afresh'\n\n\t/** How much each goal scored this think, by id: what the debug tools showed before the report */\n\tscores: Record<string, number> = {}\n\t/** The goal that scored highest above the minimum this think: what the army is on. None when nothing is worth doing */\n\tbest: string | undefined\n\tprivate readonly entries = new Map<string, Entry>()\n\tprivate holds: Record<string, Hold> = {}\n\tprivate cooldowns: Record<string, number> = {}\n\tprivate added = 0\n\tprivate thoughtAt = -1\n\tprivate readonly min: number\n\tprivate readonly margin: number\n\tprivate readonly commitment: number\n\n\tconstructor(\n\t\t/** The brain they are the goals of */\n\t\treadonly ai: Brain,\n\t\toptions: PickingOptions = {}\n\t) {\n\t\tthis.min = options.min ?? MIN\n\t\tthis.margin = options.margin ?? MARGIN\n\t\tthis.commitment = options.commitment ?? COMMITMENT\n\t}\n\n\t/** Adds goals to pick among: a brain's own (`BrainDef.goals`), the seat's (`AiOptions.goals`), a module's */\n\tadd(...defs: GoalDef[]): void {\n\t\tfor (const def of defs) {\n\t\t\tif (this.entries.has(def.id)) throw new Error(`The brain \"${this.ai.def.id}\" has two goals called \"${def.id}\"`)\n\t\t\tthis.entries.set(def.id, { def, order: this.added++, score: 0, urgent: false, considerations: [], picked: false })\n\t\t}\n\t}\n\n\t/** Takes a goal out: what it held goes back to the pool, and it is told `removed`. Whether there was one */\n\tremove(id: string): boolean {\n\t\tconst entry = this.entries.get(id)\n\t\tif (!entry) return false\n\t\tthis.release(id, 'removed')\n\t\tthis.entries.delete(id)\n\t\treturn true\n\t}\n\n\t/** The goals, as added */\n\tlist(): GoalDef[] {\n\t\treturn [...this.entries.values()].map((entry) => entry.def)\n\t}\n\n\t/** A goal by id */\n\tget(id: string): GoalDef | undefined {\n\t\treturn this.entries.get(id)?.def\n\t}\n\n\t/** What a goal holds, while it does */\n\theld(id: string): Hold | undefined {\n\t\treturn this.holds[id]\n\t}\n\n\t/** What every goal holds, by goal id */\n\tall(): Readonly<Record<string, Hold>> {\n\t\treturn this.holds\n\t}\n\n\t/** The goal that holds a unit, by the unit's id: none for a unit in the pool */\n\tholder(unit: number): string | undefined {\n\t\tfor (const id in this.holds) if (this.holds[id].units.includes(unit)) return id\n\t\treturn undefined\n\t}\n\n\t/** The player's units no goal holds, as of the think's picture: what a goal picked next may claim */\n\tpool(): UnitSet {\n\t\tconst held = this.heldIds()\n\t\tconst { mine } = this.ai.view\n\t\treturn held.size ? mine.where((entity) => !held.has(entity.id)) : mine\n\t}\n\n\t/** The money the goals hold together (`GoalClaims.money`): held in the purse (`ai.purse`), which takes it off what is free */\n\treserved(): Cost {\n\t\tconst sum: Cost = {}\n\t\tfor (const id in this.holds) {\n\t\t\tconst { money } = this.holds[id]\n\t\t\tfor (const kind in money) sum[kind] = (sum[kind] ?? 0) + money[kind]\n\t\t}\n\t\treturn sum\n\t}\n\n\t/**\n\t * Takes units from whatever goals hold them, for a rule (B2) or a module (the defence, C4) that wants them: a goal\n\t * left with none is told why (`told` when left out). Those of them that were held, by id.\n\t *\n\t * With `by`, the units are then held by that rule or module itself (`by.id`, which names no goal: `rule:attack`),\n\t * for `by.seconds` (30 when left out) or until `release(by.id)`: no goal may claim them meanwhile, for a rule goes\n\t * before the goals (the one order of who may move a unit: goals, then rules take, then the defence; micro never\n\t * retasks). Units taken again by the same id are added to what it holds, and its time starts again. `seconds:\n\t * Infinity` holds them until let go of (`release`, `drop`): what a squad that is no goal's holds its units by\n\t */\n\ttake(units: Iterable<number>, why: StopReason = 'told', by?: { id: string; seconds?: number }): number[] {\n\t\tconst wanted = new Set(units)\n\t\tconst taken: number[] = []\n\t\tfor (const id in this.holds) {\n\t\t\tif (id === by?.id) continue\n\t\t\tconst hold = this.holds[id]\n\t\t\tconst kept = hold.units.filter((unit) => !wanted.has(unit))\n\t\t\tif (kept.length === hold.units.length) continue\n\t\t\ttaken.push(...hold.units.filter((unit) => wanted.has(unit)))\n\t\t\thold.units = kept\n\t\t\tif (!kept.length) this.release(id, why)\n\t\t}\n\t\tif (by) {\n\t\t\tif (this.entries.has(by.id)) throw new Error(`\"${by.id}\" is a goal of the brain: what a rule holds needs a name of its own`)\n\t\t\tconst { tick, session } = this.ai\n\t\t\t// what it held and is gone is let go of here: a brain with no goals has no picker to do it each think\n\t\t\tconst kept = (this.holds[by.id]?.units ?? []).filter((unit) => this.ai.view.mine.has(unit))\n\t\t\tconst all = [...kept, ...[...wanted].filter((unit) => !kept.includes(unit) && this.ai.view.mine.has(unit))]\n\t\t\tall.sort((a, b) => this.ai.view.indexOf(this.ai.view.byId(a)!) - this.ai.view.indexOf(this.ai.view.byId(b)!))\n\t\t\tconst seconds = by.seconds ?? 30\n\t\t\t// for ever is no number a save can keep: such a hold is `kept`, and its `until` is when it was taken\n\t\t\tconst forever = seconds === Infinity\n\t\t\tthis.holds[by.id] = {\n\t\t\t\tunits: all,\n\t\t\t\tsince: this.holds[by.id]?.since ?? tick,\n\t\t\t\tuntil: forever ? tick : tick + Math.round(seconds * session.tickRate),\n\t\t\t\tscore: 1,\n\t\t\t\t...(forever && { kept: true as const })\n\t\t\t}\n\t\t}\n\t\treturn taken\n\t}\n\n\t/**\n\t * Adds units from the pool (what nothing holds) to what a goal, a rule or a module holds: a squad's reinforcements\n\t * (`Squad.reinforce`). What another holds is passed over: `take` is for that. Those given, by id\n\t */\n\tgive(id: string, units: Iterable<number>): number[] {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return []\n\t\tconst { view } = this.ai\n\t\tconst held = this.heldIds()\n\t\tconst given: number[] = []\n\t\tfor (const unit of units) if (!held.has(unit) && view.mine.has(unit) && !given.includes(unit)) given.push(unit)\n\t\tif (!given.length) return given\n\t\thold.units = hold.units.filter((unit) => view.mine.has(unit))\n\t\thold.units.push(...given)\n\t\thold.units.sort((a, b) => view.indexOf(view.byId(a)!) - view.indexOf(view.byId(b)!))\n\t\treturn given\n\t}\n\n\t/**\n\t * Lets go of some of what a goal, a rule or a module holds: they go back to the pool. One left with none is released,\n\t * told why (`done` when left out). Those let go of, by id\n\t */\n\tdrop(id: string, units: Iterable<number>, why: StopReason = 'done'): number[] {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return []\n\t\tconst gone = new Set(units)\n\t\tconst dropped = hold.units.filter((unit) => gone.has(unit))\n\t\tif (!dropped.length) return dropped\n\t\thold.units = hold.units.filter((unit) => !gone.has(unit))\n\t\tif (!hold.units.length) this.release(id, why)\n\t\treturn dropped\n\t}\n\n\t/** What rules and modules hold (`take` with `by`), by their id: not goals' */\n\ttaken(): Record<string, Hold> {\n\t\tconst result: Record<string, Hold> = {}\n\t\tfor (const id in this.holds) if (!this.entries.has(id)) result[id] = this.holds[id]\n\t\treturn result\n\t}\n\n\t/** Whether a unit is held by a rule or a module rather than by a goal (`take` with `by`): what nothing else is to give orders to */\n\truled(unit: number): boolean {\n\t\tfor (const id in this.holds) if (!this.entries.has(id) && this.holds[id].units.includes(unit)) return true\n\t\treturn false\n\t}\n\n\t/** Takes a goal's claim away, telling it why (`told` when left out): its units go back to the pool. Whether it held one */\n\trelease(id: string, why: StopReason = 'told'): boolean {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return false\n\t\tdelete this.holds[id]\n\t\tif (hold.money) this.ai.purse.release(id)\n\t\tconst entry = this.entries.get(id)\n\t\tif (!entry) {\n\t\t\tthis.ai.decide(`${id} lets go of ${hold.units.length === 1 ? '1 unit' : `${hold.units.length} units`}`, { kind: 'rule' })\n\t\t\treturn true\n\t\t}\n\t\tthis.ai.decide(`${id} stopped: ${stopped(why, entry.lostTo)}`, { kind: 'goal', goal: id })\n\t\tentry.def.stop?.(this.ai, why, this.claimedOf(id, hold, false))\n\t\tconst cooldown = entry.def.cooldown ?? 0\n\t\tif (cooldown > 0) this.cooldowns[id] = this.ai.tick + Math.round(cooldown * this.ai.session.tickRate)\n\t\treturn true\n\t}\n\n\t/**\n\t * The think: every goal scored (its considerations read, curved, multiplied, weighed), the goals that hold a claim\n\t * kept to it or beaten, the rest picked best first with what they claim, and each picked one run. Once a think: a\n\t * second call in the same think does nothing\n\t */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tconst { tick, view } = ai\n\t\tif (this.thoughtAt === tick) return\n\t\tthis.thoughtAt = tick\n\n\t\t// what is held and no longer mine (dead, given away) is let go of first\n\t\tfor (const id in this.holds) {\n\t\t\tconst hold = this.holds[id]\n\t\t\tconst entry = this.entries.get(id)\n\t\t\tconst alive = hold.units.filter((unit) => view.mine.has(unit))\n\t\t\tif (alive.length !== hold.units.length) hold.units = alive\n\t\t\t// what a rule holds is its own until its time is up, or nothing of it is left\n\t\t\tif (!entry) {\n\t\t\t\tif ((!hold.kept && tick >= hold.until) || !alive.length) this.release(id, 'done')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// a goal whose every unit died has nothing left to run with\n\t\t\tif (!alive.length && entry.def.claims?.units) this.release(id, 'done')\n\t\t}\n\t\tfor (const id in this.cooldowns) if (this.cooldowns[id] <= tick) delete this.cooldowns[id]\n\n\t\t// every goal scored, whether or not it can run: the report says what each was worth\n\t\tconst entries = [...this.entries.values()]\n\t\tthis.scores = {}\n\t\tthis.best = undefined\n\t\tlet bestScore = this.min\n\t\tfor (const entry of entries) {\n\t\t\tthis.score(entry)\n\t\t\tthis.scores[entry.def.id] = entry.score\n\t\t\tif (entry.score > bestScore) {\n\t\t\t\tbestScore = entry.score\n\t\t\t\tthis.best = entry.def.id\n\t\t\t}\n\t\t}\n\n\t\t// a held goal whose score fell to nothing is done; one on cooldown or under the minimum is out of the running\n\t\tfor (const entry of entries) {\n\t\t\tconst { id } = entry.def\n\t\t\tif (this.holds[id] && entry.score <= (entry.def.min ?? this.min)) this.release(id, 'done')\n\t\t}\n\n\t\t// best first; among equals, as added, so that two thinks of one picture pick alike\n\t\tconst ranked = entries.filter((entry) => entry.score > (entry.def.min ?? this.min)).sort((a, b) => b.score - a.score || a.order - b.order)\n\t\tconst pool = new Set(this.pool().ids())\n\t\tfor (let i = 0; i < ranked.length; i++) {\n\t\t\tconst entry = ranked[i]\n\t\t\tconst { def } = entry\n\t\t\tconst { id } = def\n\t\t\tif (this.cooldowns[id] !== undefined) {\n\t\t\t\tentry.why = 'cooldown'\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlet hold: Hold | undefined = this.holds[id]\n\t\t\tlet first = false\n\t\t\tif (hold) {\n\t\t\t\t// it keeps what it holds, less what the goals above it took: with nothing left of what it claimed, it is beaten\n\t\t\t\tif (!hold.units.length && def.claims?.units) {\n\t\t\t\t\tthis.release(id, entry.lost ?? 'beaten')\n\t\t\t\t\tentry.why = entry.lost === 'urgent' ? 'taken by an urgent goal' : 'beaten'\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\thold = this.claim(entry, ranked, i, pool)\n\t\t\t\tif (!hold) continue\n\t\t\t\tfirst = true\n\t\t\t}\n\t\t\tentry.picked = true\n\t\t\tconst claimed = this.claimedOf(id, hold, first)\n\t\t\tif (first) this.decided(entry, claimed)\n\t\t\tdef.run(ai, claimed)\n\t\t}\n\t}\n\n\t/**\n\t * A goal's score this think: each consideration read and curved, their product, the weight, the game's say. Once a\n\t * consideration answers 0 the goal is vetoed, and the ones after it are not asked: put the cheap questions first\n\t */\n\tprivate score(entry: Entry): void {\n\t\tconst { ai } = this\n\t\tconst { def } = entry\n\t\tlet product = 1\n\t\tentry.considerations = []\n\t\tfor (const consideration of def.considerations) {\n\t\t\tif (product === 0) {\n\t\t\t\tentry.considerations.push({ name: consideration.name, value: 0, curved: 0, asked: false })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst value = finite(consideration.read(ai))\n\t\t\tconst curved = positive(consideration.curve(value))\n\t\t\tentry.considerations.push({ name: consideration.name, value, curved })\n\t\t\tproduct *= curved\n\t\t}\n\t\t// its weight, and what the profile says it weighs (a personality's leanings: `{ attack: 1.3 }`)\n\t\t// a weight of the game's or the profile's that is no number scores nothing, as a consideration's does\n\t\tlet score = positive(product * (def.weight ?? 1) * (ai.profile.weights?.[def.id] ?? 1))\n\t\tentry.score = score\n\t\t// whether it may break a commitment: asked only of a goal in the running\n\t\tentry.urgent = score > (def.min ?? this.min) && (typeof def.urgent === 'function' ? def.urgent(ai) : !!def.urgent)\n\t\tentry.picked = false\n\t\tentry.why = undefined\n\t\tentry.lost = undefined\n\t\tentry.lostTo = undefined\n\t}\n\n\t/** Writes down a goal picked anew, for the decision log: its score, what it holds, its considerations */\n\tprivate decided(entry: Entry, claimed: Claimed): void {\n\t\tconst { def } = entry\n\t\tconst units = def.claims?.units ? ` (${claimed.units.length === 1 ? '1 unit' : `${claimed.units.length} units`})` : ''\n\t\tconst reasons = considerationsLine(entry)\n\t\tthis.ai.decide(`${def.id} picked at ${entry.score.toFixed(2)}${units}${entry.urgent ? ', urgent' : ''}${reasons && `: ${reasons}`}`, {\n\t\t\tkind: 'goal',\n\t\t\tgoal: def.id\n\t\t})\n\t}\n\n\t/**\n\t * What a goal picked anew takes: the units it chooses from the pool and from the holds of goals ranked below it\n\t * that it may take from (by the margin within their commitment, by any lead after it, and by any lead at all for an\n\t * urgent goal), and the money it names. Nothing where it asked for units and chose none\n\t */\n\tprivate claim(entry: Entry, ranked: Entry[], at: number, pool: Set<number>): Hold | undefined {\n\t\tconst { ai } = this\n\t\tconst { def } = entry\n\t\tconst { view, tick } = ai\n\t\tconst units: number[] = []\n\t\tif (def.claims?.units) {\n\t\t\t// what the goals run before it gave themselves since the pool was read (a squad reinforced) is no longer the pool's\n\t\t\tconst held = this.heldIds()\n\t\t\tfor (const unit of pool) if (held.has(unit)) pool.delete(unit)\n\t\t\t// whose units it may take, by the rules of commitment\n\t\t\tconst preys: Entry[] = []\n\t\t\tfor (let j = at + 1; j < ranked.length; j++) {\n\t\t\t\tconst other = ranked[j]\n\t\t\t\tconst hold = this.holds[other.def.id]\n\t\t\t\tif (!hold?.units.length) continue\n\t\t\t\tconst committed = tick < hold.until\n\t\t\t\tconst lead = committed && !entry.urgent ? (other.def.margin ?? this.margin) : 0\n\t\t\t\tif (entry.score > other.score + lead) preys.push(other)\n\t\t\t}\n\t\t\tconst takeable = new Set(pool)\n\t\t\tfor (const prey of preys) for (const unit of this.holds[prey.def.id].units) takeable.add(unit)\n\t\t\tconst available = view.mine.where((unit) => takeable.has(unit.id))\n\t\t\tfor (const chosen of def.claims.units(ai, available)) if (takeable.has(chosen.id) && !units.includes(chosen.id)) units.push(chosen.id)\n\t\t\tif (!units.length) {\n\t\t\t\tentry.why = 'nothing to claim'\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tunits.sort((a, b) => view.indexOf(view.byId(a)!) - view.indexOf(view.byId(b)!))\n\t\t\tfor (const unit of units) {\n\t\t\t\tif (pool.delete(unit)) continue\n\t\t\t\tfor (const prey of preys) {\n\t\t\t\t\tconst hold = this.holds[prey.def.id]\n\t\t\t\t\tconst index = hold.units.indexOf(unit)\n\t\t\t\t\tif (index < 0) continue\n\t\t\t\t\thold.units.splice(index, 1)\n\t\t\t\t\tprey.lost = entry.urgent ? 'urgent' : 'beaten'\n\t\t\t\t\tprey.lostTo = def.id\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst money = this.moneyOf(def)\n\t\t// held against the purse from now: nothing of the think spends what the goal holds\n\t\tif (money) ai.purse.reserve(def.id, money)\n\t\tconst commitment = def.commitment ?? this.commitment\n\t\tconst hold: Hold = {\n\t\t\tunits,\n\t\t\t...(money && { money }),\n\t\t\tsince: tick,\n\t\t\tuntil: tick + Math.round(commitment * ai.session.tickRate),\n\t\t\tscore: entry.score\n\t\t}\n\t\tthis.holds[def.id] = hold\n\t\treturn hold\n\t}\n\n\t/** The money a goal names, as a cost: a number is in the game's money */\n\tprivate moneyOf(def: GoalDef): Cost | undefined {\n\t\tconst { ai } = this\n\t\tconst asked = typeof def.claims?.money === 'function' ? def.claims.money(ai) : def.claims?.money\n\t\tif (asked === undefined) return undefined\n\t\tif (typeof asked === 'number') {\n\t\t\tif (!(asked > 0)) return undefined\n\t\t\tconst currency = ai.registry.currency ?? ai.registry.resources[0]?.id\n\t\t\treturn currency === undefined ? undefined : { [currency]: asked }\n\t\t}\n\t\treturn Object.keys(asked).length ? { ...asked } : undefined\n\t}\n\n\t/** What a goal holds, as it is handed to it */\n\tprivate claimedOf(goal: string, hold: Hold, first: boolean): Claimed {\n\t\tconst { ai } = this\n\t\tconst units = new UnitSet(\n\t\t\tai.view,\n\t\t\thold.units.map((id) => ai.view.byId(id)).filter((unit): unit is EntityState => !!unit)\n\t\t)\n\t\t// the goal's squad of that name, kept: called again (each think) it is the same squad, made up with what is given\n\t\tconst squad = (name: string, of: Iterable<EntityState | number>, options: SquadOptions = {}) => {\n\t\t\tconst kept = ai.squads.named(name)\n\t\t\tif (!kept || kept.owner !== goal) return ai.squads.make(name, of, { ...options, owner: goal })\n\t\t\tkept.data.options = { ...ai.squads.defaults, ...options }\n\t\t\treturn kept.add(of)\n\t\t}\n\t\treturn { units, ...(hold.money && { money: hold.money }), began: hold.since, first, squad }\n\t}\n\n\tprivate heldIds(): Set<number> {\n\t\tconst held = new Set<number>()\n\t\tfor (const id in this.holds) for (const unit of this.holds[id].units) held.add(unit)\n\t\treturn held\n\t}\n\n\t/** Every goal as the picker last saw it: score, considerations, what it holds, why it did not run */\n\treport(): GoalReport[] {\n\t\tconst { view } = this.ai\n\t\treturn [...this.entries.values()].map((entry) => {\n\t\t\tconst { def } = entry\n\t\t\tconst hold = this.holds[def.id]\n\t\t\treturn {\n\t\t\t\tid: def.id,\n\t\t\t\tscope: def.scope ?? 'army',\n\t\t\t\tscore: entry.score,\n\t\t\t\tconsiderations: entry.considerations,\n\t\t\t\tpicked: entry.picked,\n\t\t\t\turgent: entry.urgent,\n\t\t\t\t...(hold && {\n\t\t\t\t\theld: {\n\t\t\t\t\t\tunits: hold.units.length,\n\t\t\t\t\t\tids: [...hold.units],\n\t\t\t\t\t\tstrength: view.strength.sum(hold.units.map((id) => view.byId(id)).filter((unit): unit is EntityState => !!unit)),\n\t\t\t\t\t\t...(hold.money && { money: { ...hold.money } }),\n\t\t\t\t\t\tsince: hold.since,\n\t\t\t\t\t\tuntil: hold.until\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\t...(entry.why && { why: entry.why })\n\t\t\t}\n\t\t})\n\t}\n\n\t/** What is held and on cooldown, for a save */\n\t/** Whether it has anything to remember now: one that does not is left out of a save */\n\tremembers(): boolean {\n\t\treturn this.list().length > 0 || Object.keys(this.all()).length > 0\n\t}\n\n\tsave(): GoalsMemory {\n\t\tconst holds: Record<string, Hold> = {}\n\t\tfor (const id in this.holds) {\n\t\t\tconst hold = this.holds[id]\n\t\t\tholds[id] = { ...hold, units: [...hold.units], ...(hold.money && { money: { ...hold.money } }) }\n\t\t}\n\t\treturn { v: 1, holds, cooldowns: { ...this.cooldowns } }\n\t}\n\n\t/** Takes back what `save` gave: whether it was read */\n\trestore(memory: unknown): boolean {\n\t\tconst given = memory as GoalsMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.holds = {}\n\t\tfor (const id in given.holds ?? {}) {\n\t\t\tconst hold = given.holds[id]\n\t\t\tthis.holds[id] = { ...hold, units: [...(hold.units ?? [])], ...(hold.money && { money: { ...hold.money } }) }\n\t\t}\n\t\tthis.cooldowns = { ...(given.cooldowns ?? {}) }\n\t\treturn true\n\t}\n\n\t/** What the debug tools show: the report, the best, and the picker's numbers */\n\tinspect(): Record<string, unknown> {\n\t\treturn { goals: this.report(), ...(this.best !== undefined && { goal: this.best }) }\n\t}\n}\n\n/** Why a goal stopped, in words, for the decision log */\nfunction stopped(why: StopReason, by: string | undefined): string {\n\tswitch (why) {\n\t\tcase 'beaten':\n\t\t\treturn by ? `beaten by ${by}` : 'beaten'\n\t\tcase 'urgent':\n\t\t\treturn by ? `its units taken by ${by}, urgent` : 'its units taken by an urgent goal'\n\t\tcase 'done':\n\t\t\treturn 'done, or nothing left to run with'\n\t\tcase 'told':\n\t\t\treturn 'its units taken by a rule or a module'\n\t\tcase 'removed':\n\t\t\treturn 'taken out of the brain'\n\t}\n}\n\n/** A number as it is, and 0 for what is none (NaN, infinite): the picker never picks on nonsense */\nconst finite = (x: number) => (Number.isFinite(x) ? x : 0)\n/** A curved value or a score: finite, and nothing under 0 */\nconst positive = (x: number) => (Number.isFinite(x) && x > 0 ? x : 0)\n\n/**\n * The goals module: runs the brain's picker (`ai.goals.think`) in its place among the brain's modules, after what\n * reads the game and before what acts on orders. With goals of its own to add to the brain's\n *\n * @beta\n */\nexport const goals = (defs: GoalDef[] = []): AiModuleDef =>\n\tdefineModule('goals', (ai: Brain): AiModule => {\n\t\tai.goals.add(...defs)\n\t\treturn {\n\t\t\tid: 'goals',\n\t\t\tphase: 'act',\n\t\t\tthink: () => ai.goals.think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tgoals?: GoalsMemory\n\t}\n}\n","import type { ResourceKind } from '#engine/defs'\nimport type { AiArea } from './area'\nimport type { PlayerId } from '#engine/entity'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { CampInfo, EntityState, FogState, MineInfo } from '#engine/session/protocol'\nimport type { AiView } from './view'\nimport { heroOfState } from '#engine/hero'\nimport { BASE_REACH, CELL } from './reach'\n\n/*\n * Knowledge: what a computer player remembers, with when (AI plan, A3). The view (`view.ts`) is one think's picture\n * and is thrown away with it; a person playing remembers more than what is on the screen: \"their army was at the river\n * twenty seconds ago\", \"they have a second hall by the far mine\", \"they have flyers now\", \"I lost three peasants at the\n * east mine\". This file is that memory. It is updated once a think, after the view is made, from the view and the\n * view of the think before (which says what the dead were), and it is plain data, kept in the brain's memory, so a\n * save keeps it and a load gives it back.\n *\n * What it keeps, and from what:\n * - the enemy's **structures**: the engine remembers them already for the team (`teamMemory`: a building seen and out\n * of sight is still in the snapshot, `visible: false`, until someone sees its spot empty). Knowledge adds when each\n * was first and last seen, and keeps one that is gone a while, so that a base that \"looks gone\" can be told from one\n * never seen. Bases are the structures clustered, as the view clusters one's own;\n * - the enemy's **army**: a unit out of sight is not in the snapshot at all, so where an army was is only ever a memory.\n * Each think the enemy fighters in sight are grouped by nearness into sightings (where, when, how many, of what); a\n * newer sighting near an older one replaces it (the army moved), and a sighting is dropped when its place is in\n * sight again with no one there, so the army is never chased where it no longer is;\n * - their **workers** and **heroes** as last seen, the unit **types** seen (with the most seen at once) and the **tech**\n * that implies (a knight means what knights require);\n * - the **map**: when each coarse cell was last in sight (`lastLooked`), from the seat's fog;\n * - one's **own** losses (what died, where, to what), the attacks sent, and what was gathered over time (`income`);\n * - what was **heard**: pings, damage to one's own and allies' units, deaths seen.\n *\n * Everything is bounded (at most so many of each kind, the oldest dropped) and ages (`KnowledgeOptions`,\n * `forget`). Nothing here takes the world: it reads the view, cut to the seat's fog, and the seat's fog itself.\n */\n\n/**\n * How a brain's knowledge remembers (`BrainDef.knowledge`): how long, how much, what counts as the army. Every field\n * has its default; numbers are seconds where they say so\n *\n * @beta\n */\nexport interface KnowledgeOptions {\n\t/** Seconds a sighting of the enemy's army, or of a worker, is kept: 180 */\n\tarmyFor?: number\n\t/** Seconds a structure seen gone is still remembered as gone, and an event, a loss or an attack sent is kept: 300 */\n\tkeepFor?: number\n\t/** How near two groups of enemy fighters are to be one sighting, and a newer sighting to replace an older: 16 */\n\tmergeRadius?: number\n\t/** Seconds between samples of what was gathered, for `own.income`: 5 */\n\thistoryEvery?: number\n\t/** At most so many of each: sightings 12, workers 40, heroes 16, structures 400, losses 64, events 48, attacks 20, samples 36 */\n\tlimits?: Partial<Record<'sightings' | 'workers' | 'heroes' | 'structures' | 'lost' | 'events' | 'attacks' | 'history', number>>\n\t/** What of the enemy's units in sight counts as their army: their soldiers and heroes (`UnitSet.fighters`) when left out */\n\tarmy?: (entity: EntityState, view: AiView) => boolean\n}\n\n/**\n * An enemy structure as remembered: where, what, whose, and when it was first and last in sight (ticks). `gone` is the\n * tick it was known to be gone: seen destroyed, or its spot seen empty\n *\n * @beta\n */\nexport interface StructureSeen {\n\tid: number\n\ttype: string\n\towner: PlayerId\n\tat: Vec2\n\tfirst: number\n\tlast: number\n\tgone?: number\n}\n\n/**\n * A group of the enemy's fighters, seen together (`enemy.armySeen`): where its middle was, the tick, how many, of\n * what types, with how much health and strength, whose (the owner of most of them)\n *\n * @beta\n */\nexport interface ArmySighting {\n\tat: Vec2\n\ttick: number\n\towner: PlayerId\n\tcount: number\n\t/** Their health together, as seen */\n\thealth: number\n\t/** Their strength together, as seen (`Strength.of`, with the health each had left) */\n\tstrength: number\n\ttypes: Record<string, number>\n\theroes: number\n}\n\n/**\n * An enemy unit as last seen (`enemy.workersSeen`, `enemy.heroesSeen`): `level` for a hero, `died` the tick it was\n * seen to die (a hero may come back)\n *\n * @beta\n */\nexport interface UnitSeen {\n\tid: number\n\ttype: string\n\towner: PlayerId\n\tat: Vec2\n\ttick: number\n\tlevel?: number\n\tdied?: number\n}\n\n/**\n * A unit type of the enemy's as seen (`enemy.typesSeen`): first and last tick, and the most seen at once\n *\n * @beta\n */\nexport interface TypeSeen {\n\tfirst: number\n\tlast: number\n\tmost: number\n}\n\n/**\n * An enemy's base, as its structures remembered cluster (`enemy.bases`): around what takes deposits (a hall), or\n * around any structure where none does. `gone` when every structure of it is known gone; `expansion` for every base of\n * an owner but the first seen of theirs\n *\n * @beta\n */\nexport interface EnemyBase {\n\towner: PlayerId\n\tat: Vec2\n\t/** When the first of it was seen */\n\tfirst: number\n\t/** When any of it was last in sight */\n\tlast: number\n\tstructures: StructureSeen[]\n\t/** Whether it is around what takes deposits: a hall, not a lone tower */\n\thall: boolean\n\tgone: boolean\n\texpansion: boolean\n}\n\n/**\n * Something of one's own that died (`own.lost`): what, where, when, to what type of killer where it was seen\n *\n * @beta\n */\nexport interface Loss {\n\tid: number\n\ttype: string\n\tat: Vec2\n\ttick: number\n\tby?: string\n}\n\n/**\n * An attack a module sent (`own.attackSent`): when, where to, with how many\n *\n * @beta\n */\nexport interface AttackSent {\n\ttick: number\n\tat: Vec2\n\tcount: number\n}\n\n/**\n * A ping heard (`events.pings`): who marked where, of what kind\n *\n * @beta\n */\nexport interface PingHeard {\n\ttick: number\n\tplayer: PlayerId\n\tat: Vec2\n\tkind: string\n}\n\n/**\n * Damage seen done to one's own or an ally's entity in a think (`events.damage`): added up over the think, one line\n * an entity\n *\n * @beta\n */\nexport interface DamageSeen {\n\ttick: number\n\tid: number\n\ttype: string\n\towner: PlayerId\n\tat: Vec2\n\tamount: number\n\tby?: string\n}\n\n/**\n * A death seen (`events.deaths`): of anyone known to the seat in the think before\n *\n * @beta\n */\nexport interface DeathSeen {\n\ttick: number\n\tid: number\n\ttype: string\n\towner: PlayerId\n\tat: Vec2\n\tby?: string\n}\n\n/**\n * What a brain's knowledge is, as plain data: what a save keeps (`Brain.save`, under `knowledge`), what a game's module\n * may read or add to through `Knowledge`\n *\n * @beta\n */\nexport interface KnowledgeMemory {\n\tv: 1\n\t/** The tick it was last brought up to date */\n\ttick: number\n\tstructures: StructureSeen[]\n\t/** Newest first */\n\tarmy: ArmySighting[]\n\tworkers: UnitSeen[]\n\theroes: UnitSeen[]\n\ttypes: Record<string, TypeSeen>\n\t/** The tick each cell of the map was last in sight, row by row (-1: never); `cols` cells a row */\n\tlooked: { cols: number; rows: number; ticks: number[] }\n\tlost: Loss[]\n\tattacks: AttackSent[]\n\t/** What was gathered of each resource since the game began, as far as rises in what the player has tell */\n\tgathered: Record<ResourceKind, number>\n\t/** What the player had at the last update, to see the next rise against */\n\thad?: Record<ResourceKind, number>\n\t/** Samples of `gathered`, oldest first */\n\thistory: { tick: number; gathered: Record<ResourceKind, number> }[]\n\tpings: PingHeard[]\n\tdamage: DamageSeen[]\n\tdeaths: DeathSeen[]\n}\n\nconst LIMITS = { sightings: 12, workers: 40, heroes: 16, structures: 400, lost: 64, events: 48, attacks: 20, history: 36 }\n\nconst empty = (): KnowledgeMemory => ({\n\tv: 1,\n\ttick: 0,\n\tstructures: [],\n\tarmy: [],\n\tworkers: [],\n\theroes: [],\n\ttypes: {},\n\tlooked: { cols: 0, rows: 0, ticks: [] },\n\tlost: [],\n\tattacks: [],\n\tgathered: {},\n\thistory: [],\n\tpings: [],\n\tdamage: [],\n\tdeaths: []\n})\n\nconst at = (point: Vec2): Vec2 => ({ x: point.x, z: point.z })\n\n/** Keeps the last `limit` of a list (the newest, for lists kept oldest first) */\nfunction trimOldest<T>(list: T[], limit: number): void {\n\tif (list.length > limit) list.splice(0, list.length - limit)\n}\n\n/**\n * What a computer player remembers of the enemy, the map and itself, with when (`Brain.knowledge`). Brought up to date\n * once a think from the view; asked through its parts: `enemy` (structures, bases, army seen, workers, heroes, tech),\n * `map` (when a place was last looked at), `own` (losses, attacks sent, income), `events` (pings, damage, deaths heard).\n * Plain data underneath (`data`), saved with the brain\n *\n * @beta\n */\nexport class Knowledge implements AiArea {\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'knowledge'\n\t/** What the log says where a save's memory of it is of a shape it does not read */\n\treadonly afresh = 'the save remembers what the computer player knew in a shape this brain does not read: it starts afresh'\n\n\t/** What it remembers, as plain data. Replaced as a whole by `restore` */\n\tdata: KnowledgeMemory = empty()\n\t/** The enemy: structures, bases, army, workers, heroes, tech */\n\treadonly enemy: EnemyKnowledge\n\t/** The map: when each place was last in sight */\n\treadonly map: MapKnowledge\n\t/** One's own: losses, attacks sent, income */\n\treadonly own: OwnKnowledge\n\t/** What was heard: pings, damage to friends, deaths */\n\treadonly events: HeardEvents\n\t/** @internal The view of the last update: for what is asked of the map now */\n\tview: AiView | undefined\n\t/** @internal The seat's fog as of the last update */\n\tfog: FogState | undefined\n\t/** Where in the fog each cell of the map is read: found again when the fog or the map is of another size */\n\tprivate sample: { fog: number; cells: Int32Array } | undefined\n\treadonly options: Required<Omit<KnowledgeOptions, 'army' | 'limits'>> & Pick<KnowledgeOptions, 'army'> & { limits: typeof LIMITS }\n\n\tconstructor(\n\t\toptions: KnowledgeOptions = {},\n\t\t/** The map's size, where known before the first update: what is looked at can be told before it (an older save) */\n\t\tsize?: { width: number; depth: number },\n\t\t/** Whether a save keeps it: not for a brain that remembers nothing between thinks (`BrainDef.knowledge: false`) */\n\t\tprivate readonly kept = true\n\t) {\n\t\tthis.options = {\n\t\t\tarmyFor: options.armyFor ?? 180,\n\t\t\tkeepFor: options.keepFor ?? 300,\n\t\t\tmergeRadius: options.mergeRadius ?? 16,\n\t\t\thistoryEvery: options.historyEvery ?? 5,\n\t\t\tarmy: options.army,\n\t\t\tlimits: { ...LIMITS, ...options.limits }\n\t\t}\n\t\tthis.enemy = new EnemyKnowledge(this)\n\t\tthis.map = new MapKnowledge(this)\n\t\tthis.own = new OwnKnowledge(this)\n\t\tthis.events = new HeardEvents(this)\n\t\tif (size) this.size(size.width, size.depth)\n\t}\n\n\t/** Makes what is remembered of the map the size of a map of this many units: forgotten where it was another size */\n\tprivate size(width: number, depth: number): void {\n\t\tconst cols = Math.max(1, Math.ceil(width / CELL))\n\t\tconst rows = Math.max(1, Math.ceil(depth / CELL))\n\t\tconst looked = this.data.looked\n\t\tif (looked.cols !== cols || looked.rows !== rows) this.data.looked = { cols, rows, ticks: new Array(cols * rows).fill(-1) }\n\t}\n\n\t/** The tick it was last brought up to date */\n\tget tick(): number {\n\t\treturn this.data.tick\n\t}\n\n\t/** @internal Seconds into the game of a tick, at the seat's rate */\n\tseconds(ticks: number): number {\n\t\treturn ticks / (this.view?.session.tickRate ?? 1)\n\t}\n\n\t/** @internal The tick so many seconds before the last update */\n\tsince(seconds: number | undefined): number {\n\t\tif (seconds === undefined) return -Infinity\n\t\treturn this.data.tick - seconds * (this.view?.session.tickRate ?? 1)\n\t}\n\n\t/**\n\t * Brings it up to date from a think's view. `before` is the view of the think before: what the dead of this think\n\t * were (a death says only an id). What the brain calls as each think begins, after the view is made\n\t */\n\tupdate(view: AiView, before?: AiView): void {\n\t\tconst { data, options } = this\n\t\tconst tick = view.tick\n\t\tconst rate = view.session.tickRate\n\t\tthis.view = view\n\t\tthis.enemy.reset()\n\t\tdata.tick = tick\n\t\tconst sees = this.lookAround(view)\n\n\t\t// the enemy's structures: those the snapshot has, in sight or remembered by the team; one it no longer has is known gone\n\t\tconst known = new Set<number>()\n\t\tconst byId = new Map(data.structures.map((each) => [each.id, each]))\n\t\tfor (const building of view.enemies.known().buildings()) {\n\t\t\tknown.add(building.id)\n\t\t\tlet seen = byId.get(building.id)\n\t\t\tif (!seen) {\n\t\t\t\tseen = { id: building.id, type: building.type, owner: building.owner, at: at(building), first: tick, last: tick }\n\t\t\t\tdata.structures.push(seen)\n\t\t\t\tbyId.set(building.id, seen)\n\t\t\t}\n\t\t\t// a building can turn into another (a hall into a keep), and is seen where it stands\n\t\t\tseen.type = building.type\n\t\t\tseen.at = at(building)\n\t\t\tif (building.visible) seen.last = tick\n\t\t\tdelete seen.gone\n\t\t}\n\t\tconst goneFor = options.keepFor * rate\n\t\tdata.structures = data.structures.filter((each) => {\n\t\t\tif (!known.has(each.id) && each.gone === undefined) each.gone = tick\n\t\t\treturn each.gone === undefined || tick - each.gone <= goneFor\n\t\t})\n\t\ttrimOldest(data.structures, options.limits.structures)\n\n\t\t// the types seen, with the most at once: what is in sight now\n\t\tconst now: Record<string, number> = {}\n\t\tfor (const entity of view.enemies) now[entity.type] = (now[entity.type] ?? 0) + 1\n\t\tfor (const [type, count] of Object.entries(now)) {\n\t\t\tconst seen = (data.types[type] ??= { first: tick, last: tick, most: 0 })\n\t\t\tseen.last = tick\n\t\t\tseen.most = Math.max(seen.most, count)\n\t\t}\n\n\t\tthis.seeArmy(view, sees)\n\t\tthis.seeUnits(view, sees)\n\t\tthis.hear(view, before)\n\t\tthis.count(view)\n\t}\n\n\t/** Brings what was last looked at up to date from the seat's fog: what is in sight now, by cell (1 for in sight) */\n\t/**\n\t * Reads the think's picture through this view without remembering anything of it: for a think a game loaded from a\n\t * save goes on with (`BrainMemory.thinking`), whose picture the saved game remembered already, so that what is restored\n\t * is as it was after that; only what is asked of the map now needs the view it is asked through\n\t */\n\tresume(view: AiView): void {\n\t\tthis.view = view\n\t\tthis.fog = view.session.fog()\n\t\tthis.size(view.session.terrain.width, view.session.terrain.depth)\n\t\tthis.enemy.reset()\n\t}\n\n\tprivate lookAround(view: AiView): Uint8Array {\n\t\tconst { width, depth } = view.session.terrain\n\t\t// a map of another size than what was remembered (a save of another map): what was looked at is forgotten\n\t\tthis.size(width, depth)\n\t\tconst { cols, rows } = this.data.looked\n\t\tconst ticks = this.data.looked.ticks\n\t\tconst fog = view.session.fog()\n\t\tthis.fog = fog\n\t\tconst sees = new Uint8Array(cols * rows)\n\t\tconst tick = view.tick\n\t\tif (fog.revealed || !fog.visible.length) {\n\t\t\tsees.fill(1)\n\t\t\tticks.fill(tick)\n\t\t\treturn sees\n\t\t}\n\t\t// where in the fog each cell's middle falls, worked out once for the map and the fog's size\n\t\tlet sample = this.sample\n\t\tif (!sample || sample.fog !== fog.width * 65536 + fog.depth || sample.cells.length !== cols * rows) {\n\t\t\tconst cells = new Int32Array(cols * rows)\n\t\t\tfor (let r = 0; r < rows; r++) {\n\t\t\t\tconst fz = Math.min(fog.depth - 1, Math.floor((((r + 0.5) * CELL) / depth) * fog.depth))\n\t\t\t\tfor (let c = 0; c < cols; c++)\n\t\t\t\t\tcells[r * cols + c] = fz * fog.width + Math.min(fog.width - 1, Math.floor((((c + 0.5) * CELL) / width) * fog.width))\n\t\t\t}\n\t\t\tsample = this.sample = { fog: fog.width * 65536 + fog.depth, cells }\n\t\t}\n\t\tconst { visible } = fog\n\t\tconst { cells } = sample\n\t\tfor (let i = 0; i < cells.length; i++) {\n\t\t\tif (!visible[cells[i]]) continue\n\t\t\tsees[i] = 1\n\t\t\tticks[i] = tick\n\t\t}\n\t\treturn sees\n\t}\n\n\t/** @internal The cell of a point, in what is remembered of the map: -1 off it */\n\tcell(point: Vec2): number {\n\t\tconst { cols, rows } = this.data.looked\n\t\tconst c = Math.floor(point.x / CELL)\n\t\tconst r = Math.floor(point.z / CELL)\n\t\tif (c < 0 || r < 0 || c >= cols || r >= rows) return -1\n\t\treturn r * cols + c\n\t}\n\n\t/**\n\t * The enemy's fighters in sight, grouped by nearness into sightings. A newer sighting replaces the older ones near\n\t * it (the army moved); an older one whose place is in sight with no sighting near is dropped (no one is there now)\n\t */\n\tprivate seeArmy(view: AiView, sees: Uint8Array): void {\n\t\tconst { data, options } = this\n\t\tconst tick = view.tick\n\t\tconst merge = options.mergeRadius * options.mergeRadius\n\t\tconst fighters = options.army ? view.enemies.units().where((entity) => options.army!(entity, view)) : view.enemies.units().fighters()\n\t\t// grouped greedily in the snapshot's order: each joins the first group whose first member is near, or starts one\n\t\tconst groups: EntityState[][] = []\n\t\tfor (const unit of fighters) {\n\t\t\tif (unit.hp <= 0) continue\n\t\t\tconst group = groups.find((each) => distSq(each[0], unit) <= merge)\n\t\t\tif (group) group.push(unit)\n\t\t\telse groups.push([unit])\n\t\t}\n\t\tconst fresh: ArmySighting[] = groups.map((group) => {\n\t\t\tlet x = 0\n\t\t\tlet z = 0\n\t\t\tlet health = 0\n\t\t\tlet strength = 0\n\t\t\tlet heroes = 0\n\t\t\tconst types: Record<string, number> = {}\n\t\t\tconst owners = new Map<PlayerId, number>()\n\t\t\tfor (const unit of group) {\n\t\t\t\tx += unit.x\n\t\t\t\tz += unit.z\n\t\t\t\thealth += unit.hp\n\t\t\t\tstrength += view.strength.of(unit)\n\t\t\t\tif (view.hasRole(unit, 'hero')) heroes++\n\t\t\t\ttypes[unit.type] = (types[unit.type] ?? 0) + 1\n\t\t\t\towners.set(unit.owner, (owners.get(unit.owner) ?? 0) + 1)\n\t\t\t}\n\t\t\tlet owner = group[0].owner\n\t\t\tfor (const [player, count] of owners) if (count > owners.get(owner)!) owner = player\n\t\t\treturn { at: { x: x / group.length, z: z / group.length }, tick, owner, count: group.length, health, strength, types, heroes }\n\t\t})\n\t\tconst oldest = tick - options.armyFor * view.session.tickRate\n\t\tconst kept = data.army.filter((old) => {\n\t\t\tif (old.tick < oldest) return false\n\t\t\tif (fresh.some((each) => distSq(each.at, old.at) <= merge)) return false\n\t\t\t// looked at again, and no one there\n\t\t\tconst cell = this.cell(old.at)\n\t\t\treturn cell < 0 || !sees[cell]\n\t\t})\n\t\tdata.army = [...fresh, ...kept].slice(0, options.limits.sightings)\n\t}\n\n\t/**\n\t * The enemy's workers and heroes in sight, by id, where they were. A worker whose place is in sight and who is not\n\t * there is forgotten; a hero is kept where last seen (there are few, and where they went matters)\n\t */\n\tprivate seeUnits(view: AiView, sees: Uint8Array): void {\n\t\tconst { data, options } = this\n\t\tconst tick = view.tick\n\t\tconst workers = new Map(data.workers.map((each) => [each.id, each]))\n\t\tfor (const unit of view.enemies.units()) {\n\t\t\tconst worker = view.hasRole(unit, 'worker') || (view.hasRole(unit, 'gatherer') && !view.hasRole(unit, 'soldier'))\n\t\t\tif (!worker) continue\n\t\t\tconst seen = workers.get(unit.id)\n\t\t\tif (seen) {\n\t\t\t\tseen.at = at(unit)\n\t\t\t\tseen.tick = tick\n\t\t\t} else workers.set(unit.id, { id: unit.id, type: unit.type, owner: unit.owner, at: at(unit), tick })\n\t\t}\n\t\tconst oldest = tick - options.armyFor * view.session.tickRate\n\t\tdata.workers = [...workers.values()].filter((each) => {\n\t\t\tif (each.tick === tick) return true\n\t\t\tconst cell = this.cell(each.at)\n\t\t\treturn each.tick >= oldest && (cell < 0 || !sees[cell])\n\t\t})\n\t\tdata.workers.sort((a, b) => b.tick - a.tick || a.id - b.id)\n\t\tdata.workers.length = Math.min(data.workers.length, options.limits.workers)\n\n\t\tconst heroes = new Map(data.heroes.map((each) => [each.id, each]))\n\t\tfor (const hero of view.enemies.heroes()) {\n\t\t\tconst seen = heroes.get(hero.id) ?? { id: hero.id, type: hero.type, owner: hero.owner, at: at(hero), tick }\n\t\t\tseen.type = hero.type\n\t\t\tseen.at = at(hero)\n\t\t\tseen.tick = tick\n\t\t\tconst level = heroOfState(hero)?.level\n\t\t\tif (level !== undefined) seen.level = level\n\t\t\tdelete seen.died\n\t\t\theroes.set(hero.id, seen)\n\t\t}\n\t\tdata.heroes = [...heroes.values()]\n\t\tdata.heroes.sort((a, b) => b.tick - a.tick || a.id - b.id)\n\t\tdata.heroes.length = Math.min(data.heroes.length, options.limits.heroes)\n\t}\n\n\t/** What the think's events say: deaths (one's own among them, as losses), pings, damage to one's own and allies' */\n\tprivate hear(view: AiView, before: AiView | undefined): void {\n\t\tconst { data, options } = this\n\t\tconst tick = view.tick\n\t\tconst limit = options.limits.events\n\t\tfor (const death of view.events.of('death')) {\n\t\t\t// a death says only an id: what it was is in the picture before, where the seat knew of it\n\t\t\tconst was = before?.byId(death.id) ?? view.byId(death.id)\n\t\t\tif (!was) continue\n\t\t\tconst by = death.killerType\n\t\t\tconst seen: DeathSeen = { tick, id: was.id, type: was.type, owner: was.owner, at: at(was), ...(by && { by }) }\n\t\t\tdata.deaths.push(seen)\n\t\t\tif (was.owner === view.playerId) data.lost.push({ id: was.id, type: was.type, at: seen.at, tick, ...(by && { by }) })\n\t\t\tconst worker = data.workers.findIndex((each) => each.id === was.id)\n\t\t\tif (worker >= 0) data.workers.splice(worker, 1)\n\t\t\tconst hero = data.heroes.find((each) => each.id === was.id)\n\t\t\tif (hero) hero.died = tick\n\t\t}\n\t\ttrimOldest(data.deaths, limit)\n\t\ttrimOldest(data.lost, options.limits.lost)\n\n\t\tfor (const ping of view.events.of('ping')) data.pings.push({ tick, player: ping.player, at: { x: ping.x, z: ping.z }, kind: ping.kind })\n\t\ttrimOldest(data.pings, limit)\n\n\t\t// damage comes many a think in a fight: added up to one line an entity\n\t\tconst damage = view.events.of('damage')\n\t\tif (damage.length) {\n\t\t\tconst byEntity = new Map<number, DamageSeen>()\n\t\t\tfor (const hit of damage) {\n\t\t\t\tconst target = view.byId(hit.id) ?? before?.byId(hit.id)\n\t\t\t\tif (!target || !view.isFriendly(target)) continue\n\t\t\t\tconst line = byEntity.get(hit.id)\n\t\t\t\tif (line) line.amount += hit.amount\n\t\t\t\telse\n\t\t\t\t\tbyEntity.set(hit.id, {\n\t\t\t\t\t\ttick,\n\t\t\t\t\t\tid: hit.id,\n\t\t\t\t\t\ttype: target.type,\n\t\t\t\t\t\towner: target.owner,\n\t\t\t\t\t\tat: at(target),\n\t\t\t\t\t\tamount: hit.amount,\n\t\t\t\t\t\t...(hit.sourceType && { by: hit.sourceType })\n\t\t\t\t\t})\n\t\t\t}\n\t\t\tfor (const line of byEntity.values()) data.damage.push(line)\n\t\t\ttrimOldest(data.damage, limit)\n\t\t}\n\t\tthis.forgetOlder(this.since(options.keepFor), false)\n\t}\n\n\t/** What was gathered: every rise in what the player has, added up; sampled every `historyEvery` seconds */\n\tprivate count(view: AiView): void {\n\t\tconst { data, options } = this\n\t\tconst resources = view.me.resources\n\t\tif (data.had) {\n\t\t\tfor (const [kind, amount] of Object.entries(resources)) {\n\t\t\t\tconst rise = amount - (data.had[kind] ?? 0)\n\t\t\t\tif (rise > 0) data.gathered[kind] = (data.gathered[kind] ?? 0) + rise\n\t\t\t}\n\t\t}\n\t\tdata.had = { ...resources }\n\t\tconst last = data.history[data.history.length - 1]\n\t\tif (!last || view.tick - last.tick >= options.historyEvery * view.session.tickRate) {\n\t\t\tdata.history.push({ tick: view.tick, gathered: { ...data.gathered } })\n\t\t\ttrimOldest(data.history, options.limits.history)\n\t\t}\n\t}\n\n\t/** Forgets what is older than so many seconds: sightings, workers, losses, attacks, what was heard, structures long gone */\n\tforget(olderThan: number): void {\n\t\tthis.forgetOlder(this.since(olderThan), true)\n\t}\n\n\tprivate forgetOlder(oldest: number, all: boolean): void {\n\t\tconst { data } = this\n\t\tconst keep = <T extends { tick: number }>(list: T[]) => list.filter((each) => each.tick >= oldest)\n\t\tdata.lost = keep(data.lost)\n\t\tdata.attacks = keep(data.attacks)\n\t\tdata.pings = keep(data.pings)\n\t\tdata.damage = keep(data.damage)\n\t\tdata.deaths = keep(data.deaths)\n\t\tif (!all) return\n\t\tdata.army = keep(data.army)\n\t\tdata.workers = keep(data.workers)\n\t\tdata.heroes = keep(data.heroes)\n\t\tdata.structures = data.structures.filter((each) => each.gone === undefined || each.gone >= oldest)\n\t\tthis.enemy.reset()\n\t}\n\n\t/** What it remembers, as plain data for a save: a copy */\n\t/** Whether it has anything to remember now: one that does not is left out of a save */\n\tremembers(): boolean {\n\t\treturn this.kept\n\t}\n\n\tsave(): KnowledgeMemory {\n\t\t// the map's cells copied as a list of numbers, much faster than `structuredClone` walks them; the rest cloned, its\n\t\t// keys in their order\n\t\tconst { looked } = this.data\n\t\tconst copy = structuredClone({ ...this.data, looked: undefined }) as unknown as KnowledgeMemory\n\t\tcopy.looked = { cols: looked.cols, rows: looked.rows, ticks: looked.ticks.slice() }\n\t\treturn copy\n\t}\n\n\t/** Takes back what `save` gave. Memory of another shape is dropped: it starts afresh */\n\trestore(memory: unknown): boolean {\n\t\tconst data = memory as KnowledgeMemory | undefined\n\t\tif (!data || typeof data !== 'object' || data.v !== 1) return false\n\t\tthis.data = { ...empty(), ...structuredClone(data) }\n\t\t// a sighting from before sightings had a strength is let go: the army will be seen again, the sighting would not add up\n\t\tthis.data.army = this.data.army.filter((sighting) => typeof sighting.strength === 'number')\n\t\tthis.enemy.reset()\n\t\treturn true\n\t}\n\n\t/** What it knows, in short, for the debug tools: bases, the army seen with its age, the tech seen */\n\tinspect(): Record<string, unknown> {\n\t\tconst age = (tick: number) => Math.round(this.seconds(this.data.tick - tick))\n\t\treturn {\n\t\t\tbases: this.enemy.bases().map((base) => ({\n\t\t\t\towner: base.owner,\n\t\t\t\tat: [Math.round(base.at.x), Math.round(base.at.z)],\n\t\t\t\tstructures: base.structures.length,\n\t\t\t\tseen: age(base.last),\n\t\t\t\t...(base.gone && { gone: true })\n\t\t\t})),\n\t\t\tarmy: this.data.army.map((each) => ({ at: [Math.round(each.at.x), Math.round(each.at.z)], count: each.count, seen: age(each.tick) })),\n\t\t\ttech: this.enemy.techSeen(),\n\t\t\tlost: this.data.lost.length\n\t\t}\n\t}\n}\n\n/**\n * What a computer player remembers of its enemies (`knowledge.enemy`): their structures and bases, their army as last\n * seen, their workers and heroes, the types and tech seen. Creeps are no one's enemy here\n *\n * @beta\n */\nexport class EnemyKnowledge {\n\tprivate basesFound: EnemyBase[] | undefined\n\tprivate trainedBy: { registry: object; by: Map<string, string[]> } | undefined\n\n\tconstructor(private readonly knowledge: Knowledge) {}\n\n\t/** @internal Forgets what was worked out of the data: it changed */\n\treset(): void {\n\t\tthis.basesFound = undefined\n\t}\n\n\t/** Their structures remembered and not known gone (`gone: true` for those too), of one owner where given */\n\tstructures(options: { owner?: PlayerId; gone?: boolean } = {}): StructureSeen[] {\n\t\treturn this.knowledge.data.structures.filter(\n\t\t\t(each) => (options.gone || each.gone === undefined) && (options.owner === undefined || each.owner === options.owner)\n\t\t)\n\t}\n\n\t/**\n\t * Their bases: the structures remembered, gone ones too, clustered by owner around what takes deposits (a hall), or\n\t * around any structure where none does. The first seen of each owner's first; `gone` where all of it is known gone\n\t */\n\tbases(owner?: PlayerId): EnemyBase[] {\n\t\tconst all = (this.basesFound ??= this.cluster())\n\t\treturn owner === undefined ? all : all.filter((base) => base.owner === owner)\n\t}\n\n\tprivate cluster(): EnemyBase[] {\n\t\tconst { knowledge } = this\n\t\tconst registry = knowledge.view?.registry\n\t\tconst reach = BASE_REACH * BASE_REACH\n\t\tconst takesDeposits = (each: StructureSeen) => !!registry?.units.has(each.type) && !!registry.unit(each.type).dropOff\n\t\t// by the time each was first seen, so the first base of an owner is the first found of theirs\n\t\tconst structures = [...knowledge.data.structures].sort((a, b) => a.first - b.first || a.id - b.id)\n\t\tconst bases: EnemyBase[] = []\n\t\tconst centreOf = (each: StructureSeen) => bases.find((base) => base.owner === each.owner && distSq(base.at, each.at) < reach)\n\t\tfor (const each of structures) {\n\t\t\tif (!takesDeposits(each) || centreOf(each)) continue\n\t\t\tbases.push({\n\t\t\t\towner: each.owner,\n\t\t\t\tat: at(each.at),\n\t\t\t\tfirst: each.first,\n\t\t\t\tlast: each.last,\n\t\t\t\tstructures: [],\n\t\t\t\thall: true,\n\t\t\t\tgone: false,\n\t\t\t\texpansion: false\n\t\t\t})\n\t\t}\n\t\tfor (const each of structures) {\n\t\t\tlet base = centreOf(each)\n\t\t\tif (!base) {\n\t\t\t\tbase = { owner: each.owner, at: at(each.at), first: each.first, last: each.last, structures: [], hall: false, gone: false, expansion: false }\n\t\t\t\tbases.push(base)\n\t\t\t}\n\t\t\tbase.structures.push(each)\n\t\t\tbase.first = Math.min(base.first, each.first)\n\t\t\tbase.last = Math.max(base.last, each.last)\n\t\t}\n\t\tconst firstOf = new Set<PlayerId>()\n\t\tbases.sort((a, b) => a.first - b.first || a.owner - b.owner)\n\t\tfor (const base of bases) {\n\t\t\tbase.gone = base.structures.every((each) => each.gone !== undefined)\n\t\t\tif (!base.hall) continue\n\t\t\tif (firstOf.has(base.owner)) base.expansion = true\n\t\t\telse firstOf.add(base.owner)\n\t\t}\n\t\treturn bases\n\t}\n\n\t/** Their bases beyond the first of each owner's, with a hall: where they expanded to, as far as seen */\n\texpansionsSeen(): EnemyBase[] {\n\t\treturn this.bases().filter((base) => base.expansion && !base.gone)\n\t}\n\n\t/** Their army as last seen, in groups, newest first; only those seen within so many seconds where given */\n\tarmySeen(withinSeconds?: number): ArmySighting[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.army.filter((each) => each.tick >= oldest)\n\t}\n\n\t/** Their workers as last seen, newest first; only those seen within so many seconds where given */\n\tworkersSeen(withinSeconds?: number): UnitSeen[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.workers.filter((each) => each.tick >= oldest)\n\t}\n\n\t/** Their heroes as last seen, newest first: type, level, where, and `died` when seen to die */\n\theroesSeen(): UnitSeen[] {\n\t\treturn this.knowledge.data.heroes\n\t}\n\n\t/** The unit and structure types of theirs seen, with when and the most seen at once */\n\ttypesSeen(): Readonly<Record<string, TypeSeen>> {\n\t\treturn this.knowledge.data.types\n\t}\n\n\t/** The most of a type of theirs seen at once: 0 for one never seen */\n\tmostSeen(type: string): number {\n\t\treturn this.knowledge.data.types[type]?.most ?? 0\n\t}\n\n\t/**\n\t * What they have, as far as what was seen tells: the types seen; what those require, named as `UnitTypeDef.requires`\n\t * names them; and the building that trains a type, where only one does (a gryphon means an aviary, and what an aviary\n\t * requires). Sorted, for the same answer every time\n\t */\n\ttechSeen(): string[] {\n\t\tconst registry = this.knowledge.view?.registry\n\t\tconst tech = new Set<string>()\n\t\tconst add = (id: string) => {\n\t\t\tif (tech.has(id)) return\n\t\t\ttech.add(id)\n\t\t\tif (!registry?.units.has(id)) return\n\t\t\tfor (const need of registry.unit(id).requires ?? []) add(need)\n\t\t\tconst trainers = this.trainersOf(id)\n\t\t\tif (trainers.length === 1) add(trainers[0])\n\t\t}\n\t\tfor (const type of Object.keys(this.knowledge.data.types)) add(type)\n\t\treturn [...tech].sort()\n\t}\n\n\t/** The building types that train a unit type, found once for the game's definitions */\n\tprivate trainersOf(type: string): readonly string[] {\n\t\tconst registry = this.knowledge.view?.registry\n\t\tif (!registry) return []\n\t\tif (this.trainedBy?.registry !== registry) {\n\t\t\tconst by = new Map<string, string[]>()\n\t\t\tfor (const def of registry.units.all())\n\t\t\t\tfor (const trained of def.trains ?? []) (by.get(trained) ?? by.set(trained, []).get(trained)!).push(def.id)\n\t\t\tthis.trainedBy = { registry, by }\n\t\t}\n\t\treturn this.trainedBy.by.get(type) ?? []\n\t}\n\n\t/** Takes in what a type seen was, where the game or an older save tells: as if seen, `count` at once, at a tick */\n\tsawType(type: string, count: number, tick = this.knowledge.tick): void {\n\t\tconst seen = (this.knowledge.data.types[type] ??= { first: tick, last: tick, most: 0 })\n\t\tseen.last = Math.max(seen.last, tick)\n\t\tseen.most = Math.max(seen.most, count)\n\t}\n}\n\n/**\n * What a computer player remembers of the map (`knowledge.map`): when each place was last in sight. The cells are of\n * the view's grid (8 units)\n *\n * @beta\n */\nexport class MapKnowledge {\n\tconstructor(private readonly knowledge: Knowledge) {}\n\n\t/** The tick a place was last in sight of the seat's team: none for a place never seen */\n\tlastLooked(point: Vec2): number | undefined {\n\t\tconst cell = this.knowledge.cell(point)\n\t\tconst tick = cell < 0 ? -1 : (this.knowledge.data.looked.ticks[cell] ?? -1)\n\t\treturn tick < 0 ? undefined : tick\n\t}\n\n\t/** Seconds since a place was last in sight: `Infinity` for one never seen */\n\tsinceLooked(point: Vec2): number {\n\t\tconst tick = this.lastLooked(point)\n\t\treturn tick === undefined ? Infinity : this.knowledge.seconds(this.knowledge.tick - tick)\n\t}\n\n\t/** Whether a place is in sight now, as of the last update */\n\tinSight(point: Vec2): boolean {\n\t\treturn this.lastLooked(point) === this.knowledge.tick && this.knowledge.view !== undefined\n\t}\n\n\t/** Whether the seat's team has explored a place: seen it once, as the fog says */\n\texplored(point: Vec2): boolean {\n\t\tconst { fog, view } = this.knowledge\n\t\tif (!fog || !view) return this.lastLooked(point) !== undefined\n\t\tif (fog.revealed || !fog.explored.length) return true\n\t\tconst { width, depth } = view.session.terrain\n\t\tconst fx = Math.floor((point.x / width) * fog.width)\n\t\tconst fz = Math.floor((point.z / depth) * fog.depth)\n\t\tif (fx < 0 || fz < 0 || fx >= fog.width || fz >= fog.depth) return false\n\t\treturn !!fog.explored[fz * fog.width + fx]\n\t}\n\n\t/** Takes in that a place was looked at, at a tick: where the game or an older save tells */\n\tlook(point: Vec2, tick = this.knowledge.tick): void {\n\t\tconst cell = this.knowledge.cell(point)\n\t\tconst ticks = this.knowledge.data.looked.ticks\n\t\tif (cell >= 0) ticks[cell] = Math.max(ticks[cell] ?? -1, tick)\n\t}\n\n\t/**\n\t * The map's mines (`view.mines`), each with when its place was last looked at and whose base is by it, as far as\n\t * known: where to expand, where to look for theirs\n\t */\n\tmines(): (MineInfo & { looked?: number; taken?: PlayerId })[] {\n\t\tconst view = this.knowledge.view\n\t\tif (!view) return []\n\t\tconst mine = view.bases()\n\t\tconst theirs = this.knowledge.enemy.bases().filter((base) => base.hall && !base.gone)\n\t\tconst reach = BASE_REACH * BASE_REACH\n\t\treturn view.mines().map((each) => {\n\t\t\tconst looked = this.lastLooked(each)\n\t\t\tconst taken = mine.some((base) => distSq(base.at, each) < reach) ? view.playerId : theirs.find((base) => distSq(base.at, each) < reach)?.owner\n\t\t\treturn { ...each, ...(looked !== undefined && { looked }), ...(taken !== undefined && { taken }) }\n\t\t})\n\t}\n\n\t/** The map's creep camps, as the seat knows them (`view.camps`) */\n\tcamps(): readonly CampInfo[] {\n\t\treturn this.knowledge.view?.camps() ?? []\n\t}\n}\n\n/**\n * What a computer player remembers of itself (`knowledge.own`): what it lost, the attacks it sent, what it gathered\n *\n * @beta\n */\nexport class OwnKnowledge {\n\tconstructor(private readonly knowledge: Knowledge) {}\n\n\t/** What of its own died, oldest first; only within so many seconds where given */\n\tlost(withinSeconds?: number): Loss[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.lost.filter((each) => each.tick >= oldest)\n\t}\n\n\t/** What of its own died within a distance of a place: \"we are being raided here\" */\n\tlostNear(point: Vec2, radius: number, withinSeconds?: number): Loss[] {\n\t\tconst reach = radius * radius\n\t\treturn this.lost(withinSeconds).filter((each) => distSq(each.at, point) <= reach)\n\t}\n\n\t/** Notes an attack sent, for whoever asks later (`attacks`): what a module that sends an army calls */\n\tattackSent(point: Vec2, count: number): void {\n\t\tconst { data, options } = this.knowledge\n\t\tdata.attacks.push({ tick: data.tick, at: at(point), count })\n\t\ttrimOldest(data.attacks, options.limits.attacks)\n\t}\n\n\t/** The attacks sent, oldest first; only within so many seconds where given */\n\tattacks(withinSeconds?: number): AttackSent[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.attacks.filter((each) => each.tick >= oldest)\n\t}\n\n\t/**\n\t * What it gathers of a resource a minute, over the last so many seconds (60): from the rises in what it has, so it\n\t * is at least this (what was gathered and spent between two thinks does not show). Bounty counts as gathered\n\t */\n\tincome(kind: ResourceKind, seconds = 60): number {\n\t\tconst { data } = this.knowledge\n\t\tconst rate = this.knowledge.view?.session.tickRate ?? 1\n\t\tconst from = data.tick - seconds * rate\n\t\tconst sample = data.history.find((each) => each.tick >= from) ?? data.history[0]\n\t\tif (!sample) return 0\n\t\tconst elapsed = (data.tick - sample.tick) / rate\n\t\tif (elapsed <= 0) return 0\n\t\treturn (((data.gathered[kind] ?? 0) - (sample.gathered[kind] ?? 0)) / elapsed) * 60\n\t}\n\n\t/** The income of every resource gathered so far, a minute (`income`) */\n\tincomes(seconds = 60): Record<ResourceKind, number> {\n\t\tconst result: Record<ResourceKind, number> = {}\n\t\tfor (const kind of Object.keys(this.knowledge.data.gathered)) result[kind] = this.income(kind, seconds)\n\t\treturn result\n\t}\n\n\t/** What was gathered of each resource since the game began, as far as the rises tell */\n\tget gathered(): Readonly<Record<ResourceKind, number>> {\n\t\treturn this.knowledge.data.gathered\n\t}\n\n\t/** The samples of what was gathered, oldest first */\n\tget history(): KnowledgeMemory['history'] {\n\t\treturn this.knowledge.data.history\n\t}\n}\n\n/**\n * What a computer player heard (`knowledge.events`): pings, damage to its own and its allies', deaths, each with its\n * tick, the oldest first\n *\n * @beta\n */\nexport class HeardEvents {\n\tconstructor(private readonly knowledge: Knowledge) {}\n\n\t/** Pings heard; only within so many seconds where given */\n\tpings(withinSeconds?: number): PingHeard[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.pings.filter((each) => each.tick >= oldest)\n\t}\n\n\t/** Damage seen done to its own and its allies' entities, a line an entity a think; only within so many seconds where given */\n\tdamage(withinSeconds?: number): DamageSeen[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.damage.filter((each) => each.tick >= oldest)\n\t}\n\n\t/** Deaths seen, anyone's; only within so many seconds where given */\n\tdeaths(withinSeconds?: number): DeathSeen[] {\n\t\tconst oldest = this.knowledge.since(withinSeconds)\n\t\treturn this.knowledge.data.deaths.filter((each) => each.tick >= oldest)\n\t}\n}\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tknowledge?: KnowledgeMemory\n\t}\n}\n","import type { Vec2 } from '#engine/math'\nimport type { Waves } from './waves'\nimport type { ObjectiveStatus } from '#engine/objectives'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain, type Told } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport type { AiRole } from './roles'\nimport type { UnitSet } from './view'\nimport type { Squad } from './squads'\n\n/*\n * Rules and words from the game (AI plan, B2): what a mission scripts for its computer player, in the computer's own\n * terms. Before this, a mission that wanted \"when the hero crosses the river, the camp attacks\" wrote a system that\n * reached into the world and gave orders to the computer's units beside the computer that thought on its own, and the\n * two fought over them. Now it is a rule of the brain's:\n *\n * when({ units: { role: 'hero', of: 'enemy', near: 'the ford' } }).once().do((ai) => ai.tell('attack', { at: ford }))\n *\n * - **A condition** (`AiCondition`) is a question with a yes or no: a function of the brain, or plain data (`{ time: {\n * after: 300 } }`, `{ all: [...] }`) that a map's file, a mission's JSON, and later the editor can hold. The data\n * forms are listed in `docs/ai.md`, each with what it asks; a game adds its own (`GameAi.conditions`, a brain's `BrainDef.conditions`) and names it\n * (`{ is: 'mygame.bridgeDown', args: { name: 'north' } }`). Waves, build orders and target priorities (B3, C2, D2) take the same conditions.\n * - **A rule** (`when(condition).do(action)`) does its action when its condition becomes true: on the think it turns\n * from no to yes, not on every think it stays yes (a trigger, as a map editor's are). `once()` fires it the first\n * time only, ever; `every(seconds)` fires it again while the condition holds, at most so often; `priority(n)` checks\n * it before rules of less. Rules are a module (`rules([...])`), checked each think in order: put it ahead of the\n * modules that act, so that what a rule takes is not given orders by them first.\n * - **Words** are what the game tells a computer (`world.computers.tell(player, 'attack', { at })`): kept in the brain\n * until taken (a save keeps a word not yet heard), read with `ai.told(word)`, taken by a told rule (`when.told(word)`,\n * whose action gets the word's data) or by the `words()` module, which answers the words every brain may be told:\n * `attack`, `defend`, `retreat`, `hold`, `pause` (and `resume`, which the brain answers itself, paused as it is).\n * - **Who may move a unit.** A rule that orders units takes them first (`ai.goals.take(ids, 'told', { id, seconds })`):\n * no goal claims them while the rule holds them, and the melee player's focus fire leaves them be. What a rule took\n * is let go of when its time is up, and the goals have them again.\n *\n * What the rules remember (which fired, when, and whether each held at the last check) is plain data in the brain's\n * memory, so a loaded game does not fire a `once` rule twice.\n */\n\n/**\n * At least `min` and at most `max`, each left out for no bound: a count, an amount, a level\n *\n * @beta\n */\nexport interface AiRange {\n\tmin?: number\n\tmax?: number\n}\n\n/**\n * Whose units a condition counts: the player’s own (the default), its rivals’ in sight, its allies’\n *\n * @beta\n */\nexport type AiWhose = 'mine' | 'enemy' | 'ally'\n\n/**\n * A condition as plain data: what a map's file, a mission's JSON or the editor holds. Each form is one question; the\n * table in `docs/ai.md` says what each asks\n *\n * @beta\n */\nexport type AiConditionData =\n\t/** Every one of them */\n\t| { all: AiCondition[] }\n\t/** One of them at least */\n\t| { any: AiCondition[] }\n\t/** The other way round */\n\t| { not: AiCondition }\n\t/** How much it has of a resource */\n\t| { resource: { id: string } & AiRange }\n\t/**\n\t * How many units there are, of a type, a role or a tag, whose (`of`), near a named entity, point or region (`near`,\n\t * `within`), finished only (`finished`); and for `of: 'enemy'`, those remembered out of sight too (`known`). At\n\t * least one where neither `min` nor `max` is given\n\t */\n\t| {\n\t\t\tunits: {\n\t\t\t\ttype?: string\n\t\t\t\trole?: AiRole\n\t\t\t\ttag?: string\n\t\t\t\tof?: AiWhose\n\t\t\t\tnear?: string | Vec2\n\t\t\t\twithin?: number\n\t\t\t\tfinished?: boolean\n\t\t\t\tknown?: boolean\n\t\t\t} & AiRange\n\t }\n\t/** Its supply: free (cap less used), used, cap */\n\t| { supply: { free?: AiRange; used?: AiRange; cap?: AiRange } }\n\t/** Seconds into the game: from `after`, before `before` */\n\t| { time: { after?: number; before?: number } }\n\t/**\n\t * Whether its own are being hit: damage seen to its entities within so many seconds (5 when left out), anywhere, or\n\t * near a named entity, a point or a region (`near`, `within` the reach: 16)\n\t */\n\t| { underAttack: true | { seconds?: number; near?: string | Vec2; reach?: number } }\n\t/** Whether a rival's unit of a type or a role was seen, within so many seconds where given (ever, when left out) */\n\t| { seen: { type?: string; role?: AiRole; within?: number } }\n\t/** The difficulty it plays on (its profile's: `AiOptions.difficulty`, normal when left out), one or any of a list */\n\t| { difficulty: string | string[] }\n\t/** Whether the game told it this word and nothing took it yet */\n\t| { told: string }\n\t/** Yes so often, by the brain's own numbers (`ai.rng`): `0.3` is three times in ten. The same game says the same */\n\t| { chance: number }\n\t/** Its heroes: one at least of this type (any where left out), alive where `alive` says, of a level */\n\t| { hero: { type?: string; alive?: boolean; level?: AiRange } }\n\t/** The index of the wave whose turn it is (`ai.waves.index`, the waves sent and skipped before it); where it has no waves, the attacks it sent (its knowledge's `own.attacks`) */\n\t| { wave: AiRange }\n\t/** One of its own objectives, by id, in this status (or any of these) */\n\t| { objective: { id: string; status: ObjectiveStatus | ObjectiveStatus[] } }\n\t/** A value of the game's report to this player (`GameModule.report`), by its path (`'waves.next'`): equal to, or within */\n\t| { report: { path: string; equals?: unknown } & AiRange }\n\t/**\n\t * A value of a component the game replicates to this player (`Component.replicate`) on an entity: one the map or\n\t * the rules named (`entity`), or the first of its own of a type (`type`). By path in it, where it is an object\n\t */\n\t| { component: { id: string; entity?: string; type?: string; path?: string; equals?: unknown } & AiRange }\n\t/** How many units are in a region of the map, whose (`of`: its own when left out), of a type or a role */\n\t| { region: { name: string; of?: AiWhose; type?: string; role?: AiRole } & AiRange }\n\t/** A condition of the game's own or the brain's (`GameAi.conditions`, `BrainDef.conditions`), by id, with its arguments (`{ is: 'mygame.bridge', args: { name: 'north' } }`) */\n\t| { is: string; args?: Record<string, unknown> }\n\n/**\n * A condition: a question with a yes or no, as a function of the brain, or as plain data (`AiConditionData`)\n *\n * @beta\n */\nexport type AiCondition = ((ai: Brain) => boolean) | AiConditionData\n\n/**\n * A condition of a game's own or a brain's, for the data form (`{ is: id, args }`): a map's file names it, the game\n * (`GameAi.conditions`) or the brain (`BrainDef.conditions`) gives the code, by an id prefixed as components are\n * (`mygame.bridgeDown`)\n *\n * @beta\n */\nexport type AiConditionTest = (ai: Brain, args: Record<string, unknown>) => boolean\n\nconst inRange = (value: number, range: AiRange, least = 1) =>\n\trange.min === undefined && range.max === undefined\n\t\t? value >= least\n\t\t: (range.min === undefined || value >= range.min) && (range.max === undefined || value <= range.max)\n\n/** A value at a path of dots in plain data (`'waves.next'`): the value itself for no path */\nfunction at(value: unknown, path: string | undefined): unknown {\n\tif (!path) return value\n\tlet here = value\n\tfor (const key of path.split('.')) {\n\t\tif (!here || typeof here !== 'object') return undefined\n\t\there = (here as Record<string, unknown>)[key]\n\t}\n\treturn here\n}\n\n/** Whether a value is as asked: equal to `equals`, or a number within the range */\nconst matches = (value: unknown, asked: { equals?: unknown } & AiRange) =>\n\t'equals' in asked ? value === asked.equals : typeof value === 'number' && inRange(value, asked, -Infinity)\n\n/** Whose units: the brain's sets of them */\nfunction whose(ai: Brain, of: AiWhose | undefined, known?: boolean): UnitSet {\n\tconst { view } = ai\n\tif (of === 'enemy') return known ? view.enemies.known() : view.enemies\n\tif (of === 'ally') return view.allies\n\treturn view.mine\n}\n\n/** Narrowed to a type, a role, a tag */\nfunction kind(units: UnitSet, asked: { type?: string; role?: AiRole; tag?: string }): UnitSet {\n\tlet set = units\n\tif (asked.type !== undefined) set = set.ofType(asked.type)\n\tif (asked.role !== undefined) set = set.withRole(asked.role)\n\tif (asked.tag !== undefined) set = set.withTag(asked.tag)\n\treturn set\n}\n\n/** Where a condition means: a named entity the player knows of, or a point; nothing for a name it does not know */\nfunction place(ai: Brain, near: string | Vec2): Vec2 | undefined {\n\tif (typeof near !== 'string') return near\n\tconst named = ai.view.named(near)\n\tif (named) return { x: named.x, z: named.z }\n\treturn undefined\n}\n\n/** Whether a point is near a place: a region by name, a named entity or a point within `reach` */\nfunction nearPlace(ai: Brain, point: Vec2, near: string | Vec2, reach: number): boolean {\n\tif (typeof near === 'string' && ai.view.region(near)) return ai.view.inRegion(near, point)\n\tconst to = place(ai, near)\n\tif (!to) return false\n\tconst dx = point.x - to.x\n\tconst dz = point.z - to.z\n\treturn dx * dx + dz * dz <= reach * reach\n}\n\n/**\n * Whether a condition holds for the brain now: a function is asked, data is read as its form says. A form the kit\n * does not know (a game's own not defined) is no, and the log says so once\n *\n * @beta\n */\nexport function evaluate(condition: AiCondition, ai: Brain): boolean {\n\tif (typeof condition === 'function') return !!condition(ai)\n\tif (!condition || typeof condition !== 'object') return false\n\tconst { view } = ai\n\tif ('all' in condition) return condition.all.every((each) => evaluate(each, ai))\n\tif ('any' in condition) return condition.any.some((each) => evaluate(each, ai))\n\tif ('not' in condition) return !evaluate(condition.not, ai)\n\tif ('resource' in condition) return inRange(view.me.resources[condition.resource.id] ?? 0, condition.resource, -Infinity)\n\tif ('units' in condition) {\n\t\tconst asked = condition.units\n\t\tlet set = kind(whose(ai, asked.of, asked.known), asked)\n\t\tif (asked.finished) set = set.finished()\n\t\tif (asked.near !== undefined) {\n\t\t\tconst near = asked.near\n\t\t\tconst reach = asked.within ?? 16\n\t\t\tset = set.where((unit) => nearPlace(ai, unit, near, reach))\n\t\t}\n\t\treturn inRange(set.length, asked)\n\t}\n\tif ('supply' in condition) {\n\t\tconst { me } = view\n\t\tconst asked = condition.supply\n\t\treturn (\n\t\t\t(!asked.free || inRange(me.supplyCap - me.supplyUsed, asked.free, -Infinity)) &&\n\t\t\t(!asked.used || inRange(me.supplyUsed, asked.used, -Infinity)) &&\n\t\t\t(!asked.cap || inRange(me.supplyCap, asked.cap, -Infinity))\n\t\t)\n\t}\n\tif ('time' in condition) {\n\t\tconst { after, before } = condition.time\n\t\treturn (after === undefined || ai.time >= after) && (before === undefined || ai.time < before)\n\t}\n\tif ('underAttack' in condition) {\n\t\tconst asked = condition.underAttack === true ? {} : condition.underAttack\n\t\tconst hits = ai.knowledge.events.damage(asked.seconds ?? 5).filter((hit) => hit.owner === ai.playerId)\n\t\tif (asked.near === undefined) return hits.length > 0\n\t\tconst near = asked.near\n\t\treturn hits.some((hit) => nearPlace(ai, hit.at, near, asked.reach ?? 16))\n\t}\n\tif ('seen' in condition) {\n\t\tconst asked = condition.seen\n\t\tconst since = asked.within === undefined ? -Infinity : ai.tick - asked.within * ai.session.tickRate\n\t\tfor (const [type, seen] of Object.entries(ai.knowledge.enemy.typesSeen())) {\n\t\t\tif (seen.last < since) continue\n\t\t\tif (asked.type !== undefined && type !== asked.type) continue\n\t\t\tif (asked.role !== undefined && !view.hasRole(type, asked.role)) continue\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\tif ('difficulty' in condition) {\n\t\tconst playing = ai.profile.difficulty ?? 'normal'\n\t\treturn Array.isArray(condition.difficulty) ? condition.difficulty.includes(playing) : condition.difficulty === playing\n\t}\n\tif ('told' in condition) return ai.told(condition.told).length > 0\n\tif ('chance' in condition) return ai.rng.next() < condition.chance\n\tif ('hero' in condition) {\n\t\tconst asked = condition.hero\n\t\treturn view.me.heroes.some(\n\t\t\t(hero) =>\n\t\t\t\t(asked.type === undefined || hero.type === asked.type) &&\n\t\t\t\t(asked.alive === undefined || hero.alive === asked.alive) &&\n\t\t\t\t(!asked.level || inRange(hero.level, asked.level, -Infinity))\n\t\t)\n\t}\n\t// the index of the wave whose turn it is, where the brain has waves (D2); else the attacks it sent\n\tif ('wave' in condition) {\n\t\t// the waves it was given, where it has any, else the attacks it made\n\t\tconst waves = ai.made<Waves>('waves')\n\t\treturn inRange(waves?.given ? waves.index : ai.knowledge.own.attacks().length, condition.wave, -Infinity)\n\t}\n\tif ('objective' in condition) {\n\t\tconst { id, status } = condition.objective\n\t\tconst objective = view.me.objectives.find((each) => each.id === id)\n\t\treturn !!objective && (Array.isArray(status) ? status.includes(objective.status) : objective.status === status)\n\t}\n\tif ('report' in condition) return matches(at(view.report, condition.report.path), condition.report)\n\tif ('component' in condition) {\n\t\tconst asked = condition.component\n\t\tconst entity: EntityState | undefined =\n\t\t\tasked.entity !== undefined ? view.named(asked.entity) : asked.type !== undefined ? view.mine.ofType(asked.type).first() : undefined\n\t\treturn !!entity && matches(at(entity.components?.[asked.id], asked.path), asked)\n\t}\n\tif ('region' in condition) {\n\t\tconst asked = condition.region\n\t\tif (!view.region(asked.name)) return false\n\t\tconst set = kind(whose(ai, asked.of), asked).where((unit) => view.inRegion(asked.name, unit))\n\t\treturn inRange(set.length, asked)\n\t}\n\tif ('is' in condition) {\n\t\tconst { is, args = {} } = condition\n\t\tconst own = ai.def.conditions?.[is] ?? ai.registry.module?.ai?.conditions?.[is]\n\t\tif (!own) {\n\t\t\twarnOnce(ai, `a condition names \"${is}\", which neither the game nor the brain has (GameAi.conditions, BrainDef.conditions): it is no`)\n\t\t\treturn false\n\t\t}\n\t\treturn !!own(ai, args)\n\t}\n\twarnOnce(ai, `a condition of no form the kit knows (${Object.keys(condition).join(', ')}): it is no`)\n\treturn false\n}\n\nconst warned = new WeakMap<Brain, Set<string>>()\nfunction warnOnce(ai: Brain, line: string): void {\n\tlet said = warned.get(ai)\n\tif (!said) warned.set(ai, (said = new Set()))\n\tif (said.has(line)) return\n\tsaid.add(line)\n\tai.log.warn('ai', line)\n}\n\n/**\n * What a rule does, as plain data: a word the brain tells itself (`{ say: 'attack', data: { at } }`), answered by the\n * `words()` module or a told rule of its own, the same think where they come after the rules\n *\n * @beta\n */\nexport interface AiActionData {\n\tsay: string\n\tdata?: unknown\n}\n\n/**\n * What a rule does: a function of the brain and, for a told rule, what came with the word; or plain data\n * (`AiActionData`)\n *\n * @beta\n */\nexport type AiAction = ((ai: Brain, data?: unknown) => void) | AiActionData\n\n/**\n * A rule of a brain (`when(condition).do(action)`): checked each think by the `rules()` module, its action done as\n * its condition becomes true. Code: given again by the brain's definition, as goals are; what it remembers is data\n *\n * @beta\n */\nexport interface AiRule {\n\t/** Its name: what the memory, the report and the log know it by. `rule 1`, `rule 2`… in the module's list when left out */\n\treadonly id?: string\n\t/** When it fires: a condition, or a word told (`when.told`) */\n\treadonly when: AiCondition | { word: string }\n\t/** What it does */\n\treadonly action: AiAction\n\t/** Whether it fires the first time only, ever */\n\treadonly once?: boolean\n\t/** Seconds: fired again while its condition holds, at most so often. Left out, it fires as it turns true */\n\treadonly every?: number\n\t/** Checked before rules of less: 0 when left out */\n\treadonly priority?: number\n}\n\n/**\n * A rule being written: `when(...)`, then any of `once`, `every`, `priority`, `named`, then `do`\n *\n * @beta\n */\nexport interface RuleBuilder {\n\t/** Fires the first time only, ever */\n\tonce(): RuleBuilder\n\t/** Fires again while the condition holds, at most every so many seconds */\n\tevery(seconds: number): RuleBuilder\n\t/** Checked before rules of less */\n\tpriority(n: number): RuleBuilder\n\t/** Its name, for the memory, the report and the log */\n\tnamed(id: string): RuleBuilder\n\t/** What it does: the rule */\n\tdo(action: AiAction): AiRule\n}\n\nfunction builder(rule: Omit<AiRule, 'action'>): RuleBuilder {\n\treturn {\n\t\tonce: () => builder({ ...rule, once: true }),\n\t\tevery: (seconds) => builder({ ...rule, every: seconds }),\n\t\tpriority: (n) => builder({ ...rule, priority: n }),\n\t\tnamed: (id) => builder({ ...rule, id }),\n\t\tdo: (action) => ({ ...rule, action })\n\t}\n}\n\n/**\n * A rule: `when(condition).do(action)`, with `once()`, `every(seconds)`, `priority(n)`, `named(id)` between. The\n * condition is a function of the brain or plain data (`AiCondition`). `when.told(word)` fires once for each time the\n * word is told, taking it, its action given the word's data\n *\n * @beta\n */\nexport const when = Object.assign((condition: AiCondition): RuleBuilder => builder({ when: condition }), {\n\t/** A rule that fires for each time the game tells the brain this word (`world.computers.tell`), and takes it */\n\ttold: (word: string): RuleBuilder => builder({ when: { word } })\n})\n\n/** What the rules remember of one rule */\ninterface RuleMemory {\n\t/** Whether its condition held at the last check: a rule fires as it turns true */\n\twas?: boolean\n\t/** The tick it last fired at */\n\tfired?: number\n\t/** How many times it fired */\n\tcount: number\n}\n\n/**\n * What a rule is now, for the report: whether it held at the last check, how often and when it last fired\n *\n * @internal\n */\nexport interface RuleReport {\n\tid: string\n\tpriority: number\n\tonce: boolean\n\tholds: boolean\n\tcount: number\n\tfired?: number\n}\n\nconst isWord = (when: AiRule['when']): when is { word: string } =>\n\ttypeof when === 'object' &&\n\twhen !== null &&\n\t'word' in when &&\n\ttypeof (when as { word: unknown }).word === 'string' &&\n\tObject.keys(when).length === 1\n\n/** Does a rule's action */\nfunction act(ai: Brain, action: AiAction, data?: unknown): void {\n\tif (typeof action === 'function') action(ai, data)\n\telse ai.tell(action.say, action.data, ai.tick)\n}\n\n/**\n * The rules module: checks its rules each think, in their order (by `priority`, then as given), and does each one's\n * action as its condition turns true. Ahead of the modules that act on units, where a brain lists it: what a rule\n * takes is then not given orders by them first. Its id is `rules` (give `id` for a second one)\n *\n * @beta\n */\nexport const rules = (list: AiRule[], options: { id?: string } = {}): AiModuleDef =>\n\tdefineModule(options.id ?? 'rules', (ai: Brain): AiModule => {\n\t\tconst named = list.map((rule, i) => ({ ...rule, id: rule.id ?? `rule ${i + 1}` }))\n\t\tconst seen = new Set<string>()\n\t\tfor (const rule of named) {\n\t\t\tif (seen.has(rule.id)) throw new Error(`The brain \"${ai.def.id}\" has two rules called \"${rule.id}\"`)\n\t\t\tseen.add(rule.id)\n\t\t}\n\t\tconst ordered = named.map((rule, i) => ({ rule, i })).sort((a, b) => (b.rule.priority ?? 0) - (a.rule.priority ?? 0) || a.i - b.i)\n\t\tlet memory: Record<string, RuleMemory> = {}\n\t\tconst of = (id: string) => (memory[id] ??= { count: 0 })\n\t\tconst fire = (rule: AiRule & { id: string }, data?: unknown, word?: Told) => {\n\t\t\tconst kept = of(rule.id)\n\t\t\tkept.fired = ai.tick\n\t\t\tkept.count++\n\t\t\tai.decide(`rule \"${rule.id}\" fires${word ? `: told \"${word.word}\"` : ''}`, { kind: 'rule' })\n\t\t\tact(ai, rule.action, data)\n\t\t}\n\t\treturn {\n\t\t\tid: options.id ?? 'rules',\n\t\t\tphase: 'hear',\n\t\t\tversion: 1,\n\t\t\tthink: () => {\n\t\t\t\tfor (const { rule } of ordered) {\n\t\t\t\t\tconst kept = of(rule.id)\n\t\t\t\t\tif (rule.once && kept.count > 0) continue\n\t\t\t\t\tif (isWord(rule.when)) {\n\t\t\t\t\t\t// each time the word was told, once; a `once` rule takes the first and leaves the rest\n\t\t\t\t\t\tconst words = ai.takeTold(rule.when.word, rule.once ? 1 : Infinity)\n\t\t\t\t\t\tfor (const word of words) fire(rule, word.data, word)\n\t\t\t\t\t\tkept.was = words.length > 0\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tconst holds = evaluate(rule.when, ai)\n\t\t\t\t\tconst turned = holds && !kept.was\n\t\t\t\t\tkept.was = holds\n\t\t\t\t\tif (!holds) continue\n\t\t\t\t\tconst again = rule.every !== undefined && kept.fired !== undefined && ai.tick - kept.fired >= Math.round(rule.every * ai.session.tickRate)\n\t\t\t\t\tif (turned || again) fire(rule)\n\t\t\t\t}\n\t\t\t},\n\t\t\tsave: () => structuredClone(memory),\n\t\t\trestore: (data) => {\n\t\t\t\tmemory = data && typeof data === 'object' ? structuredClone(data as Record<string, RuleMemory>) : {}\n\t\t\t},\n\t\t\tinspect: () => ({\n\t\t\t\trules: ordered.map(({ rule }): RuleReport => {\n\t\t\t\t\tconst kept = of(rule.id)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tid: rule.id,\n\t\t\t\t\t\tpriority: rule.priority ?? 0,\n\t\t\t\t\t\tonce: !!rule.once,\n\t\t\t\t\t\tholds: !!kept.was,\n\t\t\t\t\t\tcount: kept.count,\n\t\t\t\t\t\t...(kept.fired !== undefined && { fired: kept.fired })\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\t...(Object.keys(ai.goals.taken()).length && {\n\t\t\t\t\ttaken: Object.fromEntries(Object.entries(ai.goals.taken()).map(([id, hold]) => [id, { units: hold.units.length, until: hold.until }]))\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t})\n\n/**\n * What the words a brain may be told (`words()`) come with: where (`at`, a point, or a name the map or rules gave an\n * entity or region), and for how many seconds the army is the word's, not the goals' (`seconds`)\n *\n * @beta\n */\nexport interface WordData {\n\tat?: Vec2 | string\n\tseconds?: number\n}\n\n/** The squad the words put the army in, owned by the word's hold (`word:attack`) */\nconst WORD_SQUAD = 'word'\n\n/** The seconds each word holds the army for, where its data says none */\nconst WORD_SECONDS: Record<string, number> = { attack: 60, defend: 30, retreat: 15, hold: 30 }\n\n/**\n * The words module: answers the words any brain may be told (`world.computers.tell(player, word, data)`), taking them:\n *\n * - `attack` `{ at?, seconds? }`: the army (its fighters) attacks there, fighting what it meets on the way; where no\n * place is given, at the nearest building of a rival's it knows of, else at the first rival's base the seat was told\n * (`AiOptions.enemyBases`).\n * - `defend` `{ at?, seconds? }`: the army goes to fight there, home when left out.\n * - `retreat` `{ seconds? }`: the army comes home, fighting nothing on the way.\n * - `hold` `{ seconds? }`: the army stands where it is, fighting what comes in reach.\n * - `pause`: the brain sits still until told `resume` (or `world.computers.resume`); `resume` the brain answers itself.\n *\n * The army goes as one squad on the kit's task of the word (`attack`, `defend`, `retreat`, `hold`, in the squad\n * `word`), so that where the brain has the `squads()` module it regroups, focuses, kites and falls back on the odds as\n * any squad does. The army is the word's for `seconds` (attack 60, defend 30, retreat 15, hold 30): no goal claims it\n * meanwhile, then the squad goes and the goals have it again. Its id is `words`; put it after `rules`, so that a rule's `{ say }` is answered that think\n *\n * @beta\n */\nexport const words = (): AiModuleDef =>\n\tdefineModule('words', (ai: Brain): AiModule => {\n\t\tconst army = () => ai.view.mine.fighters().alive()\n\t\tconst point = (at: Vec2 | string | undefined): Vec2 | undefined => {\n\t\t\tif (at === undefined) return undefined\n\t\t\tif (typeof at !== 'string') return at\n\t\t\tconst named = ai.view.named(at)\n\t\t\tif (named) return { x: named.x, z: named.z }\n\t\t\tconst region = ai.view.region(at)\n\t\t\t// a circle or a rectangle, both about their middle\n\t\t\tif (region) return { x: region.shape.x, z: region.shape.z }\n\t\t\treturn undefined\n\t\t}\n\t\t/**\n\t\t * The army on the word's task: `plan` says what it does (`undefined`: nothing to do), and puts the squad on it.\n\t\t * The army is a squad of the word's hold (`word:<word>`), so the squads module regroups, focuses, kites and falls\n\t\t * back for it; when the hold lapses, the squad goes and the goals have the army again\n\t\t */\n\t\tconst order = (word: string, data: WordData, plan: (ids: number[]) => { what: string; give: (squad: Squad) => void } | undefined) => {\n\t\t\tconst units = army()\n\t\t\tif (!units.length) {\n\t\t\t\tai.decide(`told \"${word}\", with no army to do it`, { kind: 'word' })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst ids = units.map((unit) => unit.id)\n\t\t\tconst planned = plan(ids)\n\t\t\tif (planned === undefined) return\n\t\t\tconst owner = `word:${word}`\n\t\t\tai.goals.take(ids, 'told', { id: owner, seconds: data.seconds ?? WORD_SECONDS[word] })\n\t\t\tfor (const other of Object.keys(WORD_SECONDS)) if (other !== word) ai.goals.release(`word:${other}`)\n\t\t\tplanned.give(ai.squads.make(WORD_SQUAD, ids, { owner }))\n\t\t\tai.decide(`told \"${word}\": ${planned.what}`, { kind: 'word' })\n\t\t}\n\t\treturn {\n\t\t\tid: 'words',\n\t\t\tphase: 'hear',\n\t\t\tafter: ['rules'],\n\t\t\tthink: () => {\n\t\t\t\tfor (const told of [...ai.told()]) {\n\t\t\t\t\tconst data = (told.data && typeof told.data === 'object' ? told.data : {}) as WordData\n\t\t\t\t\tswitch (told.word) {\n\t\t\t\t\t\tcase 'attack':\n\t\t\t\t\t\t\tai.takeTold('attack')\n\t\t\t\t\t\t\torder('attack', data, (ids) => {\n\t\t\t\t\t\t\t\tconst centre = ai.view.mine.where((unit) => ids.includes(unit.id)).centre()\n\t\t\t\t\t\t\t\tconst target = point(data.at) ?? (centre && ai.view.enemies.known().buildings().nearest(centre)) ?? ai.options.enemyBases?.[0]\n\t\t\t\t\t\t\t\tif (!target) {\n\t\t\t\t\t\t\t\t\tai.decide('told \"attack\", and knows of nowhere to attack', { kind: 'word' })\n\t\t\t\t\t\t\t\t\treturn undefined\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst at = { x: target.x, z: target.z }\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\twhat: `the army of ${ids.length} attacks at (${Math.round(target.x)}, ${Math.round(target.z)})`,\n\t\t\t\t\t\t\t\t\tgive: (squad) => squad.attack(at)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'defend':\n\t\t\t\t\t\t\tai.takeTold('defend')\n\t\t\t\t\t\t\torder('defend', data, (ids) => {\n\t\t\t\t\t\t\t\tconst home = ai.view.home()\n\t\t\t\t\t\t\t\tconst target = point(data.at) ?? (home && { x: home.x, z: home.z })\n\t\t\t\t\t\t\t\tif (!target) return undefined\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\twhat: `the army of ${ids.length} goes to fight at (${Math.round(target.x)}, ${Math.round(target.z)})`,\n\t\t\t\t\t\t\t\t\tgive: (squad) => squad.defend(target)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'retreat':\n\t\t\t\t\t\t\tai.takeTold('retreat')\n\t\t\t\t\t\t\torder('retreat', data, (ids) => {\n\t\t\t\t\t\t\t\tconst home = ai.view.home()\n\t\t\t\t\t\t\t\tif (!home) return undefined\n\t\t\t\t\t\t\t\tconst at = { x: home.x, z: home.z }\n\t\t\t\t\t\t\t\treturn { what: `the army of ${ids.length} comes home`, give: (squad) => squad.retreat(at, 'told to') }\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'hold':\n\t\t\t\t\t\t\tai.takeTold('hold')\n\t\t\t\t\t\t\torder('hold', data, (ids) => {\n\t\t\t\t\t\t\t\treturn { what: `the army of ${ids.length} holds where it stands`, give: (squad) => squad.task('hold', {}) }\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'pause':\n\t\t\t\t\t\t\tai.takeTold('pause')\n\t\t\t\t\t\t\tai.paused = true\n\t\t\t\t\t\t\tai.decide('told \"pause\": sits still until told \"resume\"', { kind: 'word' })\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n","import { footprintOf, type UnitTypeDef } from '#engine/defs'\nimport { cos, sin } from '#engine/exactMath'\nimport { distSq, type Vec2 } from '#engine/math'\nimport { footprintCell } from '#engine/grid'\nimport type { Brain } from '#engine/ai/brain'\nimport { HALL_REACH } from '../reach'\n\n/*\n * Where a building goes (AI plan, B3). The old melee player put everything in rings around home; a tower in the rings\n * is as likely to face the woods as the enemy. A placement strategy is a function that finds a spot for a type near a\n * place: the kit's are named (`nearHome`, `byResource`, `atEdge`, `behind`, `cluster`, `onLayer`), so that a seat's options, a\n * type's declaration (`UnitTypeDef.ai.placement`) and a want can name one as data, and a game writes its own as a\n * function. All of them ask the session whether the spot is free (`view.canPlace`), which says no on ground the\n * player has not explored: a hall by a mine nobody has looked at needs a worker sent to look first (the settler, in\n * the build plan). Every strategy walks the same rings, deterministically, so two thinks of one picture pick alike\n */\n\n/**\n * Where a type is wanted: near a place, no further than `within`, and which of its kind this is (`ordinal`, so that\n * two farms do not try the same corner first)\n *\n * @beta\n */\nexport interface SiteRequest {\n\tnear: Vec2\n\twithin: number\n\tordinal: number\n}\n\n/**\n * A way of finding a spot for a building: the kit's by name, or a function of the game's own. Nothing (`undefined`)\n * when there is no spot it likes\n *\n * @beta\n */\nexport type PlacementStrategy = (ai: Brain, type: UnitTypeDef, site: SiteRequest) => Vec2 | undefined\n\n/**\n * The kit's placement strategies, by name: `nearHome` (rings around the place, keeping the way to the mine clear),\n * `byResource` (on the nearest deposit it is built on: a mine), `atEdge` (at the edge of the base towards the enemy,\n * for a tower), `behind` (away from the enemy, for supply), `cluster` (beside another of its type, barracks by\n * barracks; `cluster:<type>` beside another type), `onLayer:<layer>` (where the whole footprint is on a layer of cells\n * the game paints: `onLayer:blight` for a race that builds on blight)\n *\n * @beta\n */\nexport type PlacementName = 'nearHome' | 'byResource' | 'atEdge' | 'behind' | 'cluster' | `cluster:${string}` | `onLayer:${string}`\n\n/**\n * Which strategy a type goes by (`AiOptions.placement`, `BuildPlanOptions.placement`): by type id or by role, a name\n * or a function\n *\n * @beta\n */\nexport type PlacementTable = Record<string, PlacementName | PlacementStrategy>\n\n/** The angle, as a cosine, within which a spot is \"towards\" the enemy (45°) or \"away\" from them (over 107°) */\nconst TOWARDS = 0.7\nconst AWAY = -0.3\n\n/** Whether a point lies within a distance of the segment from `a` to `b`: the way between a hall and its mine */\nfunction nearSegment(point: Vec2, a: Vec2, b: Vec2, distance: number): boolean {\n\tconst dx = b.x - a.x\n\tconst dz = b.z - a.z\n\tconst length = dx * dx + dz * dz\n\tconst t = length > 0 ? Math.min(Math.max(((point.x - a.x) * dx + (point.z - a.z) * dz) / length, 0), 1) : 0\n\treturn distSq(point, { x: a.x + dx * t, z: a.z + dz * t }) < distance * distance\n}\n\n/** The footprint's longer side: how much room a type takes */\nconst sizeOf = (type: UnitTypeDef) => Math.max(type.footprint?.w ?? 2, type.footprint?.d ?? 2)\n\n/** Whether a type can stand at a point with a little room around it: for the units that will walk past */\nfunction clear(ai: Brain, type: UnitTypeDef, point: Vec2): boolean {\n\tconst { view } = ai\n\tconst gap = 1\n\treturn (\n\t\tview.canPlace(type.id, point) &&\n\t\tview.canPlace(type.id, { x: point.x + gap, z: point.z }) &&\n\t\tview.canPlace(type.id, { x: point.x - gap, z: point.z }) &&\n\t\tview.canPlace(type.id, { x: point.x, z: point.z + gap }) &&\n\t\tview.canPlace(type.id, { x: point.x, z: point.z - gap })\n\t)\n}\n\n/**\n * The rings around a place, walked out from `from` to `within` (then in from `from` to the nearest ring where `inward`),\n * each at so many angles; the first point that stands clear and that `accept` likes. Deterministic, but not the same\n * corner for every building: the angles start where `ordinal` says\n *\n * @beta\n */\nexport function rings(\n\tai: Brain,\n\ttype: UnitTypeDef,\n\tcentre: Vec2,\n\toptions: { from?: number; within: number; ordinal?: number; inward?: boolean; accept?: (point: Vec2) => boolean }\n): Vec2 | undefined {\n\tconst size = sizeOf(type)\n\tconst least = 4 + size\n\tconst from = Math.max(least, options.from ?? least)\n\tconst radii: number[] = []\n\tfor (let radius = from; radius <= options.within; radius += 1.5) radii.push(radius)\n\tif (options.inward) for (let radius = from - 1.5; radius >= least; radius -= 1.5) radii.push(radius)\n\tfor (const radius of radii) {\n\t\tconst steps = Math.round(radius * 1.5)\n\t\tfor (let i = 0; i < steps; i++) {\n\t\t\tconst angle = ((i + (options.ordinal ?? 0) * 3) / steps) * Math.PI * 2\n\t\t\tconst point = { x: Math.round(centre.x + sin(angle) * radius), z: Math.round(centre.z + cos(angle) * radius) }\n\t\t\tif (options.accept && !options.accept(point)) continue\n\t\t\tif (clear(ai, type, point)) return point\n\t\t}\n\t}\n\treturn undefined\n}\n\n/**\n * The way from a place to its mine, to keep clear: the nearest deposit of the money within a hall's reach of it, or\n * the place itself where none is known there (home is the mine itself, for a hall by one not seen yet)\n */\nfunction mineOf(ai: Brain, near: Vec2): Vec2 {\n\tconst { view } = ai\n\tconst known = view.resources.ofResource(ai.purse.money).nearest(near)\n\treturn known && distSq(known, near) < HALL_REACH * HALL_REACH ? known : near\n}\n\n/**\n * Which way the enemy is from a place, as a unit vector: towards the nearest of their bases it knows of, else the\n * nearest base the seat was told of (`AiOptions.enemyBases`), else towards the strongest enemy reaching its own\n * (`threat.hot`). Nothing where it has no idea\n *\n * @beta\n */\nexport function enemyDirection(ai: Brain, from: Vec2): Vec2 | undefined {\n\tlet target: Vec2 | undefined\n\tlet best = Infinity\n\tconst consider = (point: Vec2 | undefined) => {\n\t\tif (!point) return\n\t\tconst d = distSq(point, from)\n\t\tif (d < best && d > 1) {\n\t\t\tbest = d\n\t\t\ttarget = point\n\t\t}\n\t}\n\tif (ai.def.knowledge !== false) for (const base of ai.knowledge.enemy.bases()) if (!base.gone) consider(base.at)\n\tif (!target) for (const base of ai.options.enemyBases ?? []) consider(base)\n\tif (!target) {\n\t\tconst hot = ai.threat.hot()[0]\n\t\tif (hot && hot.enemy > 0) consider(hot.at)\n\t}\n\tif (!target) return undefined\n\tconst length = Math.sqrt(best)\n\treturn { x: (target.x - from.x) / length, z: (target.z - from.z) / length }\n}\n\n/** How far the base around a place reaches: its furthest building from there, at least a few rings out */\nfunction edgeOf(ai: Brain, near: Vec2): number {\n\tlet furthest = 0\n\tfor (const building of ai.view.mine.buildings()) furthest = Math.max(furthest, distSq(building, near))\n\treturn Math.max(8, Math.sqrt(furthest))\n}\n\nconst dot = (a: Vec2, b: Vec2) => a.x * b.x + a.z * b.z\n\n/** The side of a place a point is on, against a direction: the cosine of the angle between them */\nfunction side(point: Vec2, near: Vec2, direction: Vec2): number {\n\tconst dx = point.x - near.x\n\tconst dz = point.z - near.z\n\tconst length = Math.sqrt(dx * dx + dz * dz)\n\treturn length > 0 ? dot({ x: dx / length, z: dz / length }, direction) : 0\n}\n\n/** Rings around the place, the way to the mine kept clear: what the melee player always did */\nconst nearHome: PlacementStrategy = (ai, type, site) => {\n\tconst mine = mineOf(ai, site.near)\n\tconst keep = sizeOf(type) / 2 + 3\n\treturn rings(ai, type, site.near, { within: site.within, ordinal: site.ordinal, accept: (point) => !nearSegment(point, site.near, mine, keep) })\n}\n\n/** On the nearest deposit of what it is built on (a cursed mine on a gold mine), within reach of the place */\nconst byResource: PlacementStrategy = (ai, type, site) => {\n\tif (type.builtOn === undefined) return nearHome(ai, type, site)\n\tconst sources = [...ai.view.resources.ofResource(type.builtOn)].sort((a, b) => distSq(a, site.near) - distSq(b, site.near))\n\tconst reach = Math.max(site.within, HALL_REACH)\n\tconst source = sources.find((each) => distSq(each, site.near) < reach * reach && ai.view.canPlace(type.id, each))\n\treturn source && { x: source.x, z: source.z }\n}\n\n/** At the edge of the base, on the side the enemy comes from: a tower. Rings around home where the enemy is not known */\nconst atEdge: PlacementStrategy = (ai, type, site) => {\n\tconst towards = enemyDirection(ai, site.near)\n\tif (!towards) return nearHome(ai, type, site)\n\tconst mine = mineOf(ai, site.near)\n\tconst keep = sizeOf(type) / 2 + 3\n\tconst edge = edgeOf(ai, site.near)\n\treturn (\n\t\trings(ai, type, site.near, {\n\t\t\tfrom: edge,\n\t\t\twithin: Math.max(site.within, edge + 3),\n\t\t\tordinal: site.ordinal,\n\t\t\tinward: true,\n\t\t\taccept: (point) => side(point, site.near, towards) >= TOWARDS && !nearSegment(point, site.near, mine, keep)\n\t\t}) ?? nearHome(ai, type, site)\n\t)\n}\n\n/** Away from the enemy, behind the hall: supply, where a raid reaches it last. Rings around home where the enemy is not known */\nconst behind: PlacementStrategy = (ai, type, site) => {\n\tconst towards = enemyDirection(ai, site.near)\n\tif (!towards) return nearHome(ai, type, site)\n\tconst mine = mineOf(ai, site.near)\n\tconst keep = sizeOf(type) / 2 + 3\n\treturn (\n\t\trings(ai, type, site.near, {\n\t\t\twithin: site.within,\n\t\t\tordinal: site.ordinal,\n\t\t\taccept: (point) => side(point, site.near, towards) <= AWAY && !nearSegment(point, site.near, mine, keep)\n\t\t}) ?? nearHome(ai, type, site)\n\t)\n}\n\n/** Beside another of a type (its own when none is named): barracks by barracks. Rings around home where there is none yet */\nconst cluster =\n\t(type?: string): PlacementStrategy =>\n\t(ai, def, site) => {\n\t\tconst with_ = ai.view.mine\n\t\t\t.ofType(type ?? def.id)\n\t\t\t.finished()\n\t\t\t.nearest(site.near)\n\t\tif (!with_ || distSq(with_, site.near) > site.within * site.within * 4) return nearHome(ai, def, site)\n\t\tconst mine = mineOf(ai, site.near)\n\t\tconst keep = sizeOf(def) / 2 + 3\n\t\treturn (\n\t\t\trings(ai, def, with_, {\n\t\t\t\tfrom: sizeOf(def) + 2,\n\t\t\t\twithin: 10 + sizeOf(def),\n\t\t\t\tordinal: site.ordinal,\n\t\t\t\taccept: (point) => !nearSegment(point, site.near, mine, keep)\n\t\t\t}) ?? nearHome(ai, def, site)\n\t\t)\n\t}\n\n/** How many of a layer's painted cells nearest the place are tried when the rings find nothing on it */\nconst PAINTED_TRIED = 256\n\n/** Whether the whole footprint of a type at a point is on a layer: its middle and its four corners, a little inset */\nfunction onLayerAt(ai: Brain, layer: string, type: UnitTypeDef, point: Vec2): boolean {\n\tconst { w, d } = footprintOf(type)\n\tconst cell = footprintCell(point.x, point.z, w, d)\n\tconst inset = 0.5\n\tconst x0 = cell.x + inset\n\tconst x1 = cell.x + w - inset\n\tconst z0 = cell.z + inset\n\tconst z1 = cell.z + d - inset\n\tconst { view } = ai\n\treturn (\n\t\tview.cellAt(layer, cell.x + w / 2, cell.z + d / 2) > 0 &&\n\t\tview.cellAt(layer, x0, z0) > 0 &&\n\t\tview.cellAt(layer, x1, z0) > 0 &&\n\t\tview.cellAt(layer, x0, z1) > 0 &&\n\t\tview.cellAt(layer, x1, z1) > 0\n\t)\n}\n\n/**\n * On a layer of cells, the whole footprint (`onLayer:<layer>`): the rings around the place, the way to the mine kept\n * clear, then the layer's painted cells nearest the place where the rings find none (a scan of the layer, only then).\n * Nothing where the layer is painted nowhere near\n */\nconst onLayer =\n\t(layer: string): PlacementStrategy =>\n\t(ai, type, site) => {\n\t\tconst mine = mineOf(ai, site.near)\n\t\tconst keep = sizeOf(type) / 2 + 3\n\t\tconst found = rings(ai, type, site.near, {\n\t\t\twithin: site.within,\n\t\t\tordinal: site.ordinal,\n\t\t\taccept: (point) => onLayerAt(ai, layer, type, point) && !nearSegment(point, site.near, mine, keep)\n\t\t})\n\t\tif (found) return found\n\t\tconst cells = ai.view.cells(layer)\n\t\tif (!cells) return undefined\n\t\tconst width = ai.session.terrain.width\n\t\tconst painted: { point: Vec2; d: number }[] = []\n\t\tfor (let i = 0; i < cells.length; i++) {\n\t\t\tif (cells[i] === 0) continue\n\t\t\tconst point = { x: i % width, z: Math.floor(i / width) }\n\t\t\tpainted.push({ point, d: distSq(point, site.near) })\n\t\t}\n\t\tpainted.sort((a, b) => a.d - b.d || a.point.z - b.point.z || a.point.x - b.point.x)\n\t\tfor (const { point } of painted.slice(0, PAINTED_TRIED)) {\n\t\t\tif (onLayerAt(ai, layer, type, point) && !nearSegment(point, site.near, mine, keep) && clear(ai, type, point)) return point\n\t\t}\n\t\treturn undefined\n\t}\n\n/**\n * The kit's placement strategies, by name (`PlacementName`), for a game that wants to call or wrap one\n *\n * @beta\n */\nexport const placements = { nearHome, byResource, atEdge, behind, cluster, onLayer } as const\n\n/**\n * A strategy by name: `cluster:<type>` clusters with another type, `onLayer:<layer>` keeps to a layer of cells; a name\n * the kit does not know is `nearHome`\n *\n * @internal\n */\nexport function placementNamed(name: PlacementName | string): PlacementStrategy {\n\tif (name.startsWith('cluster:')) return cluster(name.slice('cluster:'.length))\n\tif (name.startsWith('onLayer:')) return onLayer(name.slice('onLayer:'.length))\n\tswitch (name) {\n\t\tcase 'byResource':\n\t\t\treturn byResource\n\t\tcase 'atEdge':\n\t\t\treturn atEdge\n\t\tcase 'behind':\n\t\t\treturn behind\n\t\tcase 'cluster':\n\t\t\treturn cluster()\n\t\tdefault:\n\t\t\treturn nearHome\n\t}\n}\n\n/**\n * The strategy a role goes by where nothing else says: a tower at the edge, supply behind, what is built on a deposit by it\n *\n * @internal\n */\nexport const DEFAULT_PLACEMENT: Readonly<Record<string, PlacementName>> = { tower: 'atEdge', supply: 'behind', topper: 'byResource' }\n","import { type UnitTypeDef, upgradesOf } from '#engine/defs'\nimport { availableToPlayer } from '#engine/shared'\nimport type { AiView } from '#engine/ai/view'\n\n/*\n * The tech path (AI plan, B3): how a computer player gets from what it has to what it wants. \"I want gryphons\" is,\n * to the definitions, \"gryphons are trained at an aviary, which needs a keep and a lumber mill; a keep is what a town\n * hall turns into\". Nothing here knows those names: it reads `requires` (what must stand finished), `trains` and\n * `builds` (who makes what), `upgradesTo` (what turns into what, one or several) and `provides` (what counts as what: a keep is a town\n * hall too) and walks them back from the wanted type to the player's tech, giving the steps in the order they can be\n * taken. `requires` is a list that must all hold; there is no \"either\" form. A cycle in a game's definitions (a\n * building that requires what it provides) is refused with a message naming it, rather than walked for ever\n */\n\n/**\n * One step towards a type: a building to build (by a worker), a building to turn another into (`morph`, from the\n * type that turns into it), or a unit to train (at the type that trains it). `for` is what the step is on the way to\n *\n * @beta\n */\nexport interface TechStep {\n\ttype: string\n\thow: 'build' | 'morph' | 'train'\n\t/** For a `morph`, the type that turns into it; for a `train`, the type that trains it; for a `build`, the type that builds it */\n\tfrom: string\n\tfor: string\n}\n\n/**\n * The steps from what the player has to being able to make a type (`techPath`): the prerequisites, the producer, in\n * the order they can be taken; the type itself is not among them. `cycle` names the definitions that go round in a\n * circle where they do, `impossible` the type nothing of the player's can make, and the steps are then as far as the\n * walk got\n *\n * @beta\n */\nexport interface TechPath {\n\tsteps: TechStep[]\n\tcycle?: string[]\n\timpossible?: string\n}\n\n/**\n * How a type is made, by the player's definitions: built by a worker type, turned into from another type, or trained\n * at a building type; nothing for a type nothing of the player's race makes (a creep's hut). Of the makers, one the\n * player has first, then the first in the game's order\n *\n * @internal\n */\nexport function makerOf(view: AiView, type: string): Pick<TechStep, 'how' | 'from'> | undefined {\n\tconst { registry, me } = view\n\tif (!registry.units.has(type)) return undefined\n\tconst def = registry.unit(type)\n\tconst may = (maker: UnitTypeDef) => availableToPlayer(maker, { race: me.race, availability: me.availability }, maker.id)\n\tconst owned = (maker: UnitTypeDef) => view.mine.ofType(maker.id).length > 0\n\tconst pick = (makers: UnitTypeDef[]) => makers.find(owned) ?? makers[0]\n\tconst all = registry.units.all().filter(may)\n\tif (def.kind === 'building') {\n\t\tconst builders = all.filter((maker) => maker.kind === 'unit' && maker.builds?.includes(type))\n\t\tif (builders.length) return { how: 'build', from: pick(builders).id }\n\t\tconst befores = all.filter((maker) => upgradesOf(maker).includes(type))\n\t\tif (befores.length) return { how: 'morph', from: pick(befores).id }\n\t\treturn undefined\n\t}\n\tif (def.kind === 'unit') {\n\t\tconst trainers = all.filter((maker) => maker.kind === 'building' && maker.trains?.includes(type))\n\t\tif (trainers.length) return { how: 'train', from: pick(trainers).id }\n\t}\n\treturn undefined\n}\n\n/**\n * The steps from what the player has to being able to make a type: what it requires that it lacks, each of those in\n * turn, and the type's maker where it has none (the hall that trains the worker, the worker that builds the barracks,\n * the hall that turns into the keep). What stands finished (`view.me.tech`, with what it counts as) or is on its way\n * (`onItsWay`: under construction, a builder sent, a morph queued) is had already. A requirement no type has as its\n * id is met by a type that provides it\n *\n * @beta\n */\nexport function techPath(view: AiView, target: string, onItsWay: (type: string) => boolean = () => false): TechPath {\n\tconst { registry, me } = view\n\tconst steps: TechStep[] = []\n\tconst planned = new Set<string>()\n\tconst visiting = new Set<string>()\n\tconst path: TechPath = { steps }\n\tconst may = (def: UnitTypeDef) => availableToPlayer(def, { race: me.race, availability: me.availability }, def.id)\n\tconst have = (id: string) => me.tech.includes(id) || view.mine.ofType(id).length > 0 || onItsWay(id)\n\t/** Whether a requirement is met, or will be by a step planned already (a planned keep provides the town hall) */\n\tconst covered = (id: string) =>\n\t\thave(id) || planned.has(id) || [...planned].some((type) => registry.units.has(type) && registry.unit(type).provides?.includes(id))\n\n\t/** What is to be made for a requirement: the type itself, or the first type the player may make that provides it */\n\tconst typeFor = (id: string): string | undefined => {\n\t\tif (registry.units.has(id) && makerOf(view, id)) return id\n\t\tconst provider = registry.units.all().find((def) => may(def) && def.provides?.includes(id) && makerOf(view, def.id))\n\t\treturn provider?.id\n\t}\n\n\tconst need = (id: string, forWhat: string): boolean => {\n\t\tif (covered(id)) return true\n\t\tconst type = typeFor(id)\n\t\tif (type === undefined) {\n\t\t\tpath.impossible = id\n\t\t\treturn false\n\t\t}\n\t\tif (type !== id && covered(type)) return true\n\t\tif (visiting.has(type)) {\n\t\t\tpath.cycle = [...visiting, type]\n\t\t\treturn false\n\t\t}\n\t\tvisiting.add(type)\n\t\tconst def = registry.unit(type)\n\t\tfor (const required of def.requires ?? []) if (!need(required, type)) return false\n\t\tconst maker = makerOf(view, type)!\n\t\t// a morph turns what the player has (or will have) into it; a build needs a builder; a train a trainer\n\t\tif (!have(maker.from) && !need(maker.from, type)) return false\n\t\tvisiting.delete(type)\n\t\tplanned.add(type)\n\t\tsteps.push({ type, ...maker, for: forWhat })\n\t\treturn true\n\t}\n\n\tif (!registry.units.has(target)) {\n\t\tpath.impossible = target\n\t\treturn path\n\t}\n\tconst def = registry.unit(target)\n\tfor (const required of def.requires ?? []) if (!need(required, target)) return path\n\tconst maker = makerOf(view, target)\n\tif (!maker) {\n\t\tpath.impossible = target\n\t\treturn path\n\t}\n\tif (!have(maker.from)) need(maker.from, target)\n\treturn path\n}\n\n/**\n * A tech path's trouble in words, for the report and the log: nothing for a path with none\n *\n * @internal\n */\nexport function techTrouble(path: TechPath): string | undefined {\n\tif (path.cycle)\n\t\treturn `each needs another it does not have, so nothing can start it: ${path.cycle.join(' → ')} (a game whose definitions go round like this needs one of them to start with; a player that lost them all cannot make them again)`\n\tif (path.impossible !== undefined) return `nothing of its own makes ${path.impossible}`\n\treturn undefined\n}\n","/**\n * The small words of the AI kit (design review B13): a point as plain data, as a pair for a report, as a decision\n * writes it, and the counts and articles of a decision's line. One copy, for every module and area\n */\nimport type { Vec2 } from '#engine/math'\n\n/**\n * A point as plain data, for a save or a task's data: `{ x, z }` and nothing else\n *\n * @beta\n */\nexport const point = (at: Vec2): Vec2 => ({ x: at.x, z: at.z })\n\n/**\n * A point as a report has it: `[x, z]`, rounded\n *\n * @beta\n */\nexport const pair = (at: Vec2): [number, number] => [Math.round(at.x), Math.round(at.z)]\n\n/**\n * A point as a decision writes it: `(40, 60)`\n *\n * @beta\n */\nexport const where = (at: Vec2) => `(${Math.round(at.x)}, ${Math.round(at.z)})`\n\n/**\n * Units counted as a decision writes them: `1 unit`, `3 units`\n *\n * @beta\n */\nexport const plural = (n: number) => (n === 1 ? '1 unit' : `${n} units`)\n\n/**\n * A thing as a decision writes it, with its article: `a farm`, `an altar`\n *\n * @beta\n */\nexport const an = (thing: string) => `${/^[aeiou]/i.test(thing) ? 'an' : 'a'} ${thing}`\n","import { baseStats, type Cost, type UnitTypeDef } from '#engine/defs'\nimport { queueOf, upgradeOf } from '#engine/systems/productionQueue'\nimport { builtSoFar } from '#engine/systems/construction'\nimport { snapshotOf } from '#engine/components'\nimport { distSq, type Vec2 } from '#engine/math'\nimport { gathering } from '#engine/orders/harvest'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModule, type AiModuleDef, defineModule } from '#engine/ai/module'\nimport { type AiCondition, type AiConditionData, evaluate } from '#engine/ai/rules'\nimport { DEFAULT_PLACEMENT, type PlacementName, placementNamed, type PlacementStrategy, type PlacementTable, type SiteRequest } from './placement'\nimport { makerOf, techPath, type TechPath, type TechStep, techTrouble } from './tech'\nimport { an, where } from '../geometry'\n\n/*\n * The build plan (AI plan, B3): what a computer player builds, and how it gets there. The old melee player had a fixed\n * ladder (hall, farm, barracks, altar, …) and no way to say \"I want gryphons\" and have the computer work out that\n * gryphons need an aviary, which needs a keep and a lumber mill. The plan takes **wants** instead: \"two of this type,\n * near there, when that holds, this important\" (`Want`), from the build order, from the production plan (a unit it\n * wants that nothing of its trains yet), from the economy (another hall, a tower), from goals and from rules. Each\n * think it works out, for every want it has not met, the **steps** to it through the tech tree (`techPath`: what to\n * build, what to turn into what, what to train), takes the wants most important first, and for each acts on the first\n * step it can: finds a spot (`placement.ts`), a builder, pays out of the **purse** (`purse.ts`, the one ledger) and\n * sends the order. What it cannot pay for, it **saves** for: the most important want it cannot afford holds the money\n * in the purse, so that nothing cheaper spends it (as a person saves for a hall and lets the footmen wait). A want\n * with a place where no spot is known (a hall by a mine nobody has looked at) sends a worker to look first: the\n * settler. What is on its way (a builder sent, a site half built, a morph queued) counts as had, so the same want is\n * not acted on twice; a building lost makes a standing want short again, and it is built anew (`rebuild`).\n *\n * The plan is the brain's (`ai.plans.build`): every module adds wants to the same one, and the report shows each want\n * with what it waits for and what it holds. The `build()` module runs it in its place among a brain's modules; the\n * melee player runs it in its own\n */\n\n/**\n * Something a computer player wants built or trained, as plain data (a map's file, a rule's action, a seat's\n * options): a type, how many, under what condition, where, how important. `WantData` is what a save keeps; `Want`\n * is the same with the function forms\n *\n * @beta\n */\nexport interface WantData {\n\t/** Its name: what the memory, the report and `drop` know it by. Made up when left out */\n\tid?: string\n\t/** The unit type wanted: a building, or a unit (whose buildings the plan puts up; the production plan trains it) */\n\ttype: string\n\t/** How many of it to have, those on their way counted: 1 when left out */\n\tcount?: number\n\t/** Only while this holds (`AiConditionData`, as a rule's): a tower after the first attack, a second hall past five minutes */\n\twhen?: AiConditionData\n\t/** Where: a point, or the name of an entity the map or rules named. Home when left out */\n\tnear?: Vec2 | string\n\t/** How far from there at the most: 22 when left out */\n\twithin?: number\n\t/** How its spot is chosen (`PlacementName`): what the type declares, the brain's table, or the role's default when left out */\n\tplacement?: PlacementName\n\t/** Wants are taken most important first, and the most important one that cannot be paid for saves up: 0 when left out */\n\tpriority?: number\n\t/** Money to have left over after paying for it: a luxury that waits for gold to spare. 0 when left out */\n\tspare?: number\n\t/**\n\t * Whether the want stands: kept once met, and short again when what it made is lost, so that it is built anew.\n\t * Wants of a brain's or a seat's options stand; one added as the game goes is dropped once met, unless it says so\n\t */\n\tkeep?: boolean\n\t/** For a standing want: whether a building lost is built again (the plan's `rebuild` when left out) */\n\trebuild?: boolean\n\t/** Seconds without a spot for it before a want that does not stand is given up: the plan's `siteTimeout` when left out */\n\tsiteTimeout?: number\n\t/** Who wants it, for the report: `order`, `production`, `economy`, a goal's or a rule's id */\n\tby?: string\n}\n\n/**\n * A want with the function forms: how many as a function of the brain, a condition as code, a place found each think,\n * a placement strategy of the game's own (`ai.plans.want`, `BuildPlanOptions.wants`)\n *\n * @beta\n */\nexport interface Want extends Omit<WantData, 'count' | 'when' | 'near' | 'placement'> {\n\tcount?: number | ((ai: Brain) => number)\n\twhen?: AiCondition\n\tnear?: Vec2 | string | ((ai: Brain) => Vec2 | undefined)\n\tplacement?: PlacementName | PlacementStrategy\n}\n\n/**\n * How the build plan goes about it (`BrainDef.plans.build`, the `build()` module; the data of it in `AiOptions`)\n *\n * @beta\n */\nexport interface BuildPlanOptions {\n\t/** Standing wants: what the brain always has, built anew when lost */\n\twants?: Want[]\n\t/** How each type's spot is chosen, by type id or by role: a name or a function. What a type declares (`UnitTypeDef.ai.placement`) goes over it */\n\tplacement?: PlacementTable\n\t/** Whether a building lost is built again, for standing wants that do not say: yes when left out */\n\trebuild?: boolean\n\t/** Whether a worker is sent to mend a damaged building when no enemy reaches it: yes when left out */\n\trepair?: boolean\n\t/** Seconds without a spot before a want that does not stand is given up: 60 when left out */\n\tsiteTimeout?: number\n\t/** How far from home a building goes at the most, where a want does not say: 22 when left out */\n\twithin?: number\n}\n\n/** What the plan remembers of a want between thinks */\ninterface WantMemory {\n\t/** The tick it was added at */\n\tsince: number\n\t/** Its place among the wants: among equals in priority, the first added goes first. Kept, so a loaded game ranks alike */\n\torder: number\n\t/** How many of its type the plan started for it */\n\tmade: number\n\t/** A standing want met once and not to be built anew */\n\tsatisfied?: true\n\t/** The tick since which no spot was found for it */\n\tnoSite?: number\n\t/** The worker sent to look at the ground where it goes */\n\tsettler?: number\n}\n\n/**\n * What the build plan remembers between thinks, for a save: each want's memory, and the wants added as the game went\n * that are plain data (a rule's), to have them again\n *\n * @beta\n */\nexport interface BuildPlanMemory {\n\tv: 1\n\twants: { id: string; memory: WantMemory; data?: WantData }[]\n\t/** The order the next want added gets: kept, so that a loaded game ranks the wants it adds as the game saved did */\n\tadded?: number\n\t/** The want saving up as of the last think (`savingFor`): what a loaded game reads until it thinks again */\n\tsaving?: string\n}\n\n/**\n * One want as the report shows it: what it is, how far along, what it waits for (`status`), the steps to it, what it\n * holds in the purse\n *\n * @beta\n */\nexport interface WantReport {\n\tid: string\n\ttype: string\n\tcount: number\n\thave: number\n\tonItsWay: number\n\tpriority: number\n\tby?: string\n\tkeep?: true\n\tstatus: string\n\tsteps: string[]\n\tholds?: Cost\n}\n\n/**\n * The build plan as the report shows it: its wants, and which one saves up\n *\n * @beta\n */\nexport interface BuildPlanReport {\n\twants: WantReport[]\n\tsaving?: string\n}\n\n/** A want as the plan keeps it: its definition, its memory, and what the last think made of it */\ninterface Live {\n\tid: string\n\tdef: Want\n\tmemory: WantMemory\n\tcount: number\n\thave: number\n\tonItsWay: number\n\tstatus: string\n\tsteps: string[]\n\tholds?: Cost\n}\n\n/** How far from a mine, towards home, a settler is sent to see where the hall by it would go */\nconst SETTLE_FROM = 10\nconst WITHIN = 22\nconst SITE_TIMEOUT = 60\n/** Under this part of its health a building is mended */\nconst MEND_UNDER = 0.9\n\n/** A step in words, for the report: `build lumbermill`, `townhall → keep`, `train peasant` */\nconst stepWords = (step: Pick<TechStep, 'type' | 'how' | 'from'>) =>\n\tstep.how === 'morph' ? `${step.from} → ${step.type}` : `${step.how} ${step.type}`\n\n/** Whether a want is plain data all through: what a save can keep */\nconst isData = (def: Want): def is Want & WantData =>\n\ttypeof def.count !== 'function' && typeof def.when !== 'function' && typeof def.near !== 'function' && typeof def.placement !== 'function'\n\n/**\n * The brain's build plan (`ai.plans.build`): its wants, the steps to each, the spots, the builders, the purse. Add a\n * want with `want`, read where each stands with `report`, and let `think` act on them once a think\n *\n * @beta\n */\nexport class BuildPlan {\n\tprivate options: BuildPlanOptions = {}\n\tprivate readonly wants = new Map<string, Live>()\n\t/** Memory of wants a save remembers that no module has asked for yet: given to them as they come */\n\tprivate pending: Record<string, WantMemory> = {}\n\tprivate added = 0\n\tprivate thoughtAt = -1\n\tprivate paths = new Map<string, TechPath>()\n\t/** What is on its way, by type, worked out once a think: asked for every want and every step */\n\tprivate onWay = new Map<string, number>()\n\t/** The builders sent this think: not sent twice */\n\tprivate sent = new Set<number>()\n\t/** The want saving up this think, if one is */\n\tprivate saving: string | undefined\n\tprivate warned = new Set<string>()\n\n\tconstructor(\n\t\t/** The brain it plans for */\n\t\treadonly ai: Brain,\n\t\toptions: BuildPlanOptions = {}\n\t) {\n\t\tthis.configure(options)\n\t}\n\n\t/** Takes options in, over what it had: the standing wants added, the table of placements merged, the flags replaced */\n\tconfigure(options: BuildPlanOptions): void {\n\t\tthis.options = {\n\t\t\t...this.options,\n\t\t\t...options,\n\t\t\tplacement: { ...this.options.placement, ...options.placement }\n\t\t}\n\t\tfor (const def of options.wants ?? []) this.want({ ...def, keep: true })\n\t}\n\n\t/** The plan's options as they stand */\n\tget settings(): Readonly<BuildPlanOptions> {\n\t\treturn this.options\n\t}\n\n\t/**\n\t * Adds a want, or replaces one of the same id (its memory kept): what the plan works towards from now. Gives back\n\t * its id. A want with no `keep` is dropped once met\n\t */\n\twant(def: Want): string {\n\t\tif (!def.type) throw new Error('A want needs a type')\n\t\tconst id = def.id ?? `${def.type}#${++this.added}`\n\t\tconst live = this.wants.get(id)\n\t\tif (live) {\n\t\t\tlive.def = { ...def, id }\n\t\t\treturn id\n\t\t}\n\t\tconst memory = this.pending[id] ?? { since: this.ai.tick, order: this.added, made: 0 }\n\t\tdelete this.pending[id]\n\t\t// past every order given: a want remembered by a save comes back with its own, and moves nothing on\n\t\tthis.added = Math.max(this.added, memory.order + 1)\n\t\tthis.wants.set(id, { id, def: { ...def, id }, memory, count: 0, have: 0, onItsWay: 0, status: 'new', steps: [] })\n\t\treturn id\n\t}\n\n\t/** Takes a want out, and what a save remembered of it: whether there was one */\n\tdrop(id: string): boolean {\n\t\tconst remembered = id in this.pending\n\t\tdelete this.pending[id]\n\t\treturn this.wants.delete(id) || remembered\n\t}\n\n\t/** A want by id */\n\tget(id: string): Want | undefined {\n\t\treturn this.wants.get(id)?.def\n\t}\n\n\t/** The wants, in the order added */\n\tlist(): Want[] {\n\t\treturn this.ordered().map((live) => live.def)\n\t}\n\n\t/** Where a want stands, in words, as of the last think: `building a barracks at (40, 60)`, `saving for a town hall` */\n\tstatus(id: string): string | undefined {\n\t\treturn this.wants.get(id)?.status\n\t}\n\n\t/** The want saving up, as of the last think: the most important one it could not pay for */\n\tget savingFor(): string | undefined {\n\t\treturn this.saving\n\t}\n\n\t/** How many of a type the player has, those under construction and those that count as it included */\n\thave(type: string): number {\n\t\treturn this.ai.view.mine.ofType(type).length\n\t}\n\n\t/** How many of a type are on their way beyond those that stand: builders sent to build one, buildings turning into one, units queued */\n\tonItsWay(type: string): number {\n\t\tconst known = this.onWay.get(type)\n\t\tif (known !== undefined) return known\n\t\tlet count = 0\n\t\tfor (const entity of this.ai.view.mine) {\n\t\t\tconst own = entity.own\n\t\t\tif (!own) continue\n\t\t\tif (own.order === 'build' && own.build === type) count++\n\t\t\telse if (upgradeOf(entity)?.to === type) count++\n\t\t\tfor (const item of queueOf(entity)) if ((item.kind === 'morph' || item.kind === 'unit') && item.id === type) count++\n\t\t}\n\t\tthis.onWay.set(type, count)\n\t\treturn count\n\t}\n\n\t/** Whether a type is had or on its way: standing (finished or not), or a builder or a morph on the way to it */\n\tprivate had(type: string): boolean {\n\t\treturn this.ai.view.me.tech.includes(type) || this.have(type) > 0 || this.onItsWay(type) > 0\n\t}\n\n\t/** The steps to being able to make a type (`techPath`), worked out once a think */\n\tpath(type: string): TechPath {\n\t\tlet found = this.paths.get(type)\n\t\tif (!found) this.paths.set(type, (found = techPath(this.ai.view, type, (step) => this.onItsWay(step) > 0)))\n\t\treturn found\n\t}\n\n\t/** The first step towards a type not had yet, the type's own last: none when nothing is to be done, or the path is blocked */\n\tnext(type: string): TechStep | undefined {\n\t\tconst path = this.path(type)\n\t\tif (techTrouble(path)) return undefined\n\t\tfor (const step of path.steps) if (!this.had(step.type)) return step\n\t\tconst maker = makerOf(this.ai.view, type)\n\t\treturn maker && { type, ...maker, for: type }\n\t}\n\n\t/**\n\t * The think, once a think: every want measured against what stands and is on its way (met ones dropped, or kept\n\t * standing), those whose condition holds taken most important first, each advanced by the first step it can take:\n\t * built, turned into, or saved for. Then the mending, where the plan is to\n\t */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tif (this.thoughtAt === ai.tick) return\n\t\tthis.thoughtAt = ai.tick\n\t\tthis.paths.clear()\n\t\tthis.onWay.clear()\n\t\tthis.sent.clear()\n\t\tthis.saving = undefined\n\t\t// the game's build order, where there is one: its next item is a want before all others, and the only one\n\t\t// advanced while the order is followed\n\t\tconst following = ai.plans.follow() !== undefined\n\t\tconst active: Live[] = []\n\t\tfor (const [id, live] of this.wants) {\n\t\t\tconst { def } = live\n\t\t\tlive.steps = []\n\t\t\tlive.holds = undefined\n\t\t\tlive.count = typeof def.count === 'function' ? def.count(ai) : (def.count ?? 1)\n\t\t\tlive.have = this.have(def.type)\n\t\t\tlive.onItsWay = this.onItsWay(def.type)\n\t\t\tif (live.have + live.onItsWay >= live.count) {\n\t\t\t\tlive.status = 'met'\n\t\t\t\tif (!def.keep) {\n\t\t\t\t\tthis.wants.delete(id)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (!(def.rebuild ?? this.options.rebuild ?? true)) live.memory.satisfied = true\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (live.memory.satisfied) {\n\t\t\t\tlive.status = 'met once, not built anew'\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (def.when && !evaluate(def.when, ai)) {\n\t\t\t\tlive.status = 'waits for its condition'\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (following && id !== 'order') {\n\t\t\t\tlive.status = 'waits for the build order'\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tactive.push(live)\n\t\t}\n\t\tactive.sort((a, b) => (b.def.priority ?? 0) - (a.def.priority ?? 0) || a.memory.order - b.memory.order)\n\t\tfor (const live of active) this.advance(live)\n\t\tif (this.options.repair ?? true) this.mend()\n\t}\n\n\t/** One want, one think: the steps to it, and the first one it can take */\n\tprivate advance(live: Live): void {\n\t\tconst { ai } = this\n\t\tconst { def } = live\n\t\tconst path = this.path(def.type)\n\t\tconst trouble = techTrouble(path)\n\t\tif (trouble) {\n\t\t\tlive.status = `blocked: ${trouble}`\n\t\t\tif (!this.warned.has(def.type)) {\n\t\t\t\tthis.warned.add(def.type)\n\t\t\t\tai.log.warn('ai', `the build plan cannot get to ${def.type}: ${trouble}`, { want: live.id })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tconst own = makerOf(ai.view, def.type)\n\t\tconst steps: TechStep[] = [...path.steps, ...(own ? [{ type: def.type, ...own, for: def.type }] : [])]\n\t\tlive.steps = steps.map(stepWords)\n\t\tlet status: string | undefined\n\t\tfor (const step of steps) {\n\t\t\tconst last = step.type === def.type\n\t\t\t// a prerequisite had, or on its way, is waited for by what comes after it\n\t\t\tif (!last && this.had(step.type)) {\n\t\t\t\tif (!ai.view.me.tech.includes(step.type)) status ??= `waits for ${an(step.type)} to finish`\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst outcome = this.act(step, live, last)\n\t\t\tstatus ??= outcome\n\t\t\t// the step was taken, or could not be: what depends on it waits either way; what does not may still go\n\t\t}\n\t\tlive.status = status ?? 'nothing to do'\n\t}\n\n\t/** Takes a step for a want, where it can: what came of it, in words, for the status */\n\tprivate act(step: TechStep, live: Live, last: boolean): string {\n\t\tconst { ai } = this\n\t\tconst { view, registry } = ai\n\t\tconst { def } = live\n\t\tconst type = registry.unit(step.type)\n\t\tswitch (step.how) {\n\t\t\tcase 'train':\n\t\t\t\treturn last ? `to be trained` : `needs ${an(step.type)}`\n\t\t\tcase 'morph': {\n\t\t\t\tconst from = view.mine\n\t\t\t\t\t.where((entity) => entity.type === step.from && builtSoFar(entity) === undefined && !upgradeOf(entity)?.to && !queueOf(entity).length)\n\t\t\t\t\t.first()\n\t\t\t\tif (!from) return `waits for ${an(step.from)} with nothing to do, to turn into ${an(step.type)}`\n\t\t\t\tif (!view.has(type.requires)) return `waits for what ${an(step.type)} requires`\n\t\t\t\tif (!this.pay(live, type.cost)) return this.short(live, step.type)\n\t\t\t\tai.send({ type: 'upgradeBuilding', building: from.id, into: step.type })\n\t\t\t\tif (last) live.memory.made++\n\t\t\t\tai.decide(`turns its ${step.from} into ${an(step.type)}${def.by ? `, for ${def.by}` : ''}`, { kind: 'build' })\n\t\t\t\treturn `turning ${an(step.from)} into ${an(step.type)}`\n\t\t\t}\n\t\t\tcase 'build': {\n\t\t\t\tif (!view.has(type.requires)) return `waits for what ${an(step.type)} requires`\n\t\t\t\t// a place nobody has looked at: a worker goes to see it now, money or no money, so that the ground is known\n\t\t\t\t// by the time the money is there (the want still saves meanwhile)\n\t\t\t\tconst place = last ? this.placeOf(live) : undefined\n\t\t\t\tif (place && ai.def.knowledge !== false && !ai.knowledge.map.explored(this.settlePoint(place))) {\n\t\t\t\t\tthis.sendSettler(live, place)\n\t\t\t\t\tthis.canPay(live, type.cost)\n\t\t\t\t\treturn `no ground known at ${where(place)}, a worker sent to look`\n\t\t\t\t}\n\t\t\t\t// the money before the spot: looking for one asks the ground many times, and a step that cannot be paid for need not\n\t\t\t\tif (!this.canPay(live, type.cost)) return this.short(live, step.type)\n\t\t\t\tconst site = this.siteFor(type, last ? live : undefined)\n\t\t\t\tif (!site) {\n\t\t\t\t\tif (last && this.noSite(live)) return `gave up: no spot for ${an(step.type)}`\n\t\t\t\t\treturn `no spot for ${an(step.type)}${last && live.memory.settler ? ', a worker sent to look' : ''}`\n\t\t\t\t}\n\t\t\t\tlive.memory.noSite = undefined\n\t\t\t\tconst builder = this.builderFor(type, site)\n\t\t\t\tif (!builder) return `no builder for ${an(step.type)}`\n\t\t\t\tthis.ai.purse.spend(type.cost, def.priority ?? 0)\n\t\t\t\tthis.sent.add(builder.id)\n\t\t\t\tai.send({ type: 'order', entities: [builder.id], order: { type: 'build', unitType: step.type, point: site } })\n\t\t\t\tif (last) live.memory.made++\n\t\t\t\tai.decide(`builds ${an(step.type)} at ${where(site)}${def.by ? `, for ${def.by}` : ''}${last ? '' : `, on the way to ${def.type}`}`, {\n\t\t\t\t\tkind: 'build'\n\t\t\t\t})\n\t\t\t\treturn `building ${an(step.type)} at ${where(site)}`\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Pays for a step out of the purse, with the want's `spare` left over, as important as the want is (what less\n\t * important wants and modules hold is its to spend); where it cannot, the most important want that could not pay\n\t * holds the money (one at a time), and what is less important waits\n\t */\n\tprivate pay(live: Live, cost: Cost | undefined): boolean {\n\t\tif (!this.canPay(live, cost)) return false\n\t\tthis.ai.purse.spend(cost, live.def.priority ?? 0)\n\t\treturn true\n\t}\n\n\t/** Whether a want can pay for a step now (nothing spent); where it cannot, it may hold the money (`pay`) */\n\tprivate canPay(live: Live, cost: Cost | undefined): boolean {\n\t\tconst { purse } = this.ai\n\t\tconst priority = live.def.priority ?? 0\n\t\tif (purse.affords(cost, live.def.spare ?? 0, priority)) return true\n\t\t// a luxury (one with money to spare asked) never saves: it buys when there is spare, and that is all\n\t\tif (this.saving === undefined && cost && !live.def.spare) {\n\t\t\tthis.saving = live.id\n\t\t\tpurse.reserve(live.id, cost, priority)\n\t\t\tlive.holds = { ...cost }\n\t\t}\n\t\treturn false\n\t}\n\n\t/** A step not paid for, in words: the want holds the money (saving), waits for money to spare (a luxury), or waits for the money */\n\tprivate short(live: Live, type: string): string {\n\t\tif (live.holds) return `saving for ${an(type)}`\n\t\tif (live.def.spare) return `waits for ${live.def.spare} ${this.ai.purse.money} to spare for ${an(type)}`\n\t\treturn `waits for the money for ${an(type)}`\n\t}\n\n\t/** No spot found this think: for a want that does not stand, given up after `siteTimeout` seconds, and said */\n\tprivate noSite(live: Live): boolean {\n\t\tconst { ai } = this\n\t\tlive.memory.noSite ??= ai.tick\n\t\tconst to = this.placeOf(live)\n\t\tif (to) this.sendSettler(live, to)\n\t\tif (live.def.keep) return false\n\t\tconst limit = (live.def.siteTimeout ?? this.options.siteTimeout ?? SITE_TIMEOUT) * ai.session.tickRate\n\t\tif (ai.tick - live.memory.noSite < limit) return false\n\t\tthis.wants.delete(live.id)\n\t\tai.decide(`gives up on ${an(live.def.type)}: no spot for it in ${Math.round(limit / ai.session.tickRate)} s`, { kind: 'build' })\n\t\treturn true\n\t}\n\n\t/** Where a want says it goes, as a point: a point, a named entity it knows of, or what its function gives. Nothing for home */\n\tprivate placeOf(live: Live): Vec2 | undefined {\n\t\tconst { near } = live.def\n\t\tif (near === undefined) return undefined\n\t\tif (typeof near === 'function') return near(this.ai)\n\t\tif (typeof near === 'string') {\n\t\t\tconst named = this.ai.view.named(near)\n\t\t\treturn named ? { x: named.x, z: named.z } : undefined\n\t\t}\n\t\treturn near\n\t}\n\n\t/** A spot for a type: where the want says, no further than it says, by its strategy; near home for a step on the way */\n\tprivate siteFor(type: UnitTypeDef, live: Live | undefined): Vec2 | undefined {\n\t\tconst { view } = this.ai\n\t\tconst near = (live && this.placeOf(live)) ?? view.home() ?? view.mine.where((_, def) => !!def.builds?.includes(type.id)).first()\n\t\tif (!near) return undefined\n\t\treturn this.site(type, { near: { x: near.x, z: near.z }, within: live?.def.within ?? this.options.within ?? WITHIN }, live?.def.placement)\n\t}\n\n\t/**\n\t * A spot for a type near a place, by a strategy: the one given, else what the type declares (`UnitTypeDef.ai.placement`),\n\t * the plan's table by type then by role, the role's default, the rings around the place. What is built on a\n\t * deposit goes on one whatever the name\n\t */\n\tsite(\n\t\ttype: UnitTypeDef,\n\t\trequest: Omit<SiteRequest, 'ordinal'> & { ordinal?: number },\n\t\tplacement?: PlacementName | PlacementStrategy\n\t): Vec2 | undefined {\n\t\tconst strategy = this.strategyFor(type, placement)\n\t\treturn strategy(this.ai, type, { ...request, ordinal: request.ordinal ?? this.have(type.id) + this.onItsWay(type.id) })\n\t}\n\n\tprivate strategyFor(type: UnitTypeDef, placement?: PlacementName | PlacementStrategy): PlacementStrategy {\n\t\tif (typeof placement === 'function') return placement\n\t\tif (type.builtOn !== undefined) return placementNamed('byResource')\n\t\tconst table = this.options.placement ?? {}\n\t\tconst roles = this.ai.view.roles.of(type.id)\n\t\tconst chosen: PlacementName | PlacementStrategy | undefined =\n\t\t\tplacement ??\n\t\t\ttype.ai?.placement ??\n\t\t\ttable[type.id] ??\n\t\t\troles.map((role) => table[role]).find((each) => each !== undefined) ??\n\t\t\troles.map((role) => DEFAULT_PLACEMENT[role]).find((each) => each !== undefined)\n\t\tif (typeof chosen === 'function') return chosen\n\t\treturn placementNamed(chosen ?? 'nearHome')\n\t}\n\n\t/** The workers sent to look at the ground somewhere, by any want: not builders while they go */\n\tprivate settlers(): Set<number> {\n\t\tconst ids = new Set<number>()\n\t\tfor (const live of this.wants.values()) {\n\t\t\tconst settler = this.ai.view.byId(live.memory.settler)\n\t\t\tif (settler?.own?.order === 'move') ids.add(settler.id)\n\t\t}\n\t\treturn ids\n\t}\n\n\t/**\n\t * Who builds a type at a spot: of the player's units that build it, those not hidden, not building, not sent this\n\t * think, not off to look at ground and not in a squad or held by a rule; idle first, then whoever carries the least,\n\t * then the nearest\n\t */\n\tbuilderFor(type: UnitTypeDef, site: Vec2): EntityState | undefined {\n\t\tconst settlers = this.settlers()\n\t\tconst builders = this.ai.view.mine\n\t\t\t.where(\n\t\t\t\t(entity, def) =>\n\t\t\t\t\t!!def.builds?.includes(type.id) &&\n\t\t\t\t\t!!entity.own &&\n\t\t\t\t\t!entity.own.hidden &&\n\t\t\t\t\tentity.own.order !== 'build' &&\n\t\t\t\t\tentity.own.order !== 'repair' &&\n\t\t\t\t\t!this.sent.has(entity.id) &&\n\t\t\t\t\t!settlers.has(entity.id) &&\n\t\t\t\t\t// a unit a squad or a rule has is theirs to move (B1's one order of who may move a unit), not the plan's\n\t\t\t\t\t!this.ai.goals.ruled(entity.id) &&\n\t\t\t\t\t!this.ai.squads.squadOf(entity)\n\t\t\t)\n\t\t\t.items.slice()\n\t\tbuilders.sort(\n\t\t\t(a, b) =>\n\t\t\t\tNumber(!!a.own?.order) - Number(!!b.own?.order) ||\n\t\t\t\t(snapshotOf(a, gathering)?.carrying ?? 0) - (snapshotOf(b, gathering)?.carrying ?? 0) ||\n\t\t\t\tdistSq(a, site) - distSq(b, site) ||\n\t\t\t\ta.id - b.id\n\t\t)\n\t\treturn builders[0]\n\t}\n\n\t/** Where a settler stands to see a place: on its near side, towards home, so that it sees where the building would stand and not the mine alone */\n\tprivate settlePoint(to: Vec2): Vec2 {\n\t\tconst home = this.ai.view.home()\n\t\tconst away = home ? Math.sqrt(distSq(home, to)) : 0\n\t\treturn home && away > SETTLE_FROM\n\t\t\t? { x: to.x + ((home.x - to.x) / away) * SETTLE_FROM, z: to.z + ((home.z - to.z) / away) * SETTLE_FROM }\n\t\t\t: { x: to.x, z: to.z }\n\t}\n\n\t/**\n\t * A worker sent to where a want goes, to see the ground: one at a time for the want, sent again if it was taken off\n\t * it. To the near side of the place, towards home (`settlePoint`)\n\t */\n\tprivate sendSettler(live: Live, to: Vec2): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst settling = view.byId(live.memory.settler)\n\t\tif (settling?.owner === ai.playerId && settling.own?.order === 'move') return\n\t\tconst type = ai.registry.unit(live.def.type)\n\t\tconst workers = view.mine.where(\n\t\t\t(entity, def) => !!def.builds?.includes(type.id) && !!entity.own && !entity.own.hidden && !snapshotOf(entity, gathering)?.carrying\n\t\t)\n\t\tconst settler = workers.nearest(to)\n\t\tif (!settler) return\n\t\tlive.memory.settler = settler.id\n\t\tai.send({ type: 'order', entities: [settler.id], order: { type: 'move', point: this.settlePoint(to) } })\n\t\tai.decide(`sends a worker to see the ground at ${where(to)}, for ${an(live.def.type)}`, { kind: 'build' })\n\t}\n\n\t/**\n\t * Builds a type now, outside any want: a spot near a place (home when left out), a builder, the purse. What a\n\t * module does for a one-off (the melee player's building on a mine). Whether it was sent\n\t */\n\tbuild(\n\t\ttype: UnitTypeDef | string,\n\t\toptions: { near?: Vec2; within?: number; placement?: PlacementName | PlacementStrategy; spare?: number; by?: string } = {}\n\t): boolean {\n\t\tconst { ai } = this\n\t\tconst { view, purse } = ai\n\t\tconst def = typeof type === 'string' ? ai.registry.unit(type) : type\n\t\tif (!view.has(def.requires) || !purse.affords(def.cost, options.spare ?? 0)) return false\n\t\tconst near = options.near ?? view.home() ?? view.mine.where((_, each) => !!each.builds?.includes(def.id)).first()\n\t\tif (!near) return false\n\t\tconst site = this.site(def, { near: { x: near.x, z: near.z }, within: options.within ?? this.options.within ?? WITHIN }, options.placement)\n\t\tif (!site) return false\n\t\tconst builder = this.builderFor(def, site)\n\t\tif (!builder || !purse.spend(def.cost)) return false\n\t\tthis.sent.add(builder.id)\n\t\tai.send({ type: 'order', entities: [builder.id], order: { type: 'build', unitType: def.id, point: site } })\n\t\tai.decide(`builds ${an(def.id)} at ${where(site)}${options.by ? `, for ${options.by}` : ''}`, { kind: 'build' })\n\t\treturn true\n\t}\n\n\t/**\n\t * Mends: a worker sent to a damaged building of the player's that no enemy strength reaches, one a think, when\n\t * the purse has what the mending will cost (`GameRules.economy.repairCost` of what is missing). Not one being mended already\n\t */\n\tprivate mend(): void {\n\t\tconst { ai } = this\n\t\tconst { view, purse, registry } = ai\n\t\tconst share = registry.rules.economy.repairCost\n\t\tfor (const building of view.mine.buildings().finished()) {\n\t\t\tconst def = view.def(building)\n\t\t\tconst maxHp = building.maxHp ?? baseStats(def, registry).health\n\t\t\tif (!(building.hp < maxHp * MEND_UNDER) || !def.cost) continue\n\t\t\tif (ai.threat.at(building).enemy > 0) continue\n\t\t\tconst menders = view.mine.where((entity, each) => !!each.builds?.length && entity.own?.order === 'repair' && distSq(entity, building) < 36)\n\t\t\tif (menders.length) continue\n\t\t\tconst missing = 1 - building.hp / maxHp\n\t\t\tconst price: Cost = {}\n\t\t\tfor (const kind in def.cost) price[kind] = Math.ceil(def.cost[kind] * share * missing)\n\t\t\tif (!purse.affords(price)) continue\n\t\t\tconst worker = this.builderFor(def, building)\n\t\t\tif (!worker || !worker.own || worker.own.order === 'build') continue\n\t\t\tpurse.spend(price)\n\t\t\tthis.sent.add(worker.id)\n\t\t\tai.send({ type: 'order', entities: [worker.id], order: { type: 'repair', target: building.id } })\n\t\t\tai.decide(`mends its ${def.id} at ${where(building)}: ${Math.round(missing * 100)}% gone, nobody near it`, { kind: 'build' })\n\t\t\treturn\n\t\t}\n\t}\n\n\t/** The wants in the order they were added: what the report and a save list them in, the same in a loaded game */\n\tprivate ordered(): Live[] {\n\t\treturn [...this.wants.values()].sort((a, b) => a.memory.order - b.memory.order)\n\t}\n\n\t/** Every want as the last think left it, in the order added, the one saving up named */\n\treport(): BuildPlanReport {\n\t\tconst wants = this.ordered().map((live): WantReport => ({\n\t\t\tid: live.id,\n\t\t\ttype: live.def.type,\n\t\t\tcount: live.count,\n\t\t\thave: live.have,\n\t\t\tonItsWay: live.onItsWay,\n\t\t\tpriority: live.def.priority ?? 0,\n\t\t\t...(live.def.by !== undefined && { by: live.def.by }),\n\t\t\t...(live.def.keep && { keep: true as const }),\n\t\t\tstatus: live.status,\n\t\t\tsteps: [...live.steps],\n\t\t\t...(live.holds && { holds: { ...live.holds } })\n\t\t}))\n\t\treturn { wants, ...(this.saving !== undefined && { saving: this.saving }) }\n\t}\n\n\t/**\n\t * What it remembers, for a save: each standing want's memory (its code gives the want again), and the wants added\n\t * as the game went that are plain data, whole. A want that does not stand and has code in it is not kept: the\n\t * game loaded from the save would not know when the game saved from would have dropped it\n\t */\n\tsave(): BuildPlanMemory {\n\t\tconst wants: BuildPlanMemory['wants'] = []\n\t\tfor (const live of this.ordered()) {\n\t\t\tif (live.def.keep) wants.push({ id: live.id, memory: { ...live.memory } })\n\t\t\telse if (isData(live.def)) wants.push({ id: live.id, memory: { ...live.memory }, data: structuredClone(live.def) as WantData })\n\t\t}\n\t\tfor (const id in this.pending) wants.push({ id, memory: { ...this.pending[id] } })\n\t\twants.sort((a, b) => a.memory.order - b.memory.order)\n\t\treturn { v: 1, wants, added: this.added, ...(this.saving !== undefined && { saving: this.saving }) }\n\t}\n\n\t/** Takes back what `save` gave: whether it was read. The data wants are had again; memory waits for the wants code adds */\n\trestore(memory: unknown): boolean {\n\t\tconst given = memory as BuildPlanMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1 || !Array.isArray(given.wants)) return false\n\t\tthis.pending = {}\n\t\tif (typeof given.added === 'number') this.added = Math.max(this.added, given.added)\n\t\tthis.saving = typeof given.saving === 'string' ? given.saving : undefined\n\t\tfor (const entry of given.wants) {\n\t\t\tif (!entry || typeof entry.id !== 'string') continue\n\t\t\tconst live = this.wants.get(entry.id)\n\t\t\tif (live) live.memory = { ...entry.memory }\n\t\t\telse this.pending[entry.id] = { ...entry.memory }\n\t\t\tif (entry.data && !live) this.want({ ...entry.data, id: entry.id })\n\t\t}\n\t\treturn true\n\t}\n}\n\n/**\n * The build module: runs the brain's build plan (`ai.plans.build.think()`) in its place among a brain's modules, after\n * what adds wants (rules, goals) and before what gives idle workers something else to do. With options for the plan\n *\n * @beta\n */\nexport const build = (options: BuildPlanOptions = {}): AiModuleDef =>\n\tdefineModule('build', (ai: Brain): AiModule => {\n\t\tai.plans.build.configure(options)\n\t\treturn {\n\t\t\tid: 'build',\n\t\t\tphase: 'plan',\n\t\t\tthink: () => ai.plans.build.think()\n\t\t}\n\t})\n","import type { UnitTypeDef, UpgradeDef } from '#engine/defs'\nimport { queueOf } from '#engine/systems/productionQueue'\nimport type { EntityState } from '#engine/session/protocol'\nimport { availableToPlayer } from '#engine/shared'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModule, type AiModuleDef, defineModule } from '#engine/ai/module'\nimport type { Want } from './build'\nimport { an } from '../geometry'\n\n/*\n * The production plan (AI plan, B3): what a computer player trains and researches. The old melee player trained, at\n * each barracks, \"whatever answers their army best, then whatever there is the least of\", and researched \"whatever is\n * first with gold to spare\". The plan keeps a **composition** instead: the army it wants, as shares by unit type or\n * tag (`{ footman: 2, rifleman: 1 }`, `{ ranged: 1, melee: 1 }`), from the brain's definition, the seat's options, the\n * profile (D1) and the waves (D2) as those land; what is trained is what is furthest under its share, with what\n * answers the enemy's army seen (`Strength.counterFor`, A4) pulling the shares about: a type that cannot hit what\n * they field is not trained while they field it. **Wants** of units (`ai.plans.want({ type: 'gryphon', count: 4 })`)\n * come before the composition: the build plan puts their buildings up, this plan trains them. It trains at every\n * building that trains, as the queue length and the purse allow, and keeps **supply ahead**: when what it would train\n * next does not fit, it wants one more of the cheapest building that provides supply. **Research** goes by a ranked\n * list (`research: ['swords', ...]`, or a function giving the next), or, left to itself, by what the army it has uses\n * most, with money to spare. **Upkeep** (`GameModule.upkeep`) is read: the composition trains no further into a tier\n * of upkeep than `upkeepTier` says, unless the money would lie idle (`upkeepSpare`), and no supply is wanted past it.\n * Nothing here is of one game: the types come from the roles and the definitions\n */\n\n/**\n * The army a computer player wants, as shares by unit type id or tag (the kit's `ranged`, `melee`, `hitsAir`, a\n * game's own): `{ footman: 2, rifleman: 1 }` is two footmen to a rifleman. A tag's share is split among the types\n * that have it; a type named gets its own beside. Types it cannot train yet are left out until it can\n *\n * @beta\n */\nexport type Composition = Record<string, number>\n\n/**\n * How the production plan goes about it (`BrainDef.plans.production`, the `production()` module; the data of it in\n * `AiOptions.composition` and `research`)\n *\n * @beta\n */\nexport interface ProductionPlanOptions {\n\t/** The army it wants (`Composition`), or a function of the brain giving it. Even shares of every soldier type it can train when left out */\n\tcomposition?: Composition | ((ai: Brain) => Composition)\n\t/**\n\t * How much what answers the enemy's army seen pulls the shares about: 0 not at all, 1 (left out) as much as a\n\t * share; a type that cannot hit what they field is not trained while they field it\n\t */\n\tcounters?: number\n\t/** Whether it trains soldiers at all: yes when left out. Workers and heroes are the economy's and the hero module's */\n\ttrain?: boolean\n\t/** How many may queue at one building: 2 when left out */\n\tqueue?: number\n\t/** Whether to want one more of what provides supply when what it would train next does not fit: yes when left out */\n\tsupplyAhead?: boolean\n\t/** Supply to keep free beyond the next unit's, so that the farm is up before it is needed: 4 when left out */\n\tsupplyMargin?: number\n\t/** Upgrades to research, in order, by id (the first it can is next), or a function of the brain giving the next; what the army it has uses most when left out */\n\tresearch?: string[] | ((ai: Brain) => string | undefined)\n\t/** Money to have left over before researching: 200 when left out (research is a luxury) */\n\tresearchSpare?: number\n\t/** How important training and research are to the purse (`Purse`): 0 when left out, under every want that saves */\n\tpriority?: number\n\t/**\n\t * The tier of the game's upkeep (`GameModule.upkeep`: 0 none, 1 the first) the composition trains no further into:\n\t * a soldier that would take the supply used past it waits, and no supply is wanted past it, unless the money would\n\t * lie idle (`upkeepSpare`). What is wanted outright (a wave's, a build order's) is trained all the same. `UPKEEP_TIER`\n\t * (1) when left out; `false` reads no upkeep\n\t */\n\tupkeepTier?: number | false\n\t/** Money free past which upkeep is not read (it would lie idle else): `UPKEEP_SPARE` (600) when left out */\n\tupkeepSpare?: number\n}\n\n/**\n * The tier of upkeep the production plan trains no further into where its options say none (`upkeepTier`)\n *\n * @beta\n */\nexport const UPKEEP_TIER = 1\n\n/**\n * The money free past which the production plan reads no upkeep: what would lie idle else (`upkeepSpare`)\n *\n * @beta\n */\nexport const UPKEEP_SPARE = 600\n\n/**\n * One type as the production plan weighs it, for the report: its share of the army wanted (`target`, 0..1), its share\n * now (`share`), how well it answers their army (`counter`: 1 is as good as against anyone), and what the two come\n * to (`urge`: the most urgent is trained next)\n *\n * @beta\n */\nexport interface CompositionReport {\n\ttype: string\n\ttarget: number\n\thave: number\n\tshare: number\n\tcounter: number\n\turge: number\n}\n\n/**\n * The production plan as the report shows it: the composition as weighed, what it trained and researched this\n * think, the unit wants it trains towards, and why it did not train where it did not\n *\n * @beta\n */\nexport interface ProductionPlanReport {\n\tcomposition: CompositionReport[]\n\ttrained: string[]\n\tresearched: string[]\n\twants: string[]\n\tstatus: string\n}\n\nconst QUEUE = 2\nconst SUPPLY_MARGIN = 4\n/** The id of the build plan's want of supply */\nconst SUPPLY_WANT = 'production.supply'\nconst RESEARCH_SPARE = 200\n\n/**\n * What the production plan remembers between thinks, for a save: what its want of supply was set with\n *\n * @beta\n */\nexport interface ProductionPlanMemory {\n\tsupply?: { type: string; need: number; most?: number }\n}\n\n/**\n * The brain's production plan (`ai.plans.production`): what it trains and researches, by the wants of units, the\n * composition and the counters, with supply kept ahead. `train` and `research` are the primitives any module uses\n * to queue something through the purse; `think` runs the plan once a think\n *\n * @beta\n */\nexport class ProductionPlan {\n\tprivate options: ProductionPlanOptions = {}\n\tprivate thoughtAt = -1\n\tprivate trained: string[] = []\n\tprivate researched: string[] = []\n\tprivate status = 'new'\n\tprivate weighed: CompositionReport[] = []\n\tprivate wantedNow: string[] = []\n\t/** What the supply want was last set with (`supplyAhead`): kept in a save, for a loaded game to have it again */\n\tprivate supply: { type: string; need: number; most: number } | undefined\n\n\tconstructor(\n\t\t/** The brain it plans for */\n\t\treadonly ai: Brain,\n\t\toptions: ProductionPlanOptions = {}\n\t) {\n\t\tthis.configure(options)\n\t}\n\n\t/** Takes options in, over what it had */\n\tconfigure(options: ProductionPlanOptions): void {\n\t\tthis.options = { ...this.options, ...options }\n\t}\n\n\t/** The plan's options as they stand */\n\tget settings(): Readonly<ProductionPlanOptions> {\n\t\treturn this.options\n\t}\n\n\t/** Whether the player may make a type or research an upgrade (`key`: `upgrade:<id>`), as its race and the game's `available` hook say */\n\tprivate may(def: { readonly race?: string }, key: string): boolean {\n\t\tconst { me } = this.ai.view\n\t\treturn availableToPlayer(def, { race: me.race, availability: me.availability }, key)\n\t}\n\n\t/** How many of a unit type the player's buildings are training */\n\tqueued(type: string): number {\n\t\tlet count = 0\n\t\tfor (const entity of this.ai.view.mine) for (const item of queueOf(entity)) if (item.kind === 'unit' && item.id === type) count++\n\t\treturn count\n\t}\n\n\t/**\n\t * Trains a unit at a building, when it fits the supply, the queue has room and the purse allows: whether it was\n\t * sent. The supply used is bumped on the view's `me` at once, so that the next call this think does not queue past\n\t * the cap before the command lands. What the economy, the hero module and this plan all train through\n\t */\n\ttrain(building: EntityState, type: UnitTypeDef, priority = this.options.priority ?? 0): boolean {\n\t\tconst { ai } = this\n\t\tconst { me } = ai.view\n\t\tconst supply = type.supply ?? 0\n\t\tif (supply > 0 && me.supplyUsed + supply > me.supplyCap) return false\n\t\tif (queueOf(building).length >= (this.options.queue ?? QUEUE)) return false\n\t\tif (!ai.purse.affords(type.cost, 0, priority)) return false\n\t\tai.purse.spend(type.cost, priority)\n\t\tme.supplyUsed += supply\n\t\tai.send({ type: 'train', building: building.id, unitType: type.id })\n\t\treturn true\n\t}\n\n\t/**\n\t * Researches an upgrade at a building, when it is not researching already, the building's queue has room and the\n\t * purse allows with `spare` left over: whether it was sent. `me.researching` is bumped at once\n\t */\n\tresearch(building: EntityState, upgrade: UpgradeDef, spare = 0, priority = this.options.priority ?? 0): boolean {\n\t\tconst { ai } = this\n\t\tconst { me } = ai.view\n\t\tif (me.researching.includes(upgrade.id)) return false\n\t\tif (queueOf(building).length >= (this.options.queue ?? QUEUE)) return false\n\t\tif (!ai.purse.affords(upgrade.cost, spare, priority)) return false\n\t\tai.purse.spend(upgrade.cost, priority)\n\t\tme.researching.push(upgrade.id)\n\t\tai.send({ type: 'research', building: building.id, upgrade: upgrade.id })\n\t\treturn true\n\t}\n\n\t/** Whether an upgrade can be researched now: a level left, not under way, the player's to make, what the next level requires standing */\n\tresearchable(upgrade: UpgradeDef): boolean {\n\t\tconst { me } = this.ai.view\n\t\tconst level = me.upgrades[upgrade.id] ?? 0\n\t\treturn (\n\t\t\tlevel < (upgrade.maxLevel ?? 1) &&\n\t\t\t!me.researching.includes(upgrade.id) &&\n\t\t\tthis.may(upgrade, `upgrade:${upgrade.id}`) &&\n\t\t\tthis.ai.view.has(upgrade.requires?.[level])\n\t\t)\n\t}\n\n\t/** The soldier types the player can train now: at a finished building of its own, their requirements standing */\n\ttrainable(): UnitTypeDef[] {\n\t\tconst { view, registry } = this.ai\n\t\tconst types: UnitTypeDef[] = []\n\t\tfor (const building of view.mine.buildings().finished()) {\n\t\t\tfor (const id of view.def(building).trains ?? []) {\n\t\t\t\tif (!registry.units.has(id)) continue\n\t\t\t\tconst def = registry.unit(id)\n\t\t\t\tif (types.includes(def) || !view.hasRole(id, 'soldier') || !this.may(def, id) || !view.has(def.requires)) continue\n\t\t\t\ttypes.push(def)\n\t\t\t}\n\t\t}\n\t\treturn types\n\t}\n\n\t/** The army's composition wanted, as given: the function asked, the data as it is */\n\tprivate composition(): Composition | undefined {\n\t\tconst { composition } = this.options\n\t\treturn typeof composition === 'function' ? composition(this.ai) : composition\n\t}\n\n\t/**\n\t * The composition as weighed this think, for the types it can train: each type's share wanted (the composition's\n\t * for its id, or for a tag or role where no type has that id, split among the types that have it; even when there is no composition), its\n\t * share of the soldiers now, how well it answers the enemy's army seen, and its urge: `target × (1 + counters ×\n\t * (counter − 1)) − share`. The most urgent is trained first\n\t */\n\tweigh(): CompositionReport[] {\n\t\tconst { view } = this.ai\n\t\tconst types = this.trainable()\n\t\tif (!types.length) return []\n\t\tconst composition = this.composition()\n\t\tconst weights = new Map<UnitTypeDef, number>()\n\t\tif (composition) {\n\t\t\tfor (const [key, share] of Object.entries(composition)) {\n\t\t\t\t// a key is a type's id first (the fixture's `soldier` is a type and a role): a tag or a role only where no type has the id\n\t\t\t\tconst tagged = this.ai.registry.units.has(key)\n\t\t\t\t\t? types.filter((def) => def.id === key)\n\t\t\t\t\t: types.filter((def) => view.roles.hasTag(def.id, key) || view.roles.has(def.id, key))\n\t\t\t\tfor (const def of tagged) weights.set(def, (weights.get(def) ?? 0) + share / tagged.length)\n\t\t\t}\n\t\t}\n\t\tlet total = 0\n\t\tfor (const def of types) total += composition ? (weights.get(def) ?? 0) : 1\n\t\tconst soldiers = view.mine.fighters().where((_, def) => !def.hero)\n\t\tconst counters = this.counters(types)\n\t\tconst pull = this.options.counters ?? 1\n\t\treturn types.map((def) => {\n\t\t\tconst target = total > 0 ? (composition ? (weights.get(def) ?? 0) : 1) / total : 0\n\t\t\tconst have = soldiers.ofType(def.id).length\n\t\t\tconst share = soldiers.length ? have / soldiers.length : 0\n\t\t\tconst counter = counters.get(def.id) ?? 1\n\t\t\treturn { type: def.id, target, have, share, counter, urge: target * (1 + pull * (counter - 1)) - share }\n\t\t})\n\t}\n\n\t/** How well each type answers the most of each enemy unit type seen at once (`Strength.counterFor`): 1 for each where nothing was seen */\n\tprivate counters(types: UnitTypeDef[]): Map<string, number> {\n\t\tconst { ai } = this\n\t\tconst result = new Map<string, number>()\n\t\tif (ai.def.knowledge === false) return result\n\t\tconst seen: Record<string, number> = {}\n\t\tfor (const [type, { most }] of Object.entries(ai.knowledge.enemy.typesSeen()))\n\t\t\tif (ai.registry.units.has(type) && ai.registry.unit(type).kind === 'unit') seen[type] = most\n\t\tif (!Object.keys(seen).length) return result\n\t\tfor (const { def, score } of ai.view.strength.counterFor(seen, types)) result.set(def.id, score)\n\t\treturn result\n\t}\n\n\t/** The unit wants the build plan holds that are to be trained now (their buildings up), most important first; the order's alone while it is followed */\n\twanted(): Want[] {\n\t\tconst { ai } = this\n\t\tconst build = ai.plans.build\n\t\tconst following = ai.plans.following\n\t\treturn build\n\t\t\t.list()\n\t\t\t.filter((want) => {\n\t\t\t\tif (following && want.id !== 'order') return false\n\t\t\t\tif (!ai.registry.units.has(want.type) || ai.registry.unit(want.type).kind !== 'unit') return false\n\t\t\t\tconst count = typeof want.count === 'function' ? want.count(ai) : (want.count ?? 1)\n\t\t\t\treturn (\n\t\t\t\t\tbuild.have(want.type) + this.queued(want.type) < count &&\n\t\t\t\t\tbuild.next(want.type)?.how === 'train' &&\n\t\t\t\t\tbuild.next(want.type)?.type === want.type\n\t\t\t\t)\n\t\t\t})\n\t\t\t.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0))\n\t}\n\n\t/** The finished buildings of the player's that train a type, with room in their queue */\n\tprivate trainersOf(type: string): EntityState[] {\n\t\tconst { view } = this.ai\n\t\treturn view.mine\n\t\t\t.buildings()\n\t\t\t.finished()\n\t\t\t.filter((building) => !!view.def(building).trains?.includes(type) && queueOf(building).length < (this.options.queue ?? QUEUE))\n\t}\n\n\t/**\n\t * The think, once a think: the unit wants first (each at a building that trains it, as many as wanted), then the\n\t * composition's most urgent type at every building with room, as the supply, the queue and the purse allow; one\n\t * more of what provides supply wanted when the next does not fit; then the research\n\t */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tif (this.thoughtAt === ai.tick) return\n\t\tthis.thoughtAt = ai.tick\n\t\tthis.trained = []\n\t\tthis.researched = []\n\t\tthis.wantedNow = []\n\t\tthis.weighed = []\n\t\tthis.status = 'nothing to train'\n\t\tif (this.options.train !== false) {\n\t\t\tconst { me } = ai.view\n\t\t\tconst priority = this.options.priority ?? 0\n\t\t\tlet short: UnitTypeDef | undefined\n\t\t\tlet unpaid: UnitTypeDef | undefined\n\t\t\tlet upkept: UnitTypeDef | undefined\n\t\t\t// the upkeep it holds at, while the money would not lie idle past it\n\t\t\tconst upkeep = ai.purse.affords(undefined, this.options.upkeepSpare ?? UPKEEP_SPARE, priority) ? undefined : this.upkeepLimit()\n\t\t\tconst queue = (type: UnitTypeDef, upTo: number, composition = false) => {\n\t\t\t\tlet sent = 0\n\t\t\t\tfor (const trainer of this.trainersOf(type.id)) {\n\t\t\t\t\tif (sent >= upTo) break\n\t\t\t\t\tconst supply = type.supply ?? 0\n\t\t\t\t\tif (supply > 0 && me.supplyUsed + supply > me.supplyCap) {\n\t\t\t\t\t\tshort ??= type\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\t// the composition's soldiers go no further into upkeep than told\n\t\t\t\t\tif (composition && supply > 0 && upkeep !== undefined && me.supplyUsed + supply > upkeep) {\n\t\t\t\t\t\tupkept ??= type\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif (!ai.purse.affords(type.cost, 0, priority)) {\n\t\t\t\t\t\tunpaid ??= type\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tif (!this.train(trainer, type, priority)) break\n\t\t\t\t\tthis.trained.push(type.id)\n\t\t\t\t\tsent++\n\t\t\t\t}\n\t\t\t\treturn sent\n\t\t\t}\n\t\t\t// what is wanted outright, most important first\n\t\t\tfor (const want of this.wanted()) {\n\t\t\t\tthis.wantedNow.push(want.id!)\n\t\t\t\tconst count = typeof want.count === 'function' ? want.count(ai) : (want.count ?? 1)\n\t\t\t\tconst type = ai.registry.unit(want.type)\n\t\t\t\tconst sent = queue(type, count - ai.plans.build.have(want.type) - this.queued(want.type))\n\t\t\t\tif (sent)\n\t\t\t\t\tai.decide(`trains ${sent === 1 ? an(type.id) : `${sent} ${type.id}`}: wanted${want.by ? ` by ${want.by}` : ''}`, { kind: 'production' })\n\t\t\t}\n\t\t\t// then the army as the composition wants it, the most urgent type at each building with room, while the\n\t\t\t// order is not being followed (what the game says to make first holds back what the computer would make)\n\t\t\tif (!ai.plans.following) {\n\t\t\t\tthis.weighed = this.weigh()\n\t\t\t\t// a composition that wants nothing (`{}`: the waves', D2, whose groups are wanted outright) trains nothing\n\t\t\t\tconst empty = this.weighed.every((entry) => entry.target <= 0)\n\t\t\t\tconst ranked = empty ? [] : [...this.weighed].sort((a, b) => b.urge - a.urge)\n\t\t\t\tconst pull = this.options.counters ?? 1\n\t\t\t\tfor (const entry of ranked) {\n\t\t\t\t\t// what cannot hit what they field is not trained while they field it (where the counters count); what\n\t\t\t\t\t// is over its share waits while something is under its own\n\t\t\t\t\tif (pull > 0 && entry.counter <= 0) continue\n\t\t\t\t\tif (entry.urge <= 0 && ranked[0].urge > 0) continue\n\t\t\t\t\tconst type = ai.registry.unit(entry.type)\n\t\t\t\t\tconst before = unpaid\n\t\t\t\t\tconst sent = queue(type, Infinity, true)\n\t\t\t\t\tif (sent) {\n\t\t\t\t\t\tai.decide(\n\t\t\t\t\t\t\t`trains ${sent === 1 ? an(type.id) : `${sent} ${type.id}`}: ${entry.counter !== 1 ? `answers their army ${entry.counter.toFixed(2)}, ` : ''}${Math.round(entry.share * 100)}% of the army for ${Math.round(entry.target * 100)}% wanted`,\n\t\t\t\t\t\t\t{ kind: 'production' }\n\t\t\t\t\t\t)\n\t\t\t\t\t\t// what was sent changes the shares: the next type is weighed anew next think\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\t// nothing fits the supply: nothing else will; one it cannot pay for: the next it can may go, so that\n\t\t\t\t\t// an army is raised while the dearer type waits for its resource\n\t\t\t\t\tif (short || upkept) break\n\t\t\t\t\tif (unpaid && unpaid !== before) continue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (short) this.status = `${an(short.id)} does not fit the supply`\n\t\t\telse if (upkept) this.status = `holds at ${upkeep} supply: ${an(upkept.id)} would take it into upkeep`\n\t\t\telse if (unpaid) this.status = `waits for the money for ${an(unpaid.id)}`\n\t\t\telse if (this.trained.length) this.status = `trained ${this.trained.join(', ')}`\n\t\t\t// supply ahead of what comes next: what did not fit, else the most urgent\n\t\t\tconst next = short ?? (this.weighed.length ? ai.registry.unit([...this.weighed].sort((a, b) => b.urge - a.urge)[0].type) : undefined)\n\t\t\tif (this.options.supplyAhead !== false) this.supplyAhead(next, upkeep)\n\t\t}\n\t\tthis.runResearch()\n\t}\n\n\t/**\n\t * The supply used the composition trains no further than for upkeep (`upkeepTier`): where the tier after the one it\n\t * may be in begins. None in a game without upkeep, past its last tier, or with `upkeepTier: false`\n\t */\n\tupkeepLimit(): number | undefined {\n\t\tconst tier = this.options.upkeepTier ?? UPKEEP_TIER\n\t\tif (tier === false) return undefined\n\t\treturn this.ai.registry.upkeep[tier]?.above\n\t}\n\n\t/**\n\t * Supply kept ahead: when the type to train next does not fit (or the free supply is under the margin), one more of\n\t * the cheapest building that provides supply is wanted of the build plan, unless the cap is the game's most or one\n\t * is on its way already\n\t */\n\tprivate supplyAhead(next: UnitTypeDef | undefined, upkeep?: number): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { me } = view\n\t\tconst margin = this.options.supplyMargin ?? SUPPLY_MARGIN\n\t\tconst need = (next?.supply ?? 0) + margin\n\t\t// no further than the upkeep it holds at: the margin up to it, not past\n\t\tconst most = Math.min(ai.registry.rules.supply.max, upkeep ?? Infinity)\n\t\tif (me.supplyCap >= most || me.supplyCap - me.supplyUsed >= need) return\n\t\tconst types = [...view.typesOf('supply')].sort((a, b) => (a.cost?.[ai.purse.money] ?? 0) - (b.cost?.[ai.purse.money] ?? 0))\n\t\tconst type = types[0]\n\t\tif (!type) return\n\t\tthis.wantSupply(type.id, need, most)\n\t}\n\n\t/**\n\t * One at a time: what stands finished, and one more. A standing want, with what is needed in its condition: set\n\t * again whenever the need changes\n\t */\n\tprivate wantSupply(type: string, need: number, most: number): void {\n\t\tconst { ai } = this\n\t\tthis.supply = { type, need, most }\n\t\tai.plans.build.want({\n\t\t\tid: SUPPLY_WANT,\n\t\t\ttype,\n\t\t\tcount: () => ai.view.mine.ofType(type).finished().length + 1,\n\t\t\tpriority: 90,\n\t\t\tby: 'supply',\n\t\t\tkeep: true,\n\t\t\twhen: () => {\n\t\t\t\tconst now = ai.view.me\n\t\t\t\treturn now.supplyCap < most && now.supplyCap - now.supplyUsed < need\n\t\t\t}\n\t\t})\n\t}\n\n\t/** What it remembers, for a save: what the supply want was set with, while it stands */\n\tsave(): ProductionPlanMemory | undefined {\n\t\tconst { supply } = this\n\t\tif (!supply || !this.ai.plans.build.get(SUPPLY_WANT)) return undefined\n\t\t// no most but the game's (one without one): Infinity, which a save does not hold\n\t\treturn { supply: { type: supply.type, need: supply.need, ...(Number.isFinite(supply.most) && { most: supply.most }) } }\n\t}\n\n\t/**\n\t * Takes back what `save` gave, after the build plan's: the supply want is had again at once, before the first think,\n\t * as the game saved from has it (the module sets it again only when supply runs short, after the build plan thinks)\n\t */\n\trestore(memory: ProductionPlanMemory | undefined): void {\n\t\tconst supply = memory?.supply\n\t\tthis.supply = undefined\n\t\tif (!supply || typeof supply.type !== 'string' || !this.ai.registry.units.has(supply.type)) return\n\t\tthis.wantSupply(supply.type, supply.need, supply.most ?? Infinity)\n\t}\n\n\t/**\n\t * The upgrade to research next: the first of the list it can (`research` as a list), what the function gives, or,\n\t * left to itself, the one the most of its units benefit from (`UpgradeEffect.units`), ties as the game lists them\n\t */\n\tnextResearch(): UpgradeDef | undefined {\n\t\tconst { ai } = this\n\t\tconst { view, registry } = ai\n\t\tconst { research } = this.options\n\t\tif (typeof research === 'function') {\n\t\t\tconst id = research(ai)\n\t\t\treturn id !== undefined && registry.upgrades.has(id) && this.researchable(registry.upgrade(id)) ? registry.upgrade(id) : undefined\n\t\t}\n\t\tconst offered: UpgradeDef[] = []\n\t\tfor (const building of view.mine.buildings().finished()) {\n\t\t\tfor (const id of view.def(building).researches ?? []) {\n\t\t\t\tif (!registry.upgrades.has(id)) continue\n\t\t\t\tconst def = registry.upgrade(id)\n\t\t\t\tif (!offered.includes(def) && this.researchable(def)) offered.push(def)\n\t\t\t}\n\t\t}\n\t\tif (research) {\n\t\t\tfor (const id of research) {\n\t\t\t\tconst found = offered.find((def) => def.id === id)\n\t\t\t\tif (found) return found\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t\tlet best: UpgradeDef | undefined\n\t\tlet most = -1\n\t\tfor (const def of offered) {\n\t\t\tconst benefits = view.mine.units().filter((unit) => def.effects.some((effect) => effectApplies(effect.units, view.def(unit)))).length\n\t\t\tif (benefits > most) {\n\t\t\t\tmost = benefits\n\t\t\t\tbest = def\n\t\t\t}\n\t\t}\n\t\treturn best\n\t}\n\n\t/** Research, with money to spare: the next upgrade at a finished building of the player's that researches it */\n\tprivate runResearch(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst next = this.nextResearch()\n\t\tif (!next) return\n\t\tconst at = view.mine\n\t\t\t.buildings()\n\t\t\t.finished()\n\t\t\t.find((building) => !!view.def(building).researches?.includes(next.id) && queueOf(building).length < (this.options.queue ?? QUEUE))\n\t\tif (!at) return\n\t\tif (this.research(at, next, this.options.researchSpare ?? RESEARCH_SPARE)) {\n\t\t\tthis.researched.push(next.id)\n\t\t\tai.decide(`researches ${next.id}: money to spare`, { kind: 'research' })\n\t\t}\n\t}\n\n\t/** The composition as weighed, what was trained and researched this think, the wants trained towards, and the status */\n\treport(): ProductionPlanReport {\n\t\treturn {\n\t\t\tcomposition: this.weighed.map((entry) => ({ ...entry })),\n\t\t\ttrained: [...this.trained],\n\t\t\tresearched: [...this.researched],\n\t\t\twants: [...this.wantedNow],\n\t\t\tstatus: this.status\n\t\t}\n\t}\n}\n\n/** Whether an upgrade's effect applies to a unit type: everything the player owns when it names none */\nfunction effectApplies(units: string[] | ((def: UnitTypeDef) => boolean) | undefined, def: UnitTypeDef): boolean {\n\tif (!units) return true\n\tif (typeof units === 'function') return units(def)\n\treturn units.includes(def.id)\n}\n\n/**\n * The production module: runs the brain's production plan (`ai.plans.production.think()`) in its place among a\n * brain's modules, after the build plan (which puts up what a want needs) where a brain has both. With options for\n * the plan\n *\n * @beta\n */\nexport const production = (options: ProductionPlanOptions = {}): AiModuleDef =>\n\tdefineModule('production', (ai: Brain): AiModule => {\n\t\tai.plans.production.configure(options)\n\t\treturn {\n\t\t\tid: 'production',\n\t\t\tphase: 'plan',\n\t\t\tafter: ['build'],\n\t\t\tthink: () => ai.plans.production.think()\n\t\t}\n\t})\n","import type { Brain } from '#engine/ai/brain'\nimport type { AiArea } from '#engine/ai/area'\nimport { BuildPlan, type BuildPlanMemory, type BuildPlanOptions, type BuildPlanReport, type Want } from './build'\nimport { ProductionPlan, type ProductionPlanMemory, type ProductionPlanOptions, type ProductionPlanReport } from './production'\nimport type { PurseReport } from './purse'\n\n/*\n * The plans of a brain (AI plan, B3), under one name (`ai.plans`): the build plan (what to build, and how to get\n * there) and the production plan (what to train and research), and the game's build order over both (`order`: what\n * to have first, each item waiting for the one before, the computer's own wants held back meanwhile). They are the\n * brain's, as its goals are, so that every module adds to the same ones; the modules `build()` and `production()`\n * run each in its place among a brain's modules, and the melee player runs them in its own. What they remember is\n * kept together in the brain's memory (`BrainMemory.plans`)\n */\n\n/**\n * One item of a build order: a type to have (one of it), or a type and how many. Counts of a type add up along the order\n *\n * @beta\n */\nexport type BuildOrderItem = string | { type: string; count?: number }\n\n/**\n * How a brain plans (`BrainDef.plans`): the build plan's options, the production plan's, the build order\n *\n * @beta\n */\nexport interface PlansOptions {\n\tbuild?: BuildPlanOptions\n\tproduction?: ProductionPlanOptions\n\t/**\n\t * What to have first, in order (`BuildOrderItem`): each item waits for the one before, and nothing else the\n\t * computer would make of itself is made meanwhile (`following`); what it works out for itself once done. The\n\t * seat's `AiOptions.buildOrder`\n\t */\n\torder?: BuildOrderItem[]\n}\n\n/**\n * What the plans remember between thinks, for a save\n *\n * @beta\n */\nexport interface PlansMemory {\n\tv: 1\n\tbuild?: BuildPlanMemory\n\tproduction?: ProductionPlanMemory\n}\n\n/**\n * The plans as the report shows them: the purse, and each plan's part\n *\n * @beta\n */\nexport interface PlansReport {\n\tpurse: PurseReport\n\tbuild: BuildPlanReport\n\tproduction: ProductionPlanReport\n\t/** The build order's next item, while it is being followed */\n\torder?: { type: string; count: number; item: number }\n}\n\n/**\n * A brain's plans (`ai.plans`): `build` for what is to be built, `production` for what is to be trained and\n * researched, the game's build `order` over both. `want` is the one door: a want of a building goes to the build\n * plan; one of a unit goes to the build plan for its buildings, and the production plan trains it\n *\n * @beta\n */\nexport class Plans implements AiArea {\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'plans'\n\t/** What the log says where a save's memory of it is of a shape it does not read */\n\treadonly afresh = 'the save remembers what the computer player planned in a shape this brain does not read: it plans afresh'\n\n\t/** What to build, and the steps to it */\n\treadonly build: BuildPlan\n\t/** What to train and research */\n\treadonly production: ProductionPlan\n\tprivate readonly order: BuildOrderItem[]\n\tprivate followedAt = -1\n\tprivate next: PlansReport['order'] | undefined\n\n\tconstructor(\n\t\t/** The brain they plan for */\n\t\treadonly ai: Brain,\n\t\toptions: PlansOptions = {}\n\t) {\n\t\tthis.build = new BuildPlan(ai, options.build)\n\t\tthis.production = new ProductionPlan(ai, options.production)\n\t\tthis.order = options.order ?? []\n\t}\n\n\t/** Adds a want: what the brain works towards from now (`BuildPlan.want`). Gives back its id */\n\twant(def: Want): string {\n\t\treturn this.build.want(def)\n\t}\n\n\t/**\n\t * Works on the game's build order, once a think: the first item not had (what stands, is on its way or is queued\n\t * counted; counts of a type adding up along the order) is a want before all others (`order`, priority 1000), and\n\t * `following` is true. Called by the build plan as it thinks; a module may call it sooner\n\t */\n\tfollow(): PlansReport['order'] | undefined {\n\t\tconst { ai, build } = this\n\t\tif (this.followedAt === ai.tick) return this.next\n\t\tthis.followedAt = ai.tick\n\t\tlet next: PlansReport['order'] | undefined\n\t\tconst wanted = new Map<string, number>()\n\t\tfor (let i = 0; i < this.order.length && !next; i++) {\n\t\t\tconst item = this.order[i]\n\t\t\tconst { type, count = 1 } = typeof item === 'string' ? { type: item } : item\n\t\t\tconst need = (wanted.get(type) ?? 0) + count\n\t\t\twanted.set(type, need)\n\t\t\tif (build.have(type) + build.onItsWay(type) < need) next = { type, count: need, item: i }\n\t\t}\n\t\tthis.next = next\n\t\tif (next) build.want({ id: 'order', type: next.type, count: next.count, priority: 1000, by: 'the build order' })\n\t\telse build.drop('order')\n\t\treturn next\n\t}\n\n\t/** Whether the game's build order is still being followed: what the computer would make of itself waits */\n\tget following(): boolean {\n\t\treturn this.follow() !== undefined\n\t}\n\n\t/** Takes a want out, by id */\n\tdrop(id: string): boolean {\n\t\treturn this.build.drop(id)\n\t}\n\n\t/** The purse and each plan's part, for the report */\n\treport(): PlansReport {\n\t\treturn {\n\t\t\tpurse: this.ai.purse.inspect(),\n\t\t\tbuild: this.build.report(),\n\t\t\tproduction: this.production.report(),\n\t\t\t...(this.next && { order: { ...this.next } })\n\t\t}\n\t}\n\n\t/** What the plans remember, for a save */\n\t/** Whether it has anything to remember now: one that does not is left out of a save */\n\tremembers(): boolean {\n\t\treturn true\n\t}\n\n\tsave(): PlansMemory {\n\t\tconst production = this.production.save()\n\t\treturn { v: 1, build: this.build.save(), ...(production && { production }) }\n\t}\n\n\t/** Takes back what `save` gave: whether it was read */\n\trestore(memory: unknown): boolean {\n\t\tconst given = memory as PlansMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tif (given.build !== undefined) this.build.restore(given.build)\n\t\tthis.production.restore(given.production)\n\t\treturn true\n\t}\n}\n\ndeclare module '#engine/ai/area' {\n\tinterface AreaMemories {\n\t\tplans?: PlansMemory\n\t}\n}\n","import type { Cost, ResourceKind } from '#engine/defs'\nimport type { Registry } from '#engine/registry'\nimport type { AiView } from '#engine/ai/view'\n\n/*\n * The purse (AI plan, B3): the one ledger a computer player spends through. Commands land next tick, so a think that\n * sent a worker to build a barracks still sees the gold in its next picture; and a building is paid for as its builder\n * arrives, not as it is sent. Without a ledger the same gold is spent twice. The purse is rebuilt from the picture at\n * the start of every think (`begin`): the player's resources, less what builders on their way will pay (`promised`),\n * less what is held (`reserve`: a goal's money claim, a want of the build plan saving up for a hall). What is left is\n * `free`, and everything that spends (`spend`) takes it off `free` for the rest of the think. Nothing is carried from\n * one think to the next: a hold belongs to whoever made it and is made again each think while they still want it, so\n * nothing can be promised twice or held for ever.\n *\n * A hold has a priority, as a want does: saving up for a hero does not stop the hall going up, and does stop the\n * footmen. Whoever asks the purse says how important they are (`affords(cost, spare, priority)`), and may spend what\n * is held by anyone less important; a hold spent into is less by that much for the rest of the think.\n */\n\n/**\n * What a computer player has to spend this think (`ai.purse`): its resources less what is promised and held, spent\n * through `spend`. Rebuilt from the picture each think\n *\n * @beta\n */\nexport class Purse {\n\t/** What is free to spend now, by resource: less with every `spend` and `reserve` of the think. `view.me.purse` is this */\n\tfree: Cost = {}\n\t/** What builders on their way to a site will pay as they get there, by resource */\n\tpromised: Cost = {}\n\t/** What was paid this think (`spend`), by resource: with `promised`, never more than the picture's resources (`ai/checks.ts`) */\n\tspent: Cost = {}\n\t/** The resource most things cost (`Registry.currency`): what `affords` keeps `spare` of */\n\treadonly money: ResourceKind\n\tprivate holds: Record<string, { cost: Cost; priority: number }> = {}\n\n\tconstructor(registry: Registry) {\n\t\tthis.money = registry.currency ?? registry.resources[0]?.id ?? ''\n\t}\n\n\t/**\n\t * Starts the think's ledger from the picture: the player's resources, less what its builders on their way will pay\n\t * (`promised`). Every hold of the think before is dropped: whoever still wants one makes it again\n\t */\n\tbegin(view: AiView): void {\n\t\tthis.free = { ...view.me.resources }\n\t\tthis.promised = {}\n\t\tthis.spent = {}\n\t\tthis.holds = {}\n\t\tconst { registry } = view\n\t\tfor (const entity of view.mine) {\n\t\t\tconst own = entity.own\n\t\t\tif (own?.order !== 'build' || !own.build || !registry.units.has(own.build)) continue\n\t\t\tconst cost = registry.unit(own.build).cost\n\t\t\tfor (const kind in cost) {\n\t\t\t\tthis.promised[kind] = (this.promised[kind] ?? 0) + cost[kind]\n\t\t\t\tthis.free[kind] = (this.free[kind] ?? 0) - cost[kind]\n\t\t\t}\n\t\t}\n\t}\n\n\t/** What someone this important may spend: what is free, and what is held by anyone less important */\n\tavailable(priority = 0): Cost {\n\t\tconst sum: Cost = { ...this.free }\n\t\tfor (const id in this.holds) {\n\t\t\tconst hold = this.holds[id]\n\t\t\tif (hold.priority >= priority) continue\n\t\t\tfor (const kind in hold.cost) sum[kind] = (sum[kind] ?? 0) + hold.cost[kind]\n\t\t}\n\t\treturn sum\n\t}\n\n\t/** The resource a cost is short of, out of what someone this important may spend: none when it can be paid */\n\tshortOf(cost: Cost | undefined, priority = 0): ResourceKind | undefined {\n\t\tconst available = this.available(priority)\n\t\tfor (const kind in cost) if ((available[kind] ?? 0) < cost[kind]) return kind\n\t\treturn undefined\n\t}\n\n\t/**\n\t * Whether a cost can be paid by someone this important, with `spare` of the money left over after it (a luxury\n\t * waits for gold to spare): out of what is free, and what is held by anyone less important\n\t */\n\taffords(cost: Cost | undefined, spare = 0, priority = 0): boolean {\n\t\treturn this.shortOf(cost, priority) === undefined && (this.available(priority)[this.money] ?? 0) >= (cost?.[this.money] ?? 0) + spare\n\t}\n\n\t/**\n\t * Pays a cost, for a command sent this think: out of what is free first, then out of what is held by anyone less\n\t * important (the least important first), whose holds are less by that much. False, and nothing paid, when it cannot be\n\t */\n\tspend(cost: Cost | undefined, priority = 0): boolean {\n\t\tif (this.shortOf(cost, priority) !== undefined) return false\n\t\tconst lesser = Object.keys(this.holds)\n\t\t\t.filter((id) => this.holds[id].priority < priority)\n\t\t\t.sort((a, b) => this.holds[a].priority - this.holds[b].priority)\n\t\tfor (const kind in cost) {\n\t\t\tlet owed = cost[kind]\n\t\t\tthis.spent[kind] = (this.spent[kind] ?? 0) + owed\n\t\t\tconst free = this.free[kind] ?? 0\n\t\t\tconst fromFree = Math.min(owed, Math.max(0, free))\n\t\t\tthis.free[kind] = free - fromFree\n\t\t\towed -= fromFree\n\t\t\tfor (const id of lesser) {\n\t\t\t\tif (owed <= 0) break\n\t\t\t\tconst held = this.holds[id].cost[kind] ?? 0\n\t\t\t\tconst taken = Math.min(owed, held)\n\t\t\t\tthis.holds[id].cost[kind] = held - taken\n\t\t\t\towed -= taken\n\t\t\t}\n\t\t\t// what the lesser holds did not cover goes on the free side, under nothing: `shortOf` said it is there\n\t\t\tif (owed > 0) this.free[kind] = (this.free[kind] ?? 0) - owed\n\t\t}\n\t\treturn true\n\t}\n\n\t/**\n\t * Holds a cost aside under a name (a goal's id, a want's) for the rest of the think, with how important the holder\n\t * is (0 when left out): what is free is less by it, so that nothing less important spends what is saved up. Made\n\t * again each think by whoever still saves; a second hold under the same name replaces the first\n\t */\n\treserve(id: string, cost: Cost, priority = 0): void {\n\t\tthis.release(id)\n\t\tthis.holds[id] = { cost: { ...cost }, priority }\n\t\tfor (const kind in cost) this.free[kind] = (this.free[kind] ?? 0) - cost[kind]\n\t}\n\n\t/** Lets a hold go: what it held is free again this think */\n\trelease(id: string): void {\n\t\tconst held = this.holds[id]\n\t\tif (!held) return\n\t\tdelete this.holds[id]\n\t\tfor (const kind in held.cost) this.free[kind] = (this.free[kind] ?? 0) + held.cost[kind]\n\t}\n\n\t/** What is held under a name */\n\treservation(id: string): Readonly<Cost> | undefined {\n\t\treturn this.holds[id]?.cost\n\t}\n\n\t/** What is held altogether, by resource */\n\treserved(): Cost {\n\t\tconst sum: Cost = {}\n\t\tfor (const id in this.holds) for (const kind in this.holds[id].cost) sum[kind] = (sum[kind] ?? 0) + this.holds[id].cost[kind]\n\t\treturn sum\n\t}\n\n\t/** Every hold, by name: what and how important */\n\tholdings(): Readonly<Record<string, { cost: Readonly<Cost>; priority: number }>> {\n\t\treturn this.holds\n\t}\n\n\t/** The ledger for the report: what is free, what is promised, what is held and by whom */\n\tinspect(): PurseReport {\n\t\tconst held: PurseReport['held'] = {}\n\t\tfor (const id in this.holds) held[id] = { cost: { ...this.holds[id].cost }, priority: this.holds[id].priority }\n\t\treturn { free: { ...this.free }, promised: { ...this.promised }, held }\n\t}\n}\n\n/**\n * The purse as the report shows it: what is free, what builders on their way will pay, what is held and by whom, with\n * how important each holder is\n *\n * @beta\n */\nexport interface PurseReport {\n\tfree: Cost\n\tpromised: Cost\n\theld: Record<string, { cost: Cost; priority: number }>\n}\n","import type { PlayerId } from '#engine/entity'\nimport type { Vec2 } from '#engine/math'\nimport { isCommand, type PlayerCommand } from '#engine/session/protocol'\nimport type { Brain, BrainWatcher } from './brain'\n\n/*\n * What must always hold of a computer player, checked after every think (AI plan, E3). A brain can play badly and\n * still be right; these are the things that, broken, make it wrong in a way no single game shows until much later: a\n * unit told two things at once, gold spent twice, a `NaN` that quietly picks a goal, a command about something it\n * could not see, an order sent again and again to a unit already carrying it out, a builder or a squad that never\n * finishes. Each is one rule below, named, with the failure it catches:\n *\n * | Invariant | What must hold | Catches |\n * | ---------- | ------------------------------------------------------------------------------------ | ------------------------------------------ |\n * | `squads` | A unit is in at most one squad, and held by at most one goal, rule or module | Two orders a think, lost units |\n * | `purse` | What the think spent, with what builders on their way will pay, is what it had | Spending twice, a plan that waits for ever |\n * | `finite` | Every score, consideration, strength and odds is a finite number | `NaN` picking a goal silently |\n * | `commands` | Every command names entities and points its picture of the game has | A fog leak, a stale target |\n * | `churn` | An order is not sent again to a unit still carrying the same one out | Units that stop and start |\n * | `ends` | A builder, a squad's task, a hold of money and a stuck want each end in time | Builders, squads and plans stuck |\n *\n * The seventh, that a game saved and loaded makes the same decisions from then on, needs two worlds: it is\n * `checkComputerSave` in `@v12-engine/engine/testing`. Nothing here decides anything or touches the world: the checks\n * read the brain's picture of the game and what it sent, through `Brain.watch`. They are on in a test that asks\n * (`watchComputer`, `checkBrain`), and in every brain while the engine's own checks are (`debugChecks.ai`).\n */\n\n/**\n * The name of a rule every computer player keeps (`checkBrain`): see the table in `ai/checks.ts`\n *\n * @beta\n */\nexport type AiInvariant = 'squads' | 'purse' | 'finite' | 'commands' | 'churn' | 'ends'\n\n/**\n * Every invariant, in the order they are checked\n *\n * @beta\n */\nexport const AI_INVARIANTS: readonly AiInvariant[] = ['squads', 'purse', 'finite', 'commands', 'churn', 'ends']\n\n/**\n * A rule a computer player broke, at a think: which, whose, when, and what exactly, in words\n *\n * @beta\n */\nexport interface AiViolation {\n\tinvariant: AiInvariant\n\tplayer: PlayerId\n\t/** The tick of the think's picture of the game */\n\ttick: number\n\tmessage: string\n}\n\n/**\n * Seconds a thing may go on before the `ends` invariant says it is stuck (`AiCheckOptions.limits`)\n *\n * @beta\n */\nexport interface AiEndLimits {\n\t/** A worker on its way to build, not yet begun: 120 when left out (the build plan gives up on a site after 60) */\n\tbuilder?: number\n\t/** A squad's task in one phase (going, gathering, fighting): 300 when left out. A squad holding a place or going with a unit never times out */\n\ttask?: number\n\t/** Money held under one name, think after think: 600 when left out */\n\treservation?: number\n\t/**\n\t * A want of the build plan that cannot be got to (a requirement out of reach), or one that does not stand finding no\n\t * spot or builder: 600 when left out. A standing want waiting for room is no fault\n\t */\n\twant?: number\n}\n\n/**\n * How a brain is checked (`checkBrain`, `watchComputer`)\n *\n * @beta\n */\nexport interface AiCheckOptions {\n\t/** The invariants to check: all of them when left out */\n\tinvariants?: readonly AiInvariant[]\n\t/** How long a thing may go on before it counts as stuck (`ends`) */\n\tlimits?: AiEndLimits\n\t/** Told of each broken rule as it is found. Where none is given, `checkBrain` throws at the first */\n\tonViolation?: (violation: AiViolation) => void\n}\n\n/** Seconds within which an order sent again for the same thing is churn: what `AiStats.churn` counts by too */\nexport const CHURN_WINDOW = 5\n\nconst LIMITS: Required<AiEndLimits> = { builder: 120, task: 300, reservation: 600, want: 600 }\n\n/**\n * What an order to a unit is for, as a key: its kind, its target, its place to the cell. Two orders with the same key\n * are the same order. None for a command that is not an order to units (a train, a ping, a game's own)\n */\nexport function orderKey(command: PlayerCommand): string | undefined {\n\tif (isCommand(command, 'order')) {\n\t\tconst { type, target, point } = command.order\n\t\treturn `${type}:${target ?? ''}:${point ? `${Math.round(point.x)},${Math.round(point.z)}` : ''}`\n\t}\n\tif (isCommand(command, 'attack') && command.point)\n\t\treturn `attack:${command.target ?? ''}:${Math.round(command.point.x)},${Math.round(command.point.z)}`\n\treturn undefined\n}\n\n/** The kind of order a unit carries out for a command: an attack on a target, an attack-move, or the order's own */\nfunction kindOf(command: PlayerCommand): string | undefined {\n\tif (isCommand(command, 'attack')) return command.target === undefined ? 'attackMove' : 'attack'\n\treturn isCommand(command, 'order') ? command.order.type : undefined\n}\n\n/** Fields of the engine's commands that name an entity of the sender's own, one or a list (a hero apart: a dead one is in the player's list of heroes, not on the ground) */\nconst OWN_ONE = ['building', 'entity'] as const\nconst OWN_LIST = ['entities', 'buildings'] as const\n/** Fields that name any entity the sender knows of: a target, a shop */\nconst KNOWN = ['target', 'shop'] as const\n\n/**\n * Checks a brain against the invariants after each of its thinks, through what it is watched by (`Brain.watch`): what\n * `checkBrain` makes, and keeps the broken rules in `violations`\n *\n * @beta\n */\nexport class BrainChecks implements BrainWatcher {\n\t/** Every rule found broken, in the order found */\n\treadonly violations: AiViolation[] = []\n\tprivate readonly invariants: ReadonlySet<AiInvariant>\n\tprivate readonly limits: Required<AiEndLimits>\n\t/** What it sent since its last think ended */\n\tprivate commands: PlayerCommand[] = []\n\t/** The last order each unit was sent, with the tick of the think */\n\tprivate readonly orders = new Map<number, { key: string; tick: number }>()\n\t/** Since when each thing that has to end has been going on, by a key of what it is */\n\tprivate readonly since = new Map<string, number>()\n\t/** What was said stuck already: once a time it is stuck, not every think after */\n\tprivate readonly said = new Set<string>()\n\n\tconstructor(\n\t\treadonly brain: Brain,\n\t\tprivate readonly options: AiCheckOptions = {}\n\t) {\n\t\tthis.invariants = new Set(options.invariants ?? AI_INVARIANTS)\n\t\tthis.limits = { ...LIMITS, ...options.limits }\n\t}\n\n\tsent(command: PlayerCommand): void {\n\t\tthis.commands.push(command)\n\t}\n\n\tthought(): void {\n\t\tconst sent = this.commands\n\t\tthis.commands = []\n\t\tconst found: AiViolation[] = []\n\t\tconst say = (invariant: AiInvariant, message: string) => found.push({ invariant, player: this.brain.playerId, tick: this.brain.tick, message })\n\t\tif (this.invariants.has('squads')) this.squads(say)\n\t\tif (this.invariants.has('purse')) this.purse(say)\n\t\tif (this.invariants.has('finite')) this.finite(say)\n\t\tif (this.invariants.has('commands')) for (const command of sent) this.command(command, say)\n\t\tif (this.invariants.has('churn')) this.churn(sent, say)\n\t\tif (this.invariants.has('ends')) this.ends(say)\n\t\tfor (const violation of found) {\n\t\t\tthis.violations.push(violation)\n\t\t\tif (this.options.onViolation) this.options.onViolation(violation)\n\t\t\telse throw new Error(`The computer player ${violation.player} broke \"${violation.invariant}\" at tick ${violation.tick}: ${violation.message}`)\n\t\t}\n\t}\n\n\t/** A unit in at most one squad and one hold: two would give it two orders a think */\n\tprivate squads(say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { squads, goals } = this.brain\n\t\tconst inSquad = new Map<number, string>()\n\t\tfor (const squad of squads.all())\n\t\t\tfor (const id of squad.data.units) {\n\t\t\t\tconst other = inSquad.get(id)\n\t\t\t\tif (other !== undefined) say('squads', `unit ${id} is in the squads ${other} and ${squad.name}`)\n\t\t\t\telse inSquad.set(id, squad.name)\n\t\t\t}\n\t\tconst holder = new Map<number, string>()\n\t\tconst holds = goals.all()\n\t\tfor (const id in holds)\n\t\t\tfor (const unit of holds[id].units) {\n\t\t\t\tconst other = holder.get(unit)\n\t\t\t\tif (other !== undefined) say('squads', `unit ${unit} is held by ${other} and ${id}`)\n\t\t\t\telse holder.set(unit, id)\n\t\t\t}\n\t}\n\n\t/** What the think spent and what its builders will pay never more than what it had: else the same gold went twice */\n\tprivate purse(say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { purse, view } = this.brain\n\t\tconst had = view.me.resources\n\t\tfor (const kind of new Set([...Object.keys(purse.spent), ...Object.keys(purse.promised)])) {\n\t\t\tconst owed = (purse.spent[kind] ?? 0) + (purse.promised[kind] ?? 0)\n\t\t\tif (owed > (had[kind] ?? 0))\n\t\t\t\tsay('purse', `it spent ${purse.spent[kind] ?? 0} ${kind} and its builders will pay ${purse.promised[kind] ?? 0}, of ${had[kind] ?? 0}`)\n\t\t}\n\t}\n\n\t/** Every number a decision is made of is a number: a `NaN` compares false with everything and picks silently */\n\tprivate finite(say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { goals, squads, view } = this.brain\n\t\tfor (const goal of goals.report()) {\n\t\t\tif (!Number.isFinite(goal.score)) say('finite', `the goal ${goal.id} scores ${goal.score}`)\n\t\t\tfor (const each of goal.considerations)\n\t\t\t\tif (!Number.isFinite(each.value) || !Number.isFinite(each.curved))\n\t\t\t\t\tsay('finite', `the goal ${goal.id}'s ${each.name} is ${each.value} (${each.curved} curved)`)\n\t\t}\n\t\tfor (const squad of squads.all()) {\n\t\t\tconst strength = squad.strength()\n\t\t\tif (!Number.isFinite(strength)) say('finite', `the squad ${squad.name} is ${strength} strong`)\n\t\t}\n\t\tconst odds = view.strength.odds(view.mine.fighters(), view.enemies)\n\t\tif (!Number.isFinite(odds)) say('finite', `its odds against what it sees are ${odds}`)\n\t}\n\n\t/** A command about what its picture of the game has: its own units by theirs, anyone else's as seen, places on the map */\n\tprivate command(command: PlayerCommand, say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { view, session } = this.brain\n\t\tconst fields = command as unknown as Record<string, unknown>\n\t\tconst what = `its ${command.type} command`\n\t\tconst own = (id: unknown, field: string) => {\n\t\t\tif (typeof id !== 'number') return\n\t\t\tif (!view.byId(id)) say('commands', `${what} names ${field} ${id}, which it does not see`)\n\t\t\telse if (!view.mine.has(id)) say('commands', `${what} names ${field} ${id}, which is not its own`)\n\t\t}\n\t\tconst known = (id: unknown, field: string) => {\n\t\t\tif (typeof id === 'number' && !view.byId(id)) say('commands', `${what} names a ${field} ${id} it does not see`)\n\t\t}\n\t\tconst place = (at: unknown, field: string) => {\n\t\t\tif (!at || typeof at !== 'object') return\n\t\t\tconst { x, z } = at as Vec2\n\t\t\tconst { width, depth } = session.terrain\n\t\t\tif (!Number.isFinite(x) || !Number.isFinite(z) || x < 0 || z < 0 || x > width || z > depth)\n\t\t\t\tsay('commands', `${what} sends ${field} to (${x}, ${z}), off the map`)\n\t\t}\n\t\tfor (const field of OWN_ONE) own(fields[field], field)\n\t\tif (typeof fields.hero === 'number' && !view.me.heroes.some((hero) => hero.id === fields.hero)) own(fields.hero, 'hero')\n\t\tfor (const field of OWN_LIST) if (Array.isArray(fields[field])) for (const id of fields[field] as unknown[]) own(id, 'unit')\n\t\tfor (const field of KNOWN) known(fields[field], field)\n\t\tplace(fields.point, 'its point')\n\t\tconst order = fields.order as Record<string, unknown> | undefined\n\t\tif (order && typeof order === 'object') {\n\t\t\tknown(order.target, 'target')\n\t\t\tplace(order.point, `its ${String(order.type)}`)\n\t\t}\n\t}\n\n\t/** No order sent again for the same thing to a unit still at it: a unit told the same every think stops and starts */\n\tprivate churn(sent: readonly PlayerCommand[], say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { view, tick, session } = this.brain\n\t\tconst window = CHURN_WINDOW * session.tickRate\n\t\tfor (const command of sent) {\n\t\t\tconst key = orderKey(command)\n\t\t\tif (key === undefined || (command as { queue?: boolean }).queue) continue\n\t\t\tfor (const id of (command as { entities: readonly number[] }).entities) {\n\t\t\t\tconst last = this.orders.get(id)\n\t\t\t\t// still at it: carrying out an order of that kind. One that stands idle lost it (its target fell, its path\n\t\t\t\t// ended), one doing something else was taken off it: telling it again is right\n\t\t\t\tconst busy = view.byId(id)?.own?.order === kindOf(command)\n\t\t\t\tif (last && last.key === key && tick - last.tick <= window && busy)\n\t\t\t\t\tsay('churn', `unit ${id} was sent ${key} again ${((tick - last.tick) / session.tickRate).toFixed(1)} s after, still at it`)\n\t\t\t\tthis.orders.set(id, { key, tick })\n\t\t\t}\n\t\t}\n\t\tfor (const [id, last] of this.orders) if (tick - last.tick > window) this.orders.delete(id)\n\t}\n\n\t/** Builders, tasks, holds of money and blocked wants each end in time */\n\tprivate ends(say: (invariant: AiInvariant, message: string) => void): void {\n\t\tconst { view, squads, purse, plans, tick, session } = this.brain\n\t\tconst going = new Map<string, { limit: number; what: string; from?: number }>()\n\t\tfor (const unit of view.mine)\n\t\t\tif (unit.own?.build)\n\t\t\t\tgoing.set(`builder:${unit.id}:${unit.own.build}`, {\n\t\t\t\t\tlimit: this.limits.builder,\n\t\t\t\t\twhat: `worker ${unit.id} on its way to build a ${unit.own.build}`\n\t\t\t\t})\n\t\tfor (const squad of squads.all()) {\n\t\t\tconst task = squad.data.task\n\t\t\t// holding a place, or going with a unit (it follows as long as the unit lives): standing duties, never stuck; and\n\t\t\t// a task that says it is one (`TaskDef.standing`)\n\t\t\tif (\n\t\t\t\t!task ||\n\t\t\t\ttask.done !== undefined ||\n\t\t\t\ttask.phase === 'holding' ||\n\t\t\t\ttask.kind === 'hold' ||\n\t\t\t\t(task.kind === 'escort' && task.phase === 'going') ||\n\t\t\t\tsquads.taskDef(task.kind)?.standing\n\t\t\t)\n\t\t\t\tcontinue\n\t\t\t// the same units on the same task in the same phase: a squad whose units come and go (those fleeing) starts again\n\t\t\tgoing.set(`task:${squad.name}:${task.kind}:${task.since}:${task.phase}:${squad.data.units.join(',')}`, {\n\t\t\t\tlimit: this.limits.task,\n\t\t\t\twhat: `the squad ${squad.name} ${task.phase} on its ${task.kind}`,\n\t\t\t\tfrom: task.phaseSince\n\t\t\t})\n\t\t}\n\t\tfor (const id in purse.holdings()) going.set(`hold:${id}`, { limit: this.limits.reservation, what: `money held for ${id}` })\n\t\t// a want that cannot be got to (its tech out of reach), or one that does not stand and finds no spot or builder: a\n\t\t// standing want (`keep`) waits for room as long as it takes, which is no fault\n\t\tfor (const want of plans.build.report().wants) {\n\t\t\tconst stuck = want.status.startsWith('blocked') || (!want.keep && /^no (spot|builder)/.test(want.status))\n\t\t\tif (stuck) going.set(`want:${want.id}:${want.status}`, { limit: this.limits.want, what: `the want ${want.id} (${want.status})` })\n\t\t}\n\t\tfor (const key of [...this.since.keys()]) if (!going.has(key)) this.since.delete(key)\n\t\tfor (const key of [...this.said]) if (!going.has(key)) this.said.delete(key)\n\t\tfor (const [key, { limit, what, from }] of going) {\n\t\t\tif (!this.since.has(key)) this.since.set(key, from ?? tick)\n\t\t\tconst seconds = (tick - this.since.get(key)!) / session.tickRate\n\t\t\tif (seconds > limit && !this.said.has(key)) {\n\t\t\t\tthis.said.add(key)\n\t\t\t\tsay('ends', `${what} for ${Math.round(seconds)} s, past ${limit}`)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Checks a brain against the invariants after each of its thinks from now on: throws at the first broken rule, or tells\n * `onViolation` of each. Returns the checks (their `violations`) and the way to stop: what `watchComputer` does for a\n * seat, and every brain does by itself while `debugChecks.ai` is on\n *\n * const checks = checkBrain(brain, { onViolation: (each) => found.push(each) })\n *\n * @beta\n */\nexport function checkBrain(brain: Brain, options: AiCheckOptions = {}): { checks: BrainChecks; stop: () => void } {\n\tconst checks = new BrainChecks(brain, options)\n\treturn { checks, stop: brain.watch(checks) }\n}\n","/**\n * A kind of task a squad is on (design review B10): its definition (`TaskDef`, `defineTask`), typed by what it is given\n * (`TaskData`) and what it remembers (`TaskMemory`), and its state as the brain keeps it (`TaskState`). Apart from the\n * squads (`squads.ts`), so that the kit's tasks (`tasks/`) and a game's define theirs without loading the squads\n */\nimport type { Vec2 } from '#engine/math'\nimport type { Brain } from './brain'\nimport type { Squad } from './squads'\n\n/**\n * How a task ended (`TaskState.done`): `arrived` where it was sent, `cleared` with nothing left to fight where it went,\n * `lost` its target (gone from sight: killed, or out of it), `retreated` home after a fight it was losing, `wiped`\n * with none of its units left; or a game's own word\n *\n * @beta\n */\nexport type TaskDone = 'arrived' | 'cleared' | 'lost' | 'retreated' | 'wiped' | (string & {})\n\n/**\n * A task to give next (`then`): its kind (the kit's `attack`, a game's `defineTask` id) and what it is given\n *\n * @beta\n */\nexport interface TaskOrder {\n\tkind: string\n\tdata?: TaskData\n}\n\n/**\n * What any task may be given beside its own (`TaskState.data`): the task after it (`then`), and `regroup: false` for one\n * not stopped for its stragglers\n *\n * @beta\n */\nexport type TaskCommon = {\n\tthen?: TaskOrder\n\tregroup?: boolean\n}\n\n/**\n * What a task is given, as plain data (`TaskState.data`): each task says its own shape (`defineTask<Data>`)\n *\n * @beta\n */\nexport type TaskData = Record<string, unknown>\n\n/**\n * What a task remembers of its own, as plain data (`TaskState.memory`): each task says its own shape\n * (`defineTask<Data, Memory>`)\n *\n * @beta\n */\nexport type TaskMemory = Record<string, unknown>\n\n/**\n * What a squad is doing, as plain data kept in the brain's memory: the kind of task, what it was given, where it is in\n * it (`phase`: `going`, `regrouping`, `fighting`, `gathering`, `holding`, the task's own words), since when, the last\n * order it sent, and how it ended\n *\n * @beta\n */\nexport interface TaskState<D extends object = TaskData, M extends object = TaskMemory> {\n\t/** The kind of task: the kit's (`attack`) or a game's (`defineTask`) */\n\tkind: string\n\t/** What it was given: a point (`at`), a target, a radius, what to do next (`then`). Plain data, of the task's shape */\n\tdata: D & TaskCommon\n\t/** The tick it began at */\n\tsince: number\n\t/** Where it is in it, in a word */\n\tphase: string\n\t/** The tick its phase began at */\n\tphaseSince: number\n\t/** The tick it last sent an order */\n\tsent?: number\n\t/** How it ended: none while it goes on */\n\tdone?: TaskDone\n\t/** The tick it ended at */\n\tdoneAt?: number\n\t/** What the task remembers of its own, plain data of the task's shape: the point of a scout's round it is at */\n\tmemory: M\n}\n\n/**\n * A kind of task (`defineTask`): what it sends as it begins (`start`), what it looks at each think (`think`), and the\n * place it is about (`where`, for the squads module's regroup and reinforcements and for the report). The squads\n * module runs it with its own regroup, reinforce and retreat around it, but for what it `handles` itself\n *\n * @beta\n */\nexport interface TaskDef<D extends object = TaskData, M extends object = TaskMemory> {\n\t/** Unique among the brain's tasks: what a save names it by. The kit's are words (`attack`); a game's prefixed (`ctf.capture`) */\n\tid: string\n\t/**\n\t * Sends what puts the squad on its way: called as the task is given, and again as the squad goes on after a regroup.\n\t * Sets `state.phase`\n\t */\n\tstart(ai: Brain, squad: Squad, state: TaskState<D, M>): void\n\t/** Each think, after the squads module looked at the squad: watches how it goes, sends what was lost, `squad.finish(done)` when it is over */\n\tthink(ai: Brain, squad: Squad, state: TaskState<D, M>): void\n\t/** Whether it is over, asked each think before `think`: how it ended, or nothing while it goes on */\n\tdone?(ai: Brain, squad: Squad, state: TaskState<D, M>): TaskDone | undefined | false\n\t/** The place it is about: where reinforcements are sent, what the report shows. None for a task about no place */\n\twhere?(ai: Brain, squad: Squad, state: TaskState<D, M>): Vec2 | undefined\n\t/** What the squads module leaves to it: a task that regroups in its own way, or retreats never */\n\thandles?: readonly ('retreat' | 'regroup' | 'reinforce')[]\n\t/**\n\t * Whether it is a standing duty, going on as long as its squad has it (a hero walking a lane with its waves): never\n\t * stuck, whatever its phase, for the `ends` invariant (`checkBrain`). No when left out\n\t */\n\tstanding?: boolean\n\t/**\n\t * Whether a squad on it is in a fight it means to win, which the micro fights for (`ai.area(Micro)`): yes when left\n\t * out. No for a task that goes somewhere, looks, stands, gathers or falls back (the kit's `move`, `scout`, `hold`,\n\t * `gather`, `retreat`, and the micro's own `flee`)\n\t */\n\tfighting?: boolean\n}\n\n/**\n * Defines a task: a kind of thing a squad can be told to do (`squad.task(def, data)`, its data typed by the task), the\n * kit's and a game's own. List a game's in the brain's `settings.squads.tasks`, so that a squad on it goes on after a\n * load\n *\n * @beta\n */\nexport function defineTask<D extends object = TaskData, M extends object = TaskMemory>(id: string, def: Omit<TaskDef<D, M>, 'id'>): TaskDef<D, M> {\n\tif (!id) throw new Error('A task needs an id')\n\tif (typeof def.start !== 'function' || typeof def.think !== 'function') throw new Error(`The task \"${id}\" needs a start and a think`)\n\treturn { ...def, id }\n}\n","/**\n * What the kit's tasks share (design review B10): where a task's data says it goes, what is fighting near a place, how a\n * fight is gone to and watched, a way round, a walk's end\n */\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { Brain } from '../brain'\nimport { point, where } from '../geometry'\nimport { FIGHT_REACH } from '../reach'\nimport type { Squad } from '../squads'\nimport type { TaskDone, TaskState } from '../task'\nimport type { UnitSet } from '../view'\n\n/** How near the place it was sent to a squad is there */\nexport const ARRIVE = 8\n/** How near a place of its round a patrol is there, and a little more for each of its units (they stand round it) */\nexport const PATROL_ARRIVE = 4\n/** How near the place it was sent to look at a scout that stopped short is as near as the ground lets it: further is stuck */\nexport const SCOUT_NEAR = 16\n\n/**\n * What a task that fights somewhere is given (`attack`, `harass`, `creep`): a place, or a target (an entity, as it\n * goes), a way round their army (`avoid: 'army'`) or by a place (`via`)\n *\n * @beta\n */\nexport type FightData = {\n\tat?: Vec2\n\ttarget?: number\n\tavoid?: 'army' | false\n\tvia?: Vec2\n}\n\n/**\n * What a task that fights remembers: its way round, and the worker it hunts (`harass`)\n *\n * @beta\n */\nexport type FightMemory = {\n\trouted?: boolean\n\twaypoints?: Vec2[]\n\tprey?: number\n}\n\n/** Where a task's data says it goes: its target where it is in sight, else its place */\nexport function placeOf(ai: Brain, state: TaskState<FightData, FightMemory>): Vec2 | undefined {\n\tconst target = typeof state.data.target === 'number' ? ai.view.byId(state.data.target) : undefined\n\tif (target) return point(target)\n\treturn state.data.at\n}\n\n/** Whether a place is on the map */\nexport function onMap(ai: Brain, at: Vec2): boolean {\n\tconst { width, depth } = ai.session.terrain\n\treturn at.x >= 0 && at.z >= 0 && at.x < width && at.z < depth\n}\n\n/** What is hostile and alive near a place: what a squad there fights */\nexport function foesNear(ai: Brain, at: Vec2, radius = FIGHT_REACH): UnitSet {\n\treturn ai.view.hostile.alive().near(at, radius)\n}\n\n/**\n * Sets a task on its way to fight at its place: by the waypoints of a way round (`avoid`) where there are any, walking\n * them, then attack-moving there; else attack-moving, or attacking its target\n */\nexport function goFight(ai: Brain, squad: Squad, state: TaskState<FightData, FightMemory>): void {\n\tconst at = placeOf(ai, state)\n\tif (!at) return\n\tstate.phase = 'going'\n\tstate.phaseSince = ai.tick\n\tconst waypoints = state.memory.waypoints ?? []\n\tconst target = inSight(ai, state)\n\tconst units = squad.data.units\n\tif (waypoints.length) {\n\t\t// a waypoint already passed is not gone back to: the squad goes on from the next\n\t\tconst middle = squad.centre()\n\t\tconst next = middle ? waypoints.findIndex((each) => distSq(each, middle) > ARRIVE * ARRIVE) : 0\n\t\tconst left = next < 0 ? [] : waypoints.slice(next)\n\t\tleft.forEach((each, i) => squad.order({ type: 'move', point: each }, units, i > 0))\n\t\tif (left.length) {\n\t\t\tsquad.fight(at, units, target, true)\n\t\t\treturn\n\t\t}\n\t}\n\tsquad.fight(at, units, target)\n}\n\n/**\n * Watches a squad on its way to fight or fighting: done once there with nothing left to fight, or once its target is\n * gone; the units that stand idle short of it sent again\n */\nexport function watchFight(ai: Brain, squad: Squad, state: TaskState<FightData, FightMemory>): void {\n\tconst target = typeof state.data.target === 'number' ? state.data.target : undefined\n\tif (target !== undefined && !ai.view.byId(target)) {\n\t\tsquad.finish('lost')\n\t\treturn\n\t}\n\tconst at = placeOf(ai, state)\n\tif (!at || !onMap(ai, at)) {\n\t\tsquad.finish('lost')\n\t\treturn\n\t}\n\tconst middle = squad.centre()\n\tif (!middle) return\n\tconst fighting = foesNear(ai, middle).length > 0\n\tif (state.phase !== 'regrouping') {\n\t\tconst phase = fighting ? 'fighting' : 'going'\n\t\tif (phase !== state.phase) {\n\t\t\tstate.phase = phase\n\t\t\tstate.phaseSince = ai.tick\n\t\t}\n\t}\n\tif (!fighting && distSq(middle, at) < ARRIVE * ARRIVE && !foesNear(ai, at).length) {\n\t\tsquad.finish('cleared')\n\t\treturn\n\t}\n\tif (state.phase === 'regrouping' || !squad.mayResend()) return\n\t// what stands idle short of the place lost its order (a target fell, a path ended): on to the place again\n\tconst idle = squad.idleUnits().filter((unit) => distSq(unit, at) >= ARRIVE * ARRIVE || foesNear(ai, at).length > 0)\n\tif (idle.length)\n\t\tsquad.fight(\n\t\t\tat,\n\t\t\tidle.map((unit) => unit.id),\n\t\t\tinSight(ai, state)\n\t\t)\n}\n\n/**\n * A task's target where it is in sight, to attack it by name: a building remembered out of sight (`visible: false`)\n * cannot be told to be attacked, and is attack-moved to instead\n */\nexport function inSight(ai: Brain, state: TaskState<FightData, FightMemory>): number | undefined {\n\tif (typeof state.data.target !== 'number') return undefined\n\tconst entity = ai.view.byId(state.data.target)\n\treturn entity && entity.visible ? entity.id : undefined\n}\n\n/** Works out the way round for a task that avoids, as it begins: kept in its memory, said in the decision log */\nexport function planRoute(ai: Brain, squad: Squad, state: TaskState<FightData, FightMemory>): void {\n\t// a way of its own, given: by that place\n\tconst via = state.data.via\n\tif (via && !state.memory.routed) {\n\t\tstate.memory.routed = true\n\t\tstate.memory.waypoints = [point(via)]\n\t\treturn\n\t}\n\tif (state.data.avoid !== 'army' || state.memory.routed) return\n\tstate.memory.routed = true\n\tconst from = squad.centre()\n\tconst to = placeOf(ai, state)\n\tif (!from || !to) return\n\tconst { waypoints, note } = ai.squads.route(from, to, squad)\n\tif (waypoints.length) state.memory.waypoints = waypoints\n\tif (note) ai.decide(`squad ${squad.name} ${state.kind}s ${where(to)}: ${note}`, { kind: 'squad' })\n}\n\n/** The capture points of the game (`withCapture`), as the report tells the brain: none for a game without them */\nexport function capturePointsOf(ai: Brain): { id: string; owner: number | null; x: number; z: number }[] {\n\tconst listed = (ai.view.report as { captures?: unknown } | undefined)?.captures\n\treturn Array.isArray(listed) ? (listed as { id: string; owner: number | null; x: number; z: number }[]) : []\n}\n\n/**\n * A walk's think: done (as `done` says) once its middle is near the place, or once all of it stands idle as near as the\n * ground let it go; what stands idle short of it, while others walk on, is sent again\n */\nexport function arrive(done: TaskDone): (ai: Brain, squad: Squad, state: TaskState<{ at?: Vec2 }>) => void {\n\treturn (ai, squad, state) => {\n\t\tconst at = state.data.at\n\t\tconst middle = squad.centre()\n\t\tif (!at || !middle) {\n\t\t\tsquad.finish(done)\n\t\t\treturn\n\t\t}\n\t\tconst near = Math.max(ARRIVE / 2, squad.spread() / 2)\n\t\tconst idle = squad.idleUnits()\n\t\tif (\n\t\t\tdistSq(middle, at) <= near * near ||\n\t\t\t(ai.tick > state.phaseSince && idle.length === squad.data.units.length && distSq(middle, at) <= squad.spread() * squad.spread() * 4)\n\t\t) {\n\t\t\tsquad.finish(done)\n\t\t\treturn\n\t\t}\n\t\tif (idle.length && squad.mayResend())\n\t\t\tsquad.order(\n\t\t\t\t{ type: 'move', point: at },\n\t\t\t\tidle.map((unit) => unit.id)\n\t\t\t)\n\t}\n}\n","/**\n * The kit's `attack` task (design review B10): attacks a place or a target, by a way round where told: done `cleared` with nothing left to fight there, `lost` with its target gone\n */\nimport { defineTask } from '../task'\nimport { type FightData, type FightMemory, goFight, placeOf, planRoute, watchFight } from './shared'\n\n/**\n * Attacks a place or a target, by a way round where told: done `cleared` with nothing left to fight there, `lost` with its target gone\n *\n * @beta\n */\nexport const ATTACK = defineTask<FightData, FightMemory>('attack', {\n\tstart(ai, squad, state) {\n\t\tplanRoute(ai, squad, state)\n\t\tgoFight(ai, squad, state)\n\t},\n\tthink: watchFight,\n\twhere: (ai, _squad, state) => placeOf(ai, state)\n})\n","/**\n * The kit's `harass` task (design review B10): goes for the workers at a place, one at a time, round their army where told\n */\nimport { distSq } from '#engine/math'\nimport type { Micro } from '../micro'\nimport { FIGHT_REACH } from '../reach'\nimport { defineTask } from '../task'\nimport { type FightData, type FightMemory, goFight, placeOf, planRoute, watchFight } from './shared'\n\n/**\n * Goes for the workers at a place, one at a time, round their army where told\n *\n * @beta\n */\nexport const HARASS = defineTask<FightData, FightMemory>('harass', {\n\tstart(ai, squad, state) {\n\t\tplanRoute(ai, squad, state)\n\t\tgoFight(ai, squad, state)\n\t},\n\tthink(ai, squad, state) {\n\t\twatchFight(ai, squad, state)\n\t\tif (squad.done !== undefined || state.phase === 'regrouping') return\n\t\tconst at = placeOf(ai, state)!\n\t\tconst middle = squad.centre()\n\t\tif (!middle || distSq(middle, at) > FIGHT_REACH * FIGHT_REACH) return\n\t\t// once there, the workers first: what keeps their economy going\n\t\tconst workers = ai.view.enemies.units().alive().workers().near(at, FIGHT_REACH)\n\t\tconst prey = state.memory.prey\n\t\tif (prey !== undefined && workers.has(prey)) return\n\t\tconst next = workers.nearest(middle)\n\t\tif (!next) return\n\t\tstate.memory.prey = next.id\n\t\t// the micro module fighting for the squad sends whom it hits, the prey first (`Micro.target`): told by both, the\n\t\t// units would be told the same twice. Without it, the task sends\n\t\t// fought by its units where the micro does not take the squad (or the brain has none)\n\t\tif (!ai.made<Micro>('micro')?.manages(squad)) squad.fight(next, squad.data.units, next.id)\n\t},\n\twhere: (ai, _squad, state) => placeOf(ai, state)\n})\n","/**\n * The kit's `creep` task (design review B10): takes a camp of creeps: done `cleared` once the map says the camp is\n */\nimport { distSq } from '#engine/math'\nimport type { Vec2 } from '#engine/math'\nimport { defineTask } from '../task'\nimport { type FightMemory, goFight, watchFight } from './shared'\n\n/**\n * What the `creep` task is given: the camp\n *\n * @beta\n */\nexport type CreepData = {\n\tat: Vec2\n}\n\n/**\n * Takes a camp of creeps: done `cleared` once the map says the camp is\n *\n * @beta\n */\nexport const CREEP = defineTask<CreepData, FightMemory>('creep', {\n\tstart: goFight,\n\tthink(ai, squad, state) {\n\t\tconst at = state.data.at\n\t\t// cleared, as the map's camps say: the creeps gone, whatever stands about\n\t\tconst camp = ai.view.camps().find((each) => distSq(each, at) < 4 * 4)\n\t\tif (camp?.cleared) {\n\t\t\tsquad.finish('cleared')\n\t\t\treturn\n\t\t}\n\t\twatchFight(ai, squad, state)\n\t},\n\twhere: (_ai, _squad, state) => state.data.at\n})\n","/**\n * The kit's `defend` task (design review B10): holds a place against what comes within its radius, one foe at a time\n */\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { Micro } from '../micro'\nimport { defineTask } from '../task'\nimport { foesNear } from './shared'\n\n/** How far past the place a defender goes after a foe, as a share of the radius: past it, it comes back (AI1) */\nconst LEASH = 1.5\n\n/**\n * What the `defend` task is given\n *\n * @beta\n */\nexport type DefendData = {\n\tat: Vec2\n\t/** How far round the place it fights: 16 when left out */\n\tradius?: number\n}\n\n/**\n * What the `defend` task remembers\n *\n * @beta\n */\nexport type DefendMemory = {\n\t/** The foe the whole squad is on */\n\tfoe?: number\n}\n\n/**\n * Holds a place against what comes within its radius, one foe at a time\n *\n * @beta\n */\nexport const DEFEND_TASK = defineTask<DefendData, DefendMemory>('defend', {\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.fight(state.data.at)\n\t},\n\tthink(ai, squad, state) {\n\t\tconst at = state.data.at\n\t\tconst radius = state.data.radius ?? 16\n\t\tconst foes = foesNear(ai, at, radius).units()\n\t\tconst middle = squad.centre() ?? at\n\t\t// a defender that went after a foe past its leash, whatever it is on, comes back to the place: the foe runs home,\n\t\t// and the defender would follow it into their base (AI1)\n\t\tconst leash = radius * LEASH\n\t\tconst gone = squad\n\t\t\t.units()\n\t\t\t.filter((unit) => !unit.own?.hidden && distSq(unit, at) > leash * leash)\n\t\t\t.map((unit) => unit.id)\n\t\t// (those on their way back already are left to it: told again, the order would only be the same)\n\t\tconst back = squad\n\t\t\t.units()\n\t\t\t.filter((unit) => gone.includes(unit.id) && unit.own?.order !== 'move')\n\t\t\t.map((unit) => unit.id)\n\t\tif (back.length && squad.mayResend()) squad.order({ type: 'move', point: at }, back)\n\t\tconst here = gone.length ? squad.data.units.filter((id) => !gone.includes(id)) : squad.data.units\n\t\tif (foes.length) {\n\t\t\tstate.phase = 'fighting'\n\t\t\t// one foe at a time for the whole squad: chosen again when it is gone, or what stands idle is sent again. With\n\t\t\t// the micro module fighting for the squad (C2), it is the one that chooses, and writes whom here\n\t\t\tconst chosen = foes.find((foe) => foe.id === state.memory.foe)\n\t\t\tconst idle = squad.idleUnits().filter((unit) => !gone.includes(unit.id))\n\t\t\tif (chosen && !idle.length) return\n\t\t\tif (ai.made<Micro>('micro')?.manages(squad)) {\n\t\t\t\tif (idle.length && squad.mayResend())\n\t\t\t\t\tsquad.fight(\n\t\t\t\t\t\tchosen ?? foes.nearest(middle)!,\n\t\t\t\t\t\tidle.map((unit) => unit.id),\n\t\t\t\t\t\tchosen?.id\n\t\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst foe = chosen ?? foes.nearest(middle)!\n\t\t\tstate.memory.foe = foe.id\n\t\t\tsquad.fight(foe, chosen ? idle.map((unit) => unit.id) : here)\n\t\t\treturn\n\t\t}\n\t\tstate.phase = 'holding'\n\t\tdelete state.memory.foe\n\t\t// nothing to fight: back to the place, for those that wandered off after it\n\t\tif (!squad.mayResend()) return\n\t\tconst strayed = squad.units().filter((unit) => !unit.own?.order && distSq(unit, at) > (radius / 2) * (radius / 2))\n\t\tif (strayed.length)\n\t\t\tsquad.fight(\n\t\t\t\tat,\n\t\t\t\tstrayed.map((unit) => unit.id)\n\t\t\t)\n\t},\n\twhere: (_ai, _squad, state) => state.data.at,\n\thandles: ['regroup']\n})\n","/**\n * The kit's `hold` task (design review B10): stands its ground (defensive where the game has stances), where it is or at a place\n */\nimport { type Vec2 } from '#engine/math'\nimport { defineTask, type TaskMemory } from '../task'\n\n/**\n * What the `hold` task is given\n *\n * @beta\n */\nexport type HoldData = {\n\t/** Where it holds: where it stands when left out */\n\tat?: Vec2\n}\n\n/**\n * Stands its ground (defensive where the game has stances), where it is or at a place\n *\n * @beta\n */\nexport const HOLD = defineTask<HoldData, TaskMemory>('hold', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tconst at = state.data.at\n\t\tstate.phase = 'holding'\n\t\tstate.phaseSince = ai.tick\n\t\t// where the game has stances, a squad that holds is defensive: it fires at what comes, and keeps its place\n\t\tsquad.setStance('defensive')\n\t\tif (at) squad.order({ type: 'move', point: at })\n\t\tsquad.order({ type: 'hold' }, squad.data.units, !!at)\n\t},\n\tthink(_ai, squad, state) {\n\t\t// a hold that was lost (a unit pushed off and idle): held again where it stands\n\t\tconst idle = squad.idleUnits()\n\t\tif (idle.length && squad.mayResend())\n\t\t\tsquad.order(\n\t\t\t\t{ type: 'hold' },\n\t\t\t\tidle.map((unit) => unit.id)\n\t\t\t)\n\t\tvoid state\n\t},\n\twhere: (_ai, _squad, state) => state.data.at,\n\thandles: ['regroup']\n})\n","/**\n * The kit's `move` task (design review B10): walks to a place: done `arrived`\n */\nimport { type Vec2 } from '#engine/math'\nimport { defineTask, type TaskMemory } from '../task'\nimport { arrive } from './shared'\n\n/**\n * What the `move` task is given\n *\n * @beta\n */\nexport type MoveData = {\n\tat: Vec2\n}\n\n/**\n * Walks to a place: done `arrived`\n *\n * @beta\n */\nexport const MOVE = defineTask<MoveData, TaskMemory>('move', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.order({ type: 'move', point: state.data.at })\n\t},\n\tthink: arrive('arrived'),\n\twhere: (_ai, _squad, state) => state.data.at\n})\n","/**\n * The kit's `capture` task (design review B10): takes a capture point of the game (`withCapture`): done `captured`, or `lost` where it is gone\n */\nimport { type Vec2 } from '#engine/math'\nimport { defineTask, type TaskMemory } from '../task'\nimport { capturePointsOf } from './shared'\n\n/**\n * What the `capture` task is given\n *\n * @beta\n */\nexport type CaptureData = {\n\t/** The capture point, by id (`withCapture`) */\n\tpoint: string\n\tat?: Vec2\n}\n\n/**\n * Takes a capture point of the game (`withCapture`): done `captured`, or `lost` where it is gone\n *\n * @beta\n */\nexport const CAPTURE = defineTask<CaptureData, TaskMemory>('capture', {\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tconst at = state.data.at\n\t\tif (at) squad.fight(at)\n\t},\n\tthink(ai, squad, state) {\n\t\tconst found = capturePointsOf(ai).find((each) => each.id === state.data.point)\n\t\tif (!found) return squad.finish('lost')\n\t\tif (found.owner === ai.playerId) return squad.finish('captured')\n\t\tstate.data.at = { x: found.x, z: found.z }\n\t\t// what was pushed out, or stands idle short of it, is sent in again\n\t\tconst idle = squad.idleUnits()\n\t\tif (idle.length && squad.mayResend())\n\t\t\tsquad.fight(\n\t\t\t\t{ x: found.x, z: found.z },\n\t\t\t\tidle.map((unit) => unit.id)\n\t\t\t)\n\t},\n\twhere: (_ai, _squad, state) => state.data.at,\n\thandles: ['regroup', 'reinforce']\n})\n","/**\n * The kit's `retreat` task (design review B10): falls back to a place: done `retreated`\n */\nimport type { Vec2 } from '#engine/math'\nimport { defineTask, type TaskMemory } from '../task'\nimport { arrive } from './shared'\n\n/**\n * What the `retreat` task is given: where to (home when left out), and why, for the report\n *\n * @beta\n */\nexport type RetreatData = {\n\tat?: Vec2\n\twhy?: string\n}\n\n/**\n * Falls back to a place: done `retreated`\n *\n * @beta\n */\nexport const RETREAT = defineTask<RetreatData, TaskMemory>('retreat', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tconst at = state.data.at\n\t\tif (at) squad.order({ type: 'move', point: at })\n\t},\n\tthink: arrive('retreated'),\n\twhere: (_ai, _squad, state) => state.data.at,\n\thandles: ['retreat', 'regroup']\n})\n","/**\n * The kit's `escort` task (design review B10): follows a unit and fights what comes near it: done `lost` with it gone\n */\nimport { point } from '../geometry'\nimport { FIGHT_REACH } from '../reach'\nimport { defineTask, type TaskMemory } from '../task'\nimport { foesNear } from './shared'\n\n/**\n * What the `escort` task is given\n *\n * @beta\n */\nexport type EscortData = {\n\t/** Whom it follows */\n\ttarget: number\n}\n\n/**\n * Follows a unit and fights what comes near it: done `lost` with it gone\n *\n * @beta\n */\nexport const ESCORT = defineTask<EscortData, TaskMemory>('escort', {\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.order({ type: 'follow', target: state.data.target })\n\t},\n\tthink(ai, squad, state) {\n\t\tconst target = ai.view.byId(state.data.target)\n\t\tif (!target || target.hp <= 0) {\n\t\t\tsquad.finish('lost')\n\t\t\treturn\n\t\t}\n\t\tconst foes = foesNear(ai, target, FIGHT_REACH)\n\t\tif (foes.length) {\n\t\t\t// what comes near it is fought; once gone, it is followed again\n\t\t\tif (state.phase !== 'fighting') {\n\t\t\t\tstate.phase = 'fighting'\n\t\t\t\tstate.phaseSince = ai.tick\n\t\t\t\tsquad.fight(target)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tconst idle = squad.idleUnits()\n\t\tconst fought = state.phase === 'fighting'\n\t\tif (fought || (idle.length && squad.mayResend())) {\n\t\t\tstate.phase = 'going'\n\t\t\tstate.phaseSince = ai.tick\n\t\t\t// after a fight, those not following it already (one that never left it is not told again); else those idle\n\t\t\tconst off = fought ? squad.units().filter((unit) => unit.own?.order !== 'follow') : idle\n\t\t\tif (off.length)\n\t\t\t\tsquad.order(\n\t\t\t\t\t{ type: 'follow', target: target.id },\n\t\t\t\t\toff.map((unit) => unit.id)\n\t\t\t\t)\n\t\t}\n\t},\n\twhere: (ai, _squad, state) => {\n\t\tconst target = ai.view.byId(state.data.target)\n\t\treturn target && point(target)\n\t},\n\thandles: ['regroup']\n})\n","/**\n * The kit's `scout` task (design review B10): looks at places in turn: done `arrived` after the last\n */\nimport { distSq, type Vec2 } from '#engine/math'\nimport { CHURN_WINDOW } from '../checks'\nimport { defineTask } from '../task'\nimport { SCOUT_NEAR } from './shared'\n\n/**\n * What the `scout` task is given\n *\n * @beta\n */\nexport type RoundData = {\n\tpoints: Vec2[]\n}\n\n/**\n * What the `scout` task remembers\n *\n * @beta\n */\nexport type RoundMemory = {\n\t/** The place of the round it is on */\n\tnext?: number\n\t/** Times it was sent again to a place it stopped short of */\n\ttries?: number\n}\n\n/**\n * Looks at places in turn: done `arrived` after the last\n *\n * @beta\n */\nexport const SCOUT_TASK = defineTask<RoundData, RoundMemory>('scout', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tconst points = state.data.points\n\t\tconst next = state.memory.next ?? 0\n\t\tstate.memory.next = next\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tif (points[next]) squad.order({ type: 'move', point: points[next] })\n\t},\n\tthink(ai, squad, state) {\n\t\tconst points = state.data.points\n\t\tlet next = state.memory.next ?? 0\n\t\tconst knows = ai.def.knowledge !== false\n\t\tconst at = points[next]\n\t\tif (!at) {\n\t\t\tsquad.finish('arrived')\n\t\t\treturn\n\t\t}\n\t\t// in sight now, or as near as the ground let it go: that is as looked at as it gets, and on to the next. Stopped\n\t\t// far from it (stuck on the way), it is sent again twice (once a few seconds have gone since it was last sent), then\n\t\t// the place is passed over, not counted as looked at\n\t\tconst seen = knows && ai.knowledge.map.inSight(at)\n\t\tconst stopped = ai.tick > state.phaseSince && squad.idleUnits().length === squad.data.units.length\n\t\tif (!seen && !stopped) return\n\t\tif (!seen) {\n\t\t\tconst middle = squad.centre()\n\t\t\tconst near = !!middle && distSq(middle, at) <= SCOUT_NEAR * SCOUT_NEAR\n\t\t\tif (!near) {\n\t\t\t\tconst tries = (state.memory.tries ?? 0) + 1\n\t\t\t\t// not sooner than a unit may be told the same again without its stopping and starting (`AiStats.churn`)\n\t\t\t\tif (tries <= 2 && ai.tick - state.phaseSince <= CHURN_WINDOW * ai.session.tickRate) return\n\t\t\t\tstate.memory.tries = tries\n\t\t\t\tif (tries <= 2) {\n\t\t\t\t\tstate.phaseSince = ai.tick\n\t\t\t\t\tsquad.order({ type: 'move', point: at })\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else if (knows) ai.knowledge.map.look(at)\n\t\t}\n\t\tdelete state.memory.tries\n\t\tnext++\n\t\tstate.memory.next = next\n\t\tif (next >= points.length) {\n\t\t\tsquad.finish('arrived')\n\t\t\treturn\n\t\t}\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.order({ type: 'move', point: points[next] })\n\t},\n\twhere: (_ai, _squad, state) => state.data.points[state.memory.next ?? 0],\n\t// it goes to look, not to fight: it does not turn back at the sight of them\n\thandles: ['regroup', 'retreat']\n})\n","/**\n * The kit's `patrol` task (design review B10): walks a round of places for ever, fighting what it meets\n */\nimport { distSq } from '#engine/math'\nimport { defineTask } from '../task'\nimport { foesNear, PATROL_ARRIVE } from './shared'\nimport type { RoundData } from './scout'\nimport type { RoundMemory } from './scout'\n\n/**\n * Walks a round of places for ever, fighting what it meets\n *\n * @beta\n */\nexport const PATROL = defineTask<RoundData, RoundMemory>('patrol', {\n\tstart(ai, squad, state) {\n\t\tconst points = state.data.points\n\t\tconst next = state.memory.next ?? 0\n\t\tstate.memory.next = next\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tif (points[next]) squad.fight(points[next])\n\t},\n\tthink(ai, squad, state) {\n\t\tconst points = state.data.points\n\t\tif (!points.length) {\n\t\t\tsquad.finish('lost')\n\t\t\treturn\n\t\t}\n\t\tlet next = state.memory.next ?? 0\n\t\tconst middle = squad.centre()\n\t\tif (!middle) return\n\t\tconst fighting = foesNear(ai, middle).length > 0\n\t\tif (state.phase !== 'regrouping') {\n\t\t\tconst phase = fighting ? 'fighting' : 'going'\n\t\t\tif (phase !== state.phase) {\n\t\t\t\tstate.phase = phase\n\t\t\t\tstate.phaseSince = ai.tick\n\t\t\t}\n\t\t}\n\t\tif (state.phase === 'regrouping') return\n\t\tconst at = points[next]\n\t\t// there, with nothing to fight: on to the next place of the round, the first after the last\n\t\tconst there = PATROL_ARRIVE + Math.sqrt(squad.data.units.length)\n\t\tif (!fighting && distSq(middle, at) < there * there) {\n\t\t\tnext = (next + 1) % points.length\n\t\t\tstate.memory.next = next\n\t\t\tstate.phaseSince = ai.tick\n\t\t\tsquad.fight(points[next])\n\t\t\treturn\n\t\t}\n\t\t// what stands idle short of it lost its order (a fight over, a path ended): on to the place again\n\t\tif (!squad.mayResend()) return\n\t\tconst idle = squad.idleUnits().filter((unit) => distSq(unit, at) >= there * there)\n\t\tif (idle.length)\n\t\t\tsquad.fight(\n\t\t\t\tat,\n\t\t\t\tidle.map((unit) => unit.id)\n\t\t\t)\n\t},\n\twhere: (_ai, _squad, state) => state.data.points[state.memory.next ?? 0]\n})\n","/**\n * The kit's `gather` task (design review B10): gathers at a rally: done `arrived` once enough are there, or the time is up\n */\nimport { distSq, type Vec2 } from '#engine/math'\nimport { defineTask, type TaskMemory } from '../task'\n\n/**\n * What the `gather` task is given\n *\n * @beta\n */\nexport type GatherData = {\n\tat: Vec2\n\t/** The share of the squad there that is enough: all when left out */\n\tminForces?: number\n\t/** Seconds it waits at most */\n\tseconds?: number\n}\n\n/**\n * Gathers at a rally: done `arrived` once enough are there, or the time is up\n *\n * @beta\n */\nexport const GATHER = defineTask<GatherData, TaskMemory>('gather', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'gathering'\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.order({ type: 'move', point: state.data.at })\n\t},\n\tthink(ai, squad, state) {\n\t\tconst at = state.data.at\n\t\tconst units = squad.units()\n\t\tconst spread = squad.spread()\n\t\tconst there = units.filter((unit) => distSq(unit, at) <= spread * spread).length\n\t\tconst share = state.data.minForces ?? 1\n\t\tconst seconds = state.data.seconds\n\t\tconst ready = there >= Math.max(1, Math.ceil(squad.data.size * share))\n\t\tconst waited = seconds !== undefined && ai.tick - state.since >= seconds * ai.session.tickRate\n\t\tif (ready || waited) {\n\t\t\tsquad.finish('arrived')\n\t\t\treturn\n\t\t}\n\t\t// those that came in since, or stood idle elsewhere: to the rally\n\t\tconst lost = squad.idleUnits().filter((unit) => distSq(unit, at) > spread * spread)\n\t\tif (lost.length && squad.mayResend())\n\t\t\tsquad.order(\n\t\t\t\t{ type: 'move', point: at },\n\t\t\t\tlost.map((unit) => unit.id)\n\t\t\t)\n\t},\n\twhere: (_ai, _squad, state) => state.data.at,\n\thandles: ['regroup']\n})\n","/**\n * The kit's `drop` task: a squad carried by transports to a place it cannot walk to (an island, across a river, behind\n * the enemy's walls), let out on the land nearest it: done `landed`, its `then` after (an attack where it landed)\n */\nimport { type Vec2 } from '#engine/math'\nimport type { Squad } from '../squads'\nimport { defineTask } from '../task'\n\n/**\n * What the `drop` task is given: where it lands, and the transports that carry it (the brain's units, not of the\n * squad: they are let go of once they have let it out)\n *\n * @beta\n */\nexport type DropData = {\n\tat: Vec2\n\ttransports: number[]\n}\n\n/**\n * What the `drop` task remembers: since when it waits for its units to get in\n *\n * @beta\n */\nexport type DropMemory = {\n\t/** When it began to wait for its units to get in, in seconds of the game */\n\twaiting?: number\n\t/** When the transports were sent off, in seconds of the game */\n\tsailed?: number\n}\n\n/** Seconds it waits for its units to get in before it sails with those that did */\nconst BOARDING_WAIT = 20\n/** Seconds after the transports are sent off before their having no order is taken for their having stopped */\nconst SEEN_AFTER = 2\n\n/** The transports of the task that are still the brain's and afloat, with room or not */\nconst transportsOf = (squad: Squad, ids: readonly number[]) => {\n\tconst { view } = squad.squads.ai\n\treturn ids.filter((id) => view.mine.has(id) && (view.byId(id)?.hp ?? 0) > 0)\n}\n\n/**\n * Carries the squad to a place by its transports: each unit told to get into one (shared out as they have room), the\n * transports sent off once all are in (or after `BOARDING_WAIT` seconds, with those that are), and told to let them out\n * on the land nearest the place. Done `landed` once they are all out; `lost` with no transport left to carry them\n *\n * @beta\n */\nexport const DROP = defineTask<DropData, DropMemory>('drop', {\n\tfighting: false,\n\t// aboard, the squad is nowhere to regroup at, nor to reinforce or retreat from\n\thandles: ['regroup', 'retreat', 'reinforce'],\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'boarding'\n\t\tstate.phaseSince = ai.tick\n\t\tstate.memory.waiting = ai.time\n\t\tconst transports = transportsOf(squad, state.data.transports)\n\t\tif (!transports.length) return\n\t\t// shared out in turn: the first to the first, the second to the second...\n\t\tsquad.data.units.forEach((unit, i) => squad.order({ type: 'board', target: transports[i % transports.length] }, [unit]))\n\t},\n\tthink(ai, squad, state) {\n\t\tconst { view } = ai\n\t\tconst transports = transportsOf(squad, state.data.transports)\n\t\tconst units = [...squad.units()]\n\t\tconst aboard = units.filter((unit) => unit.own?.hidden)\n\t\tif (!units.length) return\n\t\tif (state.phase === 'boarding') {\n\t\t\tif (!transports.length) return squad.finish('lost')\n\t\t\tconst waited = ai.time - (state.memory.waiting ?? ai.time)\n\t\t\tif (aboard.length < units.length && waited < BOARDING_WAIT) return\n\t\t\tif (!aboard.length) return squad.finish('lost')\n\t\t\tstate.phase = 'sailing'\n\t\t\tstate.phaseSince = ai.tick\n\t\t\tstate.memory.sailed = ai.time\n\t\t\tai.send({ type: 'order', entities: transports, order: { type: 'unload', point: state.data.at } })\n\t\t\treturn\n\t\t}\n\t\t// sailing: done once every unit that got in is out again\n\t\tif (!aboard.length) {\n\t\t\tsquad.finish('landed')\n\t\t\treturn\n\t\t}\n\t\t// (the order sent is seen a think or two later: not taken for one stopped short meanwhile)\n\t\tif (ai.time - (state.memory.sailed ?? ai.time) < SEEN_AFTER) return\n\t\tif (!transports.length || transports.every((id) => !view.byId(id)?.own?.order)) {\n\t\t\t// the transports stopped short of it (no land in reach there): let out wherever they are\n\t\t\tif (transports.length) ai.send({ type: 'order', entities: transports, order: { type: 'unload' } })\n\t\t\telse squad.finish('lost')\n\t\t}\n\t},\n\twhere: (_ai, _squad, state) => state.data.at\n})\n","/**\n * The kit's tasks (design review B10), one file each, listed for every brain's squads (`Squads`)\n */\nimport type { TaskDef } from '../task'\nimport { ATTACK } from './attack'\nimport { HARASS } from './harass'\nimport { CREEP } from './creep'\nimport { DEFEND_TASK } from './defend'\nimport { HOLD } from './hold'\nimport { MOVE } from './move'\nimport { CAPTURE } from './capture'\nimport { RETREAT } from './retreat'\nimport { ESCORT } from './escort'\nimport { SCOUT_TASK } from './scout'\nimport { PATROL } from './patrol'\nimport { GATHER } from './gather'\nimport { DROP } from './drop'\n\n/** The kit's tasks, by their word */\nexport const TASKS: readonly TaskDef[] = [ATTACK, HARASS, CREEP, DEFEND_TASK, HOLD, MOVE, CAPTURE, RETREAT, ESCORT, SCOUT_TASK, PATROL, GATHER, DROP]\n\nexport { ATTACK } from './attack'\nexport { HARASS } from './harass'\nexport { CREEP } from './creep'\nexport { DEFEND_TASK } from './defend'\nexport { HOLD } from './hold'\nexport { MOVE } from './move'\nexport { CAPTURE } from './capture'\nexport { RETREAT } from './retreat'\nexport { ESCORT } from './escort'\nexport { SCOUT_TASK } from './scout'\nexport { PATROL } from './patrol'\nexport { GATHER } from './gather'\nexport { DROP } from './drop'\nexport type { DropData, DropMemory } from './drop'\nexport { type FightData, type FightMemory } from './shared'\nexport type { DefendData } from './defend'\nexport type { DefendMemory } from './defend'\nexport type { HoldData } from './hold'\nexport type { MoveData } from './move'\nexport type { CaptureData } from './capture'\nexport type { EscortData } from './escort'\nexport type { RoundData } from './scout'\nexport type { RoundMemory } from './scout'\nexport type { GatherData } from './gather'\nexport type { CreepData } from './creep'\nexport type { RetreatData } from './retreat'\n","import type { Layer } from '#engine/defs'\nimport type { OrderInit } from '#engine/registry'\nimport type { AiArea } from './area'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { DEFAULT_STANCE, stance, stanceCommand } from '#engine/stances'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { UnitSet } from './view'\nimport { ATTACK, CAPTURE, CREEP, DEFEND_TASK, DROP, ESCORT, GATHER, HARASS, HOLD, MOVE, PATROL, RETREAT, SCOUT_TASK, TASKS } from './tasks'\nimport type { TaskCommon, TaskData, TaskDef, TaskDone, TaskOrder, TaskState } from './task'\nimport { capturePointsOf } from './tasks/shared'\nimport { heroOfState } from '#engine/hero'\nimport { pair, plural, point, where } from './geometry'\nimport { ENGAGED, FIGHT_REACH, RESEND } from './reach'\n\n/*\n * Squads and their tasks (AI plan, C1): the unit of command. A goal that holds units (B1) used to send them all one\n * order and hope; two goals could send one unit two ways in a think, and nothing watched an order once it was sent.\n * A **squad** is a named group of the player's units with one **task** (attack there, defend here, gather at the rally\n * and then go): the goal, rule or module that made it says what, once, and the squads module (`squads()`) sees it\n * done, think after think:\n *\n * - **An order is sent once and watched.** A unit told to attack-move every second never arrives: it stops and\n * starts. A task sends its orders as it begins, then each think looks at how it goes (where the squad is, whether a\n * unit stands idle short of where it was sent, whether its target is still there) and sends again only what was lost.\n * - **A squad regroups when spread.** Units walk at different speeds: a column of footmen and knights arrives one by\n * one and is beaten one by one. When too many of its units (`regroupWhen`, four tenths) are further than `spread`\n * from its middle, on its way and out of a fight, the squad gathers on its middle, then goes on.\n * - **A squad retreats when it is losing.** In a fight away from home, with its odds (`Strength.odds`, A4) under\n * `retreatAt` (three tenths), it falls back home (the classic Groups Flee): the task becomes `retreat`, done\n * (`retreated`) once home. Whoever made it decides what next.\n * - **A squad is reinforced** (`reinforce`): what it lost since its task began is made up from the pool (the fighters\n * nothing holds, idle), the nearest first, sent to join it.\n *\n * **Who may move a unit.** The goals' holds are the one place that says (B1): a unit is held by one goal, rule or\n * module at a time (`ai.goals.holder`), and a squad is made of what its **owner** holds. A squad made in a goal's\n * `run` with `claimed.squad` is the goal's: when the goal stops, its squads go; a unit another goal took leaves the squad\n * that think. A squad made anywhere else (a rule, a module) holds its units itself, until it is disbanded (`take`\n * with `seconds: Infinity`, under `squad:<name>` or the owner it names), taking them from whatever goal had them,\n * which is told (`stop('told')`). A unit is in one squad at a time: a squad made of units of another takes them out\n * of it.\n *\n * Tasks are plain data (`TaskState`: its kind, what it was given, its phase, when it began, its own memory), kept in\n * the brain's memory with the squads, so that a save keeps the army on its way. The kit's tasks (`attack`, `defend`,\n * `hold`, `move`, `escort`, `harass`, `scout`, `gather`, `retreat`, `creep`, `patrol`) send the engine's orders; a game's own is\n * `defineTask` (a capture, a garrison, an order of the game's), run with the same regroup, reinforce and retreat\n * around it unless it says it `handles` them.\n */\n\n/** Seconds a squad waits for its stragglers at most, regrouping, before it goes on with what it has */\nconst REGROUP_FOR = 10\n/** Seconds between two calls for reinforcements */\nconst REINFORCE_EVERY = 5\n/** How far aside of the hottest place on its way a squad that avoids looks for a way round, then half as far again */\nconst DETOUR = 24\n/** Seconds a sighting of their army counts as where it is, for a squad that avoids it */\nconst AVOID_SEEN = 60\n\n/**\n * How a squad behaves around its task (`SquadsOptions`, `ai.squads.make(name, units, options)`): when it regroups,\n * reinforces, retreats. Plain data, kept in a save\n *\n * @beta\n */\nexport interface SquadOptions {\n\t/**\n\t * How far from its middle a unit may be before it counts as strayed: what a regroup brings in. Grows with the squad\n\t * when left out (8, and three times the square root of its size above that: 12 for sixteen units)\n\t */\n\tspread?: number\n\t/** The share of its units strayed (`spread`) at which it stops to regroup, on its way and out of a fight: 0.4. `false` never */\n\tregroupWhen?: number | false\n\t/** Whether it makes up what it lost since its task began from the pool (the idle fighters nothing holds): no when left out */\n\treinforce?: boolean\n\t/**\n\t * Its odds in a fight (`Strength.odds`) under which it falls back home, away from home: 0.3. `false` fights on to the\n\t * last (a mission's guards)\n\t */\n\tretreatAt?: number | false\n\t/** How near home it fights on whatever the odds: there is nowhere to fall back to. 20 when left out */\n\thome?: number\n\t/**\n\t * Whether the micro module (`micro()`, C2) fights for it once it is in a fight: focus fire, kiting, fleeing, siege.\n\t * Yes when left out; `false` for a squad left to its units (a scout, a mission's guards on an order of the game's)\n\t */\n\tmicro?: boolean\n}\n\n/**\n * How a brain's squads behave, where a squad says nothing for itself (`BrainDef.squads`, the seat's `AiOptions.squads`\n * over it); and the tasks of the game's own (`defineTask`) a save of the brain may name\n *\n * @beta\n */\nexport interface SquadsOptions extends SquadOptions {\n\t/** Tasks of the game's own: registered with the brain, so that a squad on one is carried on after a load */\n\ttasks?: TaskDef[]\n}\n\n/**\n * A squad as the brain remembers it: plain data, kept in a save\n *\n * @beta\n */\nexport interface SquadData {\n\t/** Unique among the brain's squads */\n\tname: string\n\t/** Who it belongs to: a goal's id, a rule's or a module's hold (`squad:<name>` for one of its own) */\n\towner: string\n\t/** Its units, by id, in the picture's order */\n\tunits: number[]\n\t/** How it behaves: its own, over the brain's */\n\toptions: SquadOptions\n\t/** What it is doing. None for a squad told nothing yet */\n\ttask?: TaskState\n\t/** How many units its task began with, or was given since: what reinforcements make up */\n\tsize: number\n\t/** The tick it was made at */\n\tmade: number\n\t/** How many times it fell back from a fight it was losing */\n\tretreats: number\n\t/** The last time its units or its task changed, and why, in words */\n\tchanged?: { tick: number; why: string }\n\t/** The tick it may next call for reinforcements */\n\tnextReinforce?: number\n}\n\n/**\n * What the squads remember between thinks, for a save\n *\n * @beta\n */\nexport interface SquadsMemory {\n\tv: 1\n\tsquads: SquadData[]\n}\n\n/**\n * A squad as the report shows it: who it belongs to, its units and their strength, where it is, its task and how it goes\n *\n * @beta\n */\nexport interface SquadReport {\n\tname: string\n\towner: string\n\tunits: number[]\n\tstrength: number\n\t/** Its middle */\n\tat?: [number, number]\n\tsize: number\n\ttask?: { kind: string; phase: string; since: number; at?: [number, number]; done?: TaskDone }\n\tretreats: number\n\tchanged?: { tick: number; why: string }\n}\n\n/**\n * A squad of the brain (`ai.squads.make`, `named`, `all`): a handle over its data, with the task methods. A squad's\n * units are as of the think's picture: the dead and those its owner no longer holds are dropped as the squads module\n * looks at it\n *\n * @beta\n */\nexport class Squad {\n\tconstructor(\n\t\t/** The squads it is one of */\n\t\treadonly squads: Squads,\n\t\t/** What it is, as plain data: what a save keeps */\n\t\treadonly data: SquadData\n\t) {}\n\n\t/** Its name: unique among the brain's squads */\n\tget name(): string {\n\t\treturn this.data.name\n\t}\n\n\t/** Who it belongs to: the goal, rule or module that made it */\n\tget owner(): string {\n\t\treturn this.data.owner\n\t}\n\n\t/** What it is doing: none for a squad told nothing yet */\n\tget current(): TaskState | undefined {\n\t\treturn this.data.task\n\t}\n\n\t/** How its task ended: none while it goes on, or while it has none */\n\tget done(): TaskDone | undefined {\n\t\treturn this.data.task?.done\n\t}\n\n\t/** Whether it has nothing to do: no task, or its task is over */\n\tget idle(): boolean {\n\t\treturn !this.data.task || this.data.task.done !== undefined\n\t}\n\n\t/** Whether it is still one of the brain's squads: not once disbanded */\n\tget alive(): boolean {\n\t\treturn this.squads.named(this.data.name) === this\n\t}\n\n\t/** How it behaves: its own options over the brain's */\n\tget options(): SquadOptions {\n\t\treturn this.data.options\n\t}\n\n\t/** Its units, as of the think's picture: those alive and the player's */\n\tunits(): UnitSet {\n\t\tconst { view } = this.squads.ai\n\t\treturn new UnitSet(\n\t\t\tview,\n\t\t\tthis.data.units.map((id) => view.byId(id)).filter((unit): unit is EntityState => !!unit && unit.hp > 0)\n\t\t)\n\t}\n\n\t/** How many units it has */\n\tget length(): number {\n\t\treturn this.data.units.length\n\t}\n\n\t/** How strong it is together (`UnitSet.strength`) */\n\tstrength(): number {\n\t\treturn this.units().strength()\n\t}\n\n\t/** Its middle: none with no unit left */\n\tcentre(): Vec2 | undefined {\n\t\treturn this.units().centre()\n\t}\n\n\t/**\n\t * How far from its middle a unit may be before it counts as strayed (`SquadOptions.spread`): grows with the squad\n\t * when not given\n\t */\n\tspread(): number {\n\t\treturn this.data.options.spread ?? Math.max(8, 3 * Math.sqrt(this.data.units.length))\n\t}\n\n\t/** Adds units: what its owner may have (see `Squads.make`), taken out of any other squad */\n\tadd(units: Iterable<EntityState | number>, why = 'given'): this {\n\t\tconst added = this.squads.enlist(this, ids(units))\n\t\tif (added.length) {\n\t\t\tthis.data.size = Math.max(this.data.size, this.data.units.length)\n\t\t\tthis.changed(`${why}: ${plural(added.length)}`)\n\t\t}\n\t\treturn this\n\t}\n\n\t/** Takes units out: they go back to the pool (its owner lets go of them) */\n\tremove(units: Iterable<EntityState | number>, why = 'taken out'): this {\n\t\tconst gone = new Set(ids(units))\n\t\tconst removed = this.data.units.filter((id) => gone.has(id))\n\t\tif (!removed.length) return this\n\t\tthis.data.units = this.data.units.filter((id) => !gone.has(id))\n\t\tthis.squads.ai.goals.drop(this.data.owner, removed)\n\t\tthis.changed(`${why}: ${plural(removed.length)}`)\n\t\treturn this\n\t}\n\n\t/** Disbands it: its units go back to its owner (a goal's), or to the pool (a squad of its own) */\n\tdisband(why = 'disbanded'): void {\n\t\tthis.squads.disband(this, why)\n\t}\n\n\t/** Writes down the last change of its units or task, for the report */\n\tchanged(why: string): void {\n\t\tthis.data.changed = { tick: this.squads.ai.tick, why }\n\t}\n\n\t/**\n\t * Gives it a task: one of the kit's by its word (`attack`), or of the game's (`defineTask`, by its def or its id).\n\t * What it was doing is over. Its first orders go at once; the squads module watches it from then on\n\t */\n\ttask<D extends object, M extends object>(def: TaskDef<D, M>, data: D & TaskCommon): this\n\ttask(kind: string, data?: TaskData): this\n\ttask(kind: string | TaskDef, data: TaskData = {}): this {\n\t\tthis.squads.give(this, kind, data)\n\t\treturn this\n\t}\n\n\t/** Ends its task, saying how: what a task's `think` calls once it is over */\n\tfinish(done: TaskDone): void {\n\t\tconst state = this.data.task\n\t\tif (!state || state.done !== undefined) return\n\t\tstate.done = done\n\t\tstate.doneAt = this.squads.ai.tick\n\t\tstate.phase = 'done'\n\t\tstate.phaseSince = this.squads.ai.tick\n\t}\n\n\t/**\n\t * Goes to fight at a place or a target (an entity, or its id): attack-moves there, fighting what it meets, regroups\n\t * on the way, retreats on the odds. Done `cleared` once there with nothing left to fight, `lost` when the target is\n\t * gone. `avoid: 'army'` goes round where their strength is on the way (the threat map and their army as last seen),\n\t * when there is a way round. `via`: a place to go by on the way (a way of its own: Random Paths). `then`: the task after it\n\t */\n\tattack(target: Vec2 | EntityState | number, options: { avoid?: 'army' | false; via?: Vec2; then?: TaskOrder } = {}): this {\n\t\treturn this.task(ATTACK, { ...targetOf(this.squads.ai, target), ...options })\n\t}\n\n\t/** Attack-moves to a place, as a group of units would on a click: the squad's attack without its regroup */\n\tattackMove(at: Vec2, options: { then?: TaskOrder } = {}): this {\n\t\treturn this.task(ATTACK, { at: point(at), regroup: false, ...options })\n\t}\n\n\t/**\n\t * Holds a place against what comes within `radius` of it (16 when left out): fights what comes, goes back once it is\n\t * gone. Never over by itself: its owner says when\n\t */\n\tdefend(at: Vec2, radius = 16): this {\n\t\treturn this.task(DEFEND_TASK, { at: point(at), radius })\n\t}\n\n\t/** Goes to a place (where it stands when left out) and holds it: stands, fighting only what comes within reach */\n\thold(at?: Vec2): this {\n\t\tconst there = at ?? this.centre()\n\t\treturn this.task(HOLD, there ? { at: point(there) } : {})\n\t}\n\n\t/** Walks to a place, fighting nothing on the way. Done `arrived` */\n\tmove(at: Vec2, options: { then?: TaskOrder } = {}): this {\n\t\treturn this.task(MOVE, { at: point(at), ...options })\n\t}\n\n\t/** Goes with a unit of the player's or an ally's, fighting what comes near it. Done `lost` when it is gone */\n\tescort(target: EntityState | number): this {\n\t\treturn this.task(ESCORT, { target: typeof target === 'number' ? target : target.id })\n\t}\n\n\t/**\n\t * Goes for the workers at a place, round where their army is (`avoid: 'army'` unless told otherwise), the workers\n\t * first once there. Done `cleared`\n\t */\n\tharass(at: Vec2, options: { avoid?: 'army' | false; then?: TaskOrder } = {}): this {\n\t\treturn this.task(HARASS, { at: point(at), avoid: 'army', ...options })\n\t}\n\n\t/** Goes to look at places, one after the other: each is looked at once in sight, or reached as near as the ground lets. Done `arrived` */\n\tscout(points: readonly Vec2[]): this {\n\t\treturn this.task(SCOUT_TASK, { points: points.map(point) })\n\t}\n\n\t/**\n\t * Gathers at a rally point before going on (`then`): until `minForces` of it (a share, 1 when left out) is there,\n\t * or `seconds` have gone by. Done `arrived`, and on to `then`\n\t */\n\tgather(at: Vec2, options: { minForces?: number; seconds?: number; then?: TaskOrder } = {}): this {\n\t\treturn this.task(GATHER, { at: point(at), ...options })\n\t}\n\n\t/** Falls back to a place (home when left out), fighting nothing on the way. Done `retreated` */\n\tretreat(to?: Vec2, why?: string): this {\n\t\tconst home = to ?? this.squads.ai.view.home()\n\t\treturn this.task(RETREAT, { ...(home && { at: point(home) }), ...(why && { why }) })\n\t}\n\n\t/**\n\t * Walks a round of places, one after the other and back to the first, fighting what it meets on the way (an\n\t * attack-move to each): a mission's guards on the road, a watch round the walls. Never over by itself: its owner\n\t * says when\n\t */\n\tpatrol(points: readonly Vec2[]): this {\n\t\treturn this.task(PATROL, { points: points.map(point) })\n\t}\n\n\t/** Takes a camp of creeps: fights there until the camp is cleared. Done `cleared` */\n\tcreep(camp: Vec2): this {\n\t\treturn this.task(CREEP, { at: point(camp) })\n\t}\n\n\t/**\n\t * Carried by transports to a place it cannot walk to, let out on the land nearest it (the `drop` task): done\n\t * `landed`, then what `then` says (an attack where it landed)\n\t */\n\tdrop(at: Vec2, transports: readonly number[], options: { then?: TaskOrder } = {}): this {\n\t\treturn this.task(DROP, { at: point(at), transports: [...transports], ...(options.then && { then: options.then }) })\n\t}\n\n\t/** Sends its units an order (`move`, `hold`, the game's), all or some of them: counted as the task's last */\n\torder(order: OrderInit, units: readonly number[] = this.data.units, queue = false): void {\n\t\tunits = this.living(units)\n\t\tif (!units.length) return\n\t\tthis.squads.ai.send({ type: 'order', entities: [...units], order, ...(queue && { queue: true }) })\n\t\tthis.sent()\n\t}\n\n\t/**\n\t * Puts its units, all or some, in a stance, where the game has stances (`withStances`): those not in it already. A\n\t * squad that holds is defensive, one sent to fight aggressive\n\t */\n\tsetStance(id: string, units: readonly number[] = this.data.units): void {\n\t\tif (!this.squads.ai.registry.command('stance')) return\n\t\tconst change: number[] = []\n\t\tfor (const unit of this.units()) {\n\t\t\tif (!units.includes(unit.id)) continue\n\t\t\tconst now = (unit.components?.[stance.id] as string | undefined) ?? DEFAULT_STANCE\n\t\t\tif (now !== id) change.push(unit.id)\n\t\t}\n\t\tif (change.length) this.squads.ai.send(stanceCommand.make({ entities: change, stance: id }))\n\t}\n\n\t/**\n\t * Sends its units to take a capture point of the game's (`withCapture`), by its id: they fight their way in and\n\t * stand in it until it is theirs (`captured`), or it is gone (`lost`)\n\t */\n\tcapture(id: string): this {\n\t\tconst found = capturePointsOf(this.squads.ai).find((each) => each.id === id)\n\t\treturn this.task(CAPTURE, { point: id, ...(found && { at: point({ x: found.x, z: found.z }) }) })\n\t}\n\n\t/** Sends its units, all or some, to fight at a place, or a target there: an attack-move, or an attack */\n\tfight(at: Vec2, units: readonly number[] = this.data.units, target?: number, queue = false): void {\n\t\tunits = this.living(units)\n\t\tif (!units.length) return\n\t\tthis.setStance(DEFAULT_STANCE, units)\n\t\tthis.squads.ai.send({\n\t\t\ttype: 'attack',\n\t\t\tentities: [...units],\n\t\t\tpoint: point(at),\n\t\t\t...(target !== undefined && { target }),\n\t\t\t...(queue && { queue: true })\n\t\t})\n\t\tthis.sent()\n\t}\n\n\t/**\n\t * Of some of its units, those the picture has: a unit that died since the squads were last looked at (a task given by a\n\t * goal before the `squads()` module ran) is no one to order\n\t */\n\tprivate living(units: readonly number[]): readonly number[] {\n\t\tconst { mine } = this.squads.ai.view\n\t\treturn units.every((id) => mine.has(id)) ? units : units.filter((id) => mine.has(id))\n\t}\n\n\t/** Its units that stand with nothing to do: what lost its order, or never had one */\n\tidleUnits(): EntityState[] {\n\t\treturn this.units().filter((unit) => !!unit.own && !unit.own.order && !unit.own.hidden)\n\t}\n\n\t/** Whether its last order was sent long enough ago to send one again (`RESEND` seconds): what keeps a stuck unit from being told every think */\n\tmayResend(): boolean {\n\t\tconst state = this.data.task\n\t\tconst { ai } = this.squads\n\t\treturn !state || state.sent === undefined || ai.tick - state.sent >= RESEND * ai.session.tickRate\n\t}\n\n\tprivate sent(): void {\n\t\tif (this.data.task) this.data.task.sent = this.squads.ai.tick\n\t}\n}\n\n/**\n * Some squads together (`ai.squads.all()`, `idle()`): read as a list, told as one (`ai.squads.all().defend(home)`:\n * each squad is given the task)\n *\n * @beta\n */\nexport class SquadGroup implements Iterable<Squad> {\n\tconstructor(\n\t\t/** The brain they are of */\n\t\treadonly ai: Brain,\n\t\t/** The squads */\n\t\treadonly squads: readonly Squad[]\n\t) {}\n\n\t[Symbol.iterator](): Iterator<Squad> {\n\t\treturn this.squads[Symbol.iterator]()\n\t}\n\n\t/** How many squads */\n\tget length(): number {\n\t\treturn this.squads.length\n\t}\n\n\t/** Their units together, as a set */\n\tunits(): UnitSet {\n\t\tconst { view } = this.ai\n\t\tconst all = this.squads.flatMap((squad) => squad.units().items)\n\t\tall.sort((a, b) => view.indexOf(a) - view.indexOf(b))\n\t\treturn new UnitSet(view, all)\n\t}\n\n\t/** How strong they are together */\n\tstrength(): number {\n\t\treturn this.units().strength()\n\t}\n\n\t/** Each given the same task */\n\ttask<D extends object, M extends object>(def: TaskDef<D, M>, data: D & TaskCommon): this\n\ttask(kind: string, data?: TaskData): this\n\ttask(kind: string | TaskDef, data: TaskData = {}): this {\n\t\tfor (const squad of this.squads) squad.squads.give(squad, kind, data)\n\t\treturn this\n\t}\n\n\tattack(target: Vec2 | EntityState | number, options: { avoid?: 'army' | false; then?: TaskOrder } = {}): this {\n\t\tfor (const squad of this.squads) squad.attack(target, options)\n\t\treturn this\n\t}\n\n\tdefend(at: Vec2 | undefined, radius?: number): this {\n\t\tif (at) for (const squad of this.squads) squad.defend(at, radius)\n\t\treturn this\n\t}\n\n\thold(at?: Vec2): this {\n\t\tfor (const squad of this.squads) squad.hold(at)\n\t\treturn this\n\t}\n\n\tmove(at: Vec2): this {\n\t\tfor (const squad of this.squads) squad.move(at)\n\t\treturn this\n\t}\n\n\tretreat(to?: Vec2): this {\n\t\tfor (const squad of this.squads) squad.retreat(to)\n\t\treturn this\n\t}\n\n\t/** Each disbanded */\n\tdisband(why?: string): void {\n\t\tfor (const squad of [...this.squads]) squad.disband(why)\n\t}\n}\n\n/** The ids of units given as entities or ids, each once */\nfunction ids(units: Iterable<EntityState | number>): number[] {\n\tconst result: number[] = []\n\tfor (const unit of units) {\n\t\tconst id = typeof unit === 'number' ? unit : unit.id\n\t\tif (!result.includes(id)) result.push(id)\n\t}\n\treturn result\n}\n\n/** A target as an attack's data: a place, or an entity and where it is */\nfunction targetOf(ai: Brain, target: Vec2 | EntityState | number): { target?: number; at?: Vec2 } {\n\tif (typeof target === 'number') {\n\t\tconst entity = ai.view.byId(target)\n\t\treturn { target, ...(entity && { at: point(entity) }) }\n\t}\n\tif ('id' in target && typeof (target as EntityState).id === 'number') return { target: (target as EntityState).id, at: point(target) }\n\treturn { at: point(target) }\n}\n\n/**\n * A brain's squads (`ai.squads`): made by its goals, rules and modules, watched by the `squads()` module each think\n * (`think`): the dead dropped, what the owner let go of let go of, each task looked at, regroups, retreats and\n * reinforcements seen to. Kept in the brain's memory (`BrainMemory.squads`)\n *\n * @beta\n */\nexport class Squads implements AiArea {\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'squads'\n\t/** What the log says where a save's memory of it is of a shape it does not read */\n\treadonly afresh = 'the save remembers the computer player’s squads in a shape this brain does not read: they are let go of'\n\n\tprivate list: Squad[] = []\n\tprivate readonly tasks = new Map<string, TaskDef>()\n\tprivate thoughtAt = -1\n\t/** How a squad behaves where it says nothing and the brain's settings say nothing either: the `squads()` module's */\n\tprivate moduleOptions: SquadOptions = {}\n\n\tconstructor(\n\t\t/** The brain they are the squads of */\n\t\treadonly ai: Brain,\n\t\t/** The tasks of the game's own its squads may be on (`AiSettings.squads.tasks`) */\n\t\ttasks: readonly TaskDef[] = []\n\t) {\n\t\tfor (const def of TASKS) this.tasks.set(def.id, def)\n\t\tfor (const def of tasks) this.define(def)\n\t}\n\n\t/** Puts the `squads()` module's options under the brain's settings */\n\tconfigure(options: SquadOptions): void {\n\t\tthis.moduleOptions = options\n\t}\n\n\t/** How a squad behaves where it says nothing: the module's options, the brain's settings over them (`ai.settings.squads`) */\n\tget defaults(): SquadOptions {\n\t\tconst { tasks: _tasks, ...settings } = this.ai.settings.squads ?? {}\n\t\treturn { ...this.moduleOptions, ...settings }\n\t}\n\n\t/** Registers a task of the game's own, so that a squad on it is carried on after a load. Given by `BrainDef.squads.tasks` */\n\tdefine(def: TaskDef): void {\n\t\tconst known = this.tasks.get(def.id)\n\t\tif (known && known !== def && TASKS.includes(known))\n\t\t\tthrow new Error(`\"${def.id}\" is a task of the kit's: a task of the game's needs a name of its own`)\n\t\tthis.tasks.set(def.id, def)\n\t}\n\n\t/** A kind of task by its id: the kit's, or one registered */\n\ttaskDef(id: string): TaskDef | undefined {\n\t\treturn this.tasks.get(id)\n\t}\n\n\t/**\n\t * Makes a squad of units under a name (one of that name already is disbanded first), with how it behaves where it\n\t * is not the brain's way. Whose it is (`owner`): what `options.owner` names (a goal makes its own with\n\t * `claimed.squad`), else its own (`squad:<name>`). A goal's squad is made of what the goal holds, and what\n\t * nothing holds is given to it; a squad of a rule or a module takes its units from whatever holds them (the goal\n\t * told: `stop('told')`) and holds them until it is disbanded. A unit in another squad leaves it\n\t */\n\tmake(name: string, units: Iterable<EntityState | number>, options: SquadOptions & { owner?: string } = {}): Squad {\n\t\tif (!name) throw new Error('A squad needs a name')\n\t\tconst { ai } = this\n\t\tconst { owner: named, ...own } = options\n\t\tconst owner = named ?? `squad:${name}`\n\t\tconst old = this.named(name)\n\t\tif (old) this.disband(old, 'made anew', old.owner !== owner)\n\t\t// the brain's settings (Groups Flee, the odds it falls back at), the squad's own over them\n\t\tconst behaves = { ...this.defaults, ...own }\n\t\tconst squad = new Squad(this, { name, owner, units: [], options: behaves, size: 0, made: ai.tick, retreats: 0 })\n\t\tthis.list.push(squad)\n\t\tthis.enlist(squad, ids(units))\n\t\tsquad.data.size = squad.data.units.length\n\t\tsquad.changed(`made by ${owner === `squad:${name}` ? 'itself' : owner}: ${plural(squad.data.units.length)}`)\n\t\treturn squad\n\t}\n\n\t/**\n\t * Puts units in a squad: those its owner may have (held by it, or given from the pool for a goal; taken for a rule's\n\t * or a module's), out of any other squad. Those put in, by id\n\t */\n\tenlist(squad: Squad, wanted: number[]): number[] {\n\t\tconst { goals, view, session, tick } = this.ai\n\t\tconst owner = squad.data.owner\n\t\tconst units = wanted.filter((id) => view.mine.has(id) && !squad.data.units.includes(id))\n\t\tif (!units.length) return []\n\t\tlet put: number[]\n\t\tif (goals.get(owner)) {\n\t\t\t// a goal's: what it holds, and what nothing holds given to it; what another holds is not its to have\n\t\t\tgoals.give(owner, units)\n\t\t\tput = units.filter((id) => goals.holder(id) === owner)\n\t\t} else {\n\t\t\t// a rule's, a module's, its own: taken from whoever holds them, for as long as the hold it is under lasts\n\t\t\tconst hold = goals.held(owner)\n\t\t\tconst seconds = !hold || hold.kept ? Infinity : Math.max(1, (hold.until - tick) / session.tickRate)\n\t\t\tgoals.take(units, 'told', { id: owner, seconds })\n\t\t\tput = units.filter((id) => goals.held(owner)?.units.includes(id))\n\t\t}\n\t\tif (!put.length) return put\n\t\t// in one squad at a time\n\t\tfor (const other of [...this.list]) {\n\t\t\tif (other === squad || !other.data.units.some((id) => put.includes(id))) continue\n\t\t\tother.data.units = other.data.units.filter((id) => !put.includes(id))\n\t\t\tother.changed(`${plural(put.length)} went to ${squad.name}`)\n\t\t\tif (!other.data.units.length) this.disband(other, `its units went to ${squad.name}`)\n\t\t}\n\t\t// what died since the squads module last looked is dropped as the new come in: the order is the picture's\n\t\tsquad.data.units = squad.data.units.filter((id) => view.mine.has(id))\n\t\tsquad.data.units.push(...put)\n\t\tsquad.data.units.sort((a, b) => view.indexOf(view.byId(a)!) - view.indexOf(view.byId(b)!))\n\t\treturn put\n\t}\n\n\t/** A squad by name: none for one there is not */\n\tnamed(name: string): Squad | undefined {\n\t\treturn this.list.find((squad) => squad.data.name === name)\n\t}\n\n\t/** Every squad, as made */\n\tall(): SquadGroup {\n\t\treturn new SquadGroup(this.ai, this.list)\n\t}\n\n\t/** The squads with nothing to do: told nothing, or their task over */\n\tidle(): SquadGroup {\n\t\treturn new SquadGroup(\n\t\t\tthis.ai,\n\t\t\tthis.list.filter((squad) => squad.idle)\n\t\t)\n\t}\n\n\t/** The squads a goal, rule or module owns */\n\tof(owner: string): SquadGroup {\n\t\treturn new SquadGroup(\n\t\t\tthis.ai,\n\t\t\tthis.list.filter((squad) => squad.data.owner === owner)\n\t\t)\n\t}\n\n\t/** The squad a unit is in, by the unit or its id: none for a unit in none */\n\tsquadOf(unit: EntityState | number): Squad | undefined {\n\t\tconst id = typeof unit === 'number' ? unit : unit.id\n\t\treturn this.list.find((squad) => squad.data.units.includes(id))\n\t}\n\n\t/** The player's units nothing holds (`ai.goals.pool`, buildings left out): what a squad is made of, or reinforced from */\n\tpool(): UnitSet {\n\t\treturn this.ai.goals.pool().units()\n\t}\n\n\t/** Disbands a squad: a squad that held its units itself lets them go back to the pool */\n\tdisband(squad: Squad, why = 'disbanded', letGo = true): void {\n\t\tconst index = this.list.indexOf(squad)\n\t\tif (index < 0) return\n\t\tthis.list.splice(index, 1)\n\t\tconst { goals } = this.ai\n\t\tif (letGo && !goals.get(squad.data.owner) && goals.held(squad.data.owner)) {\n\t\t\t// what it held is let go of; a hold it shares with other squads of its owner keeps theirs\n\t\t\tconst others = new Set(this.list.filter((other) => other.data.owner === squad.data.owner).flatMap((other) => other.data.units))\n\t\t\tgoals.drop(\n\t\t\t\tsquad.data.owner,\n\t\t\t\tsquad.data.units.filter((id) => !others.has(id))\n\t\t\t)\n\t\t}\n\t\tif (squad.data.units.length || why !== 'made anew') this.ai.decide(`squad ${squad.name} disbanded: ${why}`, { kind: 'squad' })\n\t}\n\n\t/**\n\t * Gives a squad a task: what it was doing is over, and the new one's first orders go at once. What it has now is what\n\t * reinforcements make up to from then on (`SquadData.size`), but for a task it goes on to by itself (`going on`: a\n\t * task's `then`, a fall back on the odds), which keeps what the task before was given. The task it is on given\n\t * again changes nothing, its `size` kept: what it lost since is what reinforcements make up\n\t */\n\tgive(squad: Squad, kind: string | TaskDef, data: TaskData, goingOn = false): void {\n\t\tconst { ai } = this\n\t\tconst def = typeof kind === 'string' ? this.tasks.get(kind) : kind\n\t\tif (!def)\n\t\t\tthrow new Error(\n\t\t\t\t`The squad \"${squad.name}\" was given a task \"${String(kind)}\" the brain does not know: list it in its squads' tasks (defineTask)`\n\t\t\t)\n\t\tif (typeof kind !== 'string' && !this.tasks.has(def.id)) this.define(def)\n\t\tconst before = squad.data.task\n\t\t// the task it is on already, given again (a goal's run each think): it goes on as it is, and nothing is sent again\n\t\tif (before && before.done === undefined && before.kind === def.id && sameData(before.data, data)) return\n\t\tconst state: TaskState = { kind: def.id, data: { ...data }, since: ai.tick, phase: 'starting', phaseSince: ai.tick, memory: {} }\n\t\tsquad.data.task = state\n\t\tif (!goingOn) squad.data.size = squad.data.units.length\n\t\tsquad.changed(before && before.done === undefined ? `${before.kind} → ${def.id}` : `on to ${def.id}`)\n\t\tif (squad.data.units.length) def.start(ai, squad, state)\n\t}\n\n\t/**\n\t * Looks at every squad, once a think: its units (the dead, and what its owner let go of, dropped; a squad of a goal\n\t * that stopped disbanded), then its task (retreat on the odds, the task's own look, regroup, reinforcements). What the\n\t * `squads()` module runs; a module may call it sooner\n\t */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tif (this.thoughtAt !== ai.tick) {\n\t\t\tthis.thoughtAt = ai.tick\n\t\t\tthis.prune()\n\t\t\tthis.advancing = [...this.list]\n\t\t\tthis.cursor = 0\n\t\t} else if (!this.advancing) return\n\t\t// each squad looked at in turn, as many as the tick's budget has room for (F2, `ai.budget`): a think sliced over\n\t\t// ticks goes on from the next squad at the next tick, over the same picture\n\t\tconst squads = this.advancing\n\t\tfor (; this.cursor < squads.length; this.cursor++) {\n\t\t\tconst squad = squads[this.cursor]\n\t\t\tthis.advance(squad)\n\t\t\tif (!ai.budget.spent(squad.data.units.length || 1) && this.cursor + 1 < squads.length) {\n\t\t\t\tthis.cursor++\n\t\t\t\treturn ai.budget.later()\n\t\t\t}\n\t\t}\n\t\tthis.advancing = undefined\n\t}\n\n\t/** The squads still to be looked at this think, where a pass stopped for the tick's budget, and the next of them */\n\tprivate advancing: Squad[] | undefined\n\tprivate cursor = 0\n\n\t/** Every squad's units looked at, as a think begins: the dead and what its owner let go of dropped, a squad with none left disbanded */\n\tprivate prune(): void {\n\t\tconst { ai } = this\n\t\tconst { goals, view } = ai\n\t\tfor (const squad of [...this.list]) {\n\t\t\tconst hold = goals.held(squad.data.owner)\n\t\t\tif (!hold) {\n\t\t\t\tthis.disband(squad, `${squad.data.owner} let go`, false)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// what a rule's or a module's hold has that is gone is let go of: with no goals in the brain, nothing else does\n\t\t\tif (!goals.get(squad.data.owner) && hold.units.some((id) => !view.mine.has(id))) hold.units = hold.units.filter((id) => view.mine.has(id))\n\t\t\tconst kept = squad.data.units.filter((id) => hold.units.includes(id) && view.mine.has(id) && view.byId(id)!.hp > 0)\n\t\t\tif (kept.length !== squad.data.units.length) squad.data.units = kept\n\t\t\tif (!kept.length) {\n\t\t\t\tsquad.finish('wiped')\n\t\t\t\tthis.disband(squad, 'none of its units left', false)\n\t\t\t}\n\t\t}\n\t}\n\n\t/** One squad's think: retreat on the odds, the task's own look, then on to the next task, regroup, reinforcements */\n\tprivate advance(squad: Squad): void {\n\t\tconst { ai } = this\n\t\tconst state = squad.data.task\n\t\tconst def = state && this.tasks.get(state.kind)\n\t\tconst handles = def?.handles ?? []\n\t\tif (state && def && state.done === undefined) {\n\t\t\tif (!handles.includes('retreat') && this.losing(squad)) return\n\t\t\tconst over = def.done?.(ai, squad, state)\n\t\t\tif (over) squad.finish(over)\n\t\t\telse def.think(ai, squad, state)\n\t\t\tif (state.done === undefined && !handles.includes('regroup') && state.data.regroup !== false) this.regroup(squad, state, def)\n\t\t\tconst then = state.data.then as TaskOrder | undefined\n\t\t\tif (state.done !== undefined && state.done !== 'lost' && state.done !== 'wiped' && then?.kind && this.tasks.has(then.kind)) {\n\t\t\t\tthis.give(squad, then.kind, then.data ?? {}, true)\n\t\t\t}\n\t\t}\n\t\tif (squad.data.options.reinforce && !handles.includes('reinforce')) this.reinforce(squad)\n\t}\n\n\t/**\n\t * Whether a squad in a fight away from home is losing it (its odds under `retreatAt`), and so falls back: its task\n\t * becomes `retreat`, home, and it is said why\n\t */\n\tprivate losing(squad: Squad): boolean {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst at = squad.data.options.retreatAt ?? 0.3\n\t\tif (at === false || !(at > 0)) return false\n\t\tconst units = squad.units()\n\t\tconst middle = units.centre()\n\t\tconst home = view.home()\n\t\tif (!middle || !home) return false\n\t\tconst safe = squad.data.options.home ?? 20\n\t\tif (distSq(middle, home) < safe * safe) return false\n\t\tconst foes = view.hostile.units().alive().near(middle, FIGHT_REACH)\n\t\tif (!foes.length || !foes.some((foe) => units.some((unit) => distSq(unit, foe) <= ENGAGED * ENGAGED))) return false\n\t\tconst odds = view.strength.odds(units.near(middle, FIGHT_REACH), foes)\n\t\tif (odds >= at) return false\n\t\tconst was = squad.data.task?.kind ?? 'nothing'\n\t\tsquad.data.retreats++\n\t\tthis.give(squad, 'retreat', { at: point(home), why: 'odds' }, true)\n\t\tai.decide(`squad ${squad.name} falls back home with ${plural(units.length)}: ${was} lost (odds ${odds.toFixed(2)} under ${at})`, {\n\t\t\tkind: 'squad'\n\t\t})\n\t\treturn true\n\t}\n\n\t/**\n\t * Regroups a squad that is strung out on its way: too many of its units (`regroupWhen`) further than `spread` from its\n\t * middle, and no fight near. It gathers on its middle and goes on once together, or once it has waited long enough\n\t */\n\tprivate regroup(squad: Squad, state: TaskState, def: TaskDef): void {\n\t\tconst { ai } = this\n\t\tconst units = squad.units()\n\t\tif (units.length < 3) return\n\t\tconst middle = units.centre()!\n\t\tconst spread = squad.spread()\n\t\tif (state.phase === 'regrouping') {\n\t\t\tconst together = units.every((unit) => distSq(unit, middle) <= spread * spread * 0.36)\n\t\t\tif (together || ai.tick - state.phaseSince >= REGROUP_FOR * ai.session.tickRate) {\n\t\t\t\t// on its way again: the task sends what it sends as it begins\n\t\t\t\tdef.start(ai, squad, state)\n\t\t\t\tai.decide(`squad ${squad.name} regrouped${together ? '' : ' as much as it waits for'}: on with ${state.kind}`, { kind: 'squad' })\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (state.phase !== 'going') return\n\t\tconst when = squad.data.options.regroupWhen ?? 0.4\n\t\tif (when === false) return\n\t\tconst strayed = units.filter((unit) => distSq(unit, middle) > spread * spread).length\n\t\tif (strayed <= units.length * when) return\n\t\tif (ai.view.hostile.alive().near(middle, FIGHT_REACH).length) return\n\t\tstate.phase = 'regrouping'\n\t\tstate.phaseSince = ai.tick\n\t\tsquad.order({ type: 'move', point: point(middle) })\n\t\tai.decide(`squad ${squad.name} regroups at ${where(middle)}: ${strayed} of ${units.length} strung out`, { kind: 'squad' })\n\t}\n\n\t/**\n\t * Makes up what a squad lost since its task began from the pool: the idle fighters nothing holds, the nearest\n\t * first, given to its owner and sent to join it. Never a hero: one crossing the map alone to a fight dies on the\n\t * way, and heroes are sent with a squad, not after it. Not while it falls back, nor more often than every few seconds\n\t */\n\tprivate reinforce(squad: Squad): void {\n\t\tconst { ai } = this\n\t\tconst { data } = squad\n\t\tconst missing = data.size - data.units.length\n\t\tif (missing <= 0 || (data.task?.kind === 'retreat' && data.task.done === undefined)) return\n\t\tif (data.nextReinforce !== undefined && ai.tick < data.nextReinforce) return\n\t\tdata.nextReinforce = ai.tick + REINFORCE_EVERY * ai.session.tickRate\n\t\tconst join = squad.centre() ?? this.whereOf(squad) ?? ai.view.home()\n\t\tif (!join) return\n\t\t// not a hero (sent with a squad, never after it), nor the wounded (one walking alone into the fight it fled dies there)\n\t\tconst { strength } = ai.view\n\t\tconst free = [...this.pool().fighters().idle()]\n\t\t\t.filter((unit) => !heroOfState(unit) && unit.hp >= WOUNDED * (unit.maxHp ?? strength.statsOf(unit).health))\n\t\t\t.sort((a, b) => distSq(a, join) - distSq(b, join) || a.id - b.id)\n\t\tconst chosen = free.slice(0, missing).map((unit) => unit.id)\n\t\tif (!chosen.length) return\n\t\tconst size = data.size\n\t\tsquad.add(chosen, 'reinforced')\n\t\tdata.size = size\n\t\tconst added = chosen.filter((id) => data.units.includes(id))\n\t\tif (!added.length) return\n\t\t// to where it is, fighting what they meet on the way\n\t\tai.send({ type: 'attack', entities: added, point: point(join) })\n\t\tai.decide(`squad ${squad.name} reinforced with ${plural(added.length)}`, { kind: 'squad' })\n\t}\n\n\t/** The place a squad's task is about: none for a task about no place */\n\twhereOf(squad: Squad): Vec2 | undefined {\n\t\tconst state = squad.data.task\n\t\tconst def = state && this.tasks.get(state.kind)\n\t\treturn state && def?.where?.(this.ai, squad, state)\n\t}\n\n\t/**\n\t * The way to a place round where the enemy is strong (`avoid: 'army'`): the waypoint to go by, where the straight way\n\t * crosses their strength (the threat map, with what is remembered of their towers, and their army as last seen) and a\n\t * way round is less hot, tried on either side and then further out, twice at most. A heuristic, not a safe route:\n\t * none where the straight way is cool enough, or where there is no way round (`note` says so)\n\t */\n\troute(from: Vec2, to: Vec2, squad: Squad): { waypoints: Vec2[]; note?: string } {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst units = squad.units()\n\t\tconst flying = units.length > 0 && units.every((unit) => !!view.def(unit).flying)\n\t\tconst layer: Layer = flying ? 'air' : 'ground'\n\t\tconst seen = ai.def.knowledge === false ? [] : ai.knowledge.enemy.armySeen(AVOID_SEEN)\n\t\tconst danger = (at: Vec2) => {\n\t\t\tlet enemy = view.threat.at(at, { layer, remembered: true }).enemy\n\t\t\tfor (const army of seen) if (distSq(army.at, at) < 12 * 12) enemy += army.strength\n\t\t\treturn enemy\n\t\t}\n\t\t// the hottest place along a way, looked at every few units of it\n\t\tconst hottest = (path: readonly Vec2[]) => {\n\t\t\tlet worst = { at: path[0] ?? from, enemy: 0 }\n\t\t\tfor (let i = 1; i < path.length; i++) {\n\t\t\t\tconst a = path[i - 1]\n\t\t\t\tconst b = path[i]\n\t\t\t\tconst steps = Math.max(1, Math.ceil(Math.sqrt(distSq(a, b)) / 6))\n\t\t\t\tfor (let s = 1; s <= steps; s++) {\n\t\t\t\t\tconst at = { x: a.x + ((b.x - a.x) * s) / steps, z: a.z + ((b.z - a.z) * s) / steps }\n\t\t\t\t\tconst enemy = danger(at)\n\t\t\t\t\tif (enemy > worst.enemy) worst = { at, enemy }\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn worst\n\t\t}\n\t\tconst straight = view.findPath(from, to, flying) ?? [from, to]\n\t\tconst worst = hottest([from, ...straight])\n\t\t// what the squad would rather not walk into: half its own strength\n\t\tconst bearable = Math.max(1e-9, units.strength() * 0.5)\n\t\tif (worst.enemy <= bearable) return { waypoints: [] }\n\t\tconst { width, depth } = view.session.terrain\n\t\tconst dx = to.x - from.x\n\t\tconst dz = to.z - from.z\n\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\tconst aside = { x: -dz / length, z: dx / length }\n\t\tlet best: { at: Vec2; enemy: number } | undefined\n\t\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\t\tconst far = DETOUR * (1 + attempt / 2)\n\t\t\tfor (const side of [1, -1]) {\n\t\t\t\tconst at = {\n\t\t\t\t\tx: Math.min(width - 1, Math.max(1, worst.at.x + aside.x * far * side)),\n\t\t\t\t\tz: Math.min(depth - 1, Math.max(1, worst.at.z + aside.z * far * side))\n\t\t\t\t}\n\t\t\t\tconst there = view.findPath(from, at, flying)\n\t\t\t\tconst on = there && view.findPath(at, to, flying)\n\t\t\t\tif (!there || !on) continue\n\t\t\t\tconst enemy = Math.max(hottest([from, ...there]).enemy, hottest([at, ...on]).enemy)\n\t\t\t\tif (!best || enemy < best.enemy) best = { at, enemy }\n\t\t\t}\n\t\t\tif (best && best.enemy <= bearable) return { waypoints: [point(best.at)], note: `round ${where(worst.at)} by ${where(best.at)}` }\n\t\t}\n\t\tif (best && best.enemy < worst.enemy)\n\t\t\treturn { waypoints: [point(best.at)], note: `no way round ${where(worst.at)} that is safe: by ${where(best.at)}, the least hot` }\n\t\treturn { waypoints: [], note: `no way round ${where(worst.at)}: straight` }\n\t}\n\n\t/** Every squad as the report shows it */\n\treport(): SquadReport[] {\n\t\treturn this.list.map((squad) => {\n\t\t\tconst { data } = squad\n\t\t\tconst units = squad.units()\n\t\t\tconst middle = units.centre()\n\t\t\tconst state = data.task\n\t\t\tconst at = this.whereOf(squad)\n\t\t\treturn {\n\t\t\t\tname: data.name,\n\t\t\t\towner: data.owner,\n\t\t\t\tunits: [...data.units],\n\t\t\t\tstrength: units.strength(),\n\t\t\t\t...(middle && { at: pair(middle) }),\n\t\t\t\tsize: data.size,\n\t\t\t\t...(state && {\n\t\t\t\t\ttask: {\n\t\t\t\t\t\tkind: state.kind,\n\t\t\t\t\t\tphase: state.phase,\n\t\t\t\t\t\tsince: state.since,\n\t\t\t\t\t\t...(at && { at: pair(at) }),\n\t\t\t\t\t\t...(state.done !== undefined && { done: state.done })\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tretreats: data.retreats,\n\t\t\t\t...(data.changed && { changed: { ...data.changed } })\n\t\t\t}\n\t\t})\n\t}\n\n\t/** What the squads are, for a save: copies */\n\t/** Whether it has anything to remember now: one that does not is left out of a save */\n\tremembers(): boolean {\n\t\treturn this.all().length > 0\n\t}\n\n\tsave(): SquadsMemory {\n\t\treturn { v: 1, squads: this.list.map((squad) => structuredClone(squad.data)) }\n\t}\n\n\t/** Takes back what `save` gave: whether it was read. A squad on a task the brain does not know is kept, and does nothing */\n\trestore(memory: unknown): boolean {\n\t\tconst given = memory as SquadsMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1 || !Array.isArray(given.squads)) return false\n\t\tthis.list = given.squads\n\t\t\t.filter((data) => data && typeof data.name === 'string' && Array.isArray(data.units))\n\t\t\t.map((data) => new Squad(this, structuredClone(data)))\n\t\tfor (const squad of this.list) {\n\t\t\tconst kind = squad.data.task?.kind\n\t\t\tif (kind && !this.tasks.has(kind))\n\t\t\t\tthis.ai.log.info('ai', `the squad \"${squad.name}\" is on a task \"${kind}\" this brain does not know: it waits`, { squad: squad.name })\n\t\t}\n\t\treturn true\n\t}\n}\n\n/** The share of its health under which a unit is not sent as a reinforcement */\nconst WOUNDED = 0.5\n\n/** Whether two tasks' data say the same: plain data, field by field */\nfunction sameData(a: unknown, b: unknown): boolean {\n\tif (a === b) return true\n\tif (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n\tif (Array.isArray(a) !== Array.isArray(b)) return false\n\tconst keys = Object.keys(a).filter((key) => (a as Record<string, unknown>)[key] !== undefined)\n\tconst others = Object.keys(b).filter((key) => (b as Record<string, unknown>)[key] !== undefined)\n\treturn keys.length === others.length && keys.every((key) => sameData((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]))\n}\n\n/**\n * The squads module: looks at every squad of the brain each think (`ai.squads.think`), after the goals, the rules and\n * the words that make them: their units, their tasks, regroups, retreats, reinforcements. With how they behave where the\n * brain's definition and the seat's options say nothing\n *\n * @beta\n */\nexport const squads = (options: SquadsOptions = {}): AiModuleDef =>\n\tdefineModule('squads', (ai: Brain): AiModule => {\n\t\tfor (const def of options.tasks ?? []) ai.squads.define(def)\n\t\tconst { tasks: _tasks, ...defaults } = options\n\t\tai.squads.configure(defaults)\n\t\treturn {\n\t\t\tid: 'squads',\n\t\t\tphase: 'act',\n\t\t\tafter: ['goals'],\n\t\t\tthink: () => ai.squads.think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tsquads?: SquadsMemory\n\t}\n}\n","import type { PlayerId } from '#engine/entity'\nimport { type Logger, rootLogger } from '#engine/log'\nimport { AI_PHASES, type AiModule, type AiModuleDef, type ModuleKey } from './module'\nimport type { AiArea, AreaKey, AreaMemories } from './area'\nimport type { Registry } from '#engine/registry'\nimport { plainParts } from '#engine/plain'\nimport { Rng } from '#engine/rng'\nimport { order } from '#engine/scheduler'\nimport type { GameSession, PlayerCommand, PlayerState, SessionEvent, Snapshot } from '#engine/session/protocol'\nimport type { AiOptions } from './options'\nimport type { BrainSeat } from '#engine/computers'\nimport { ThinkBudget, type ThinkBudgetOptions } from './budget'\nimport type { ComputerPlayer } from './computer'\nimport { type GoalDef, Goals, type PickingOptions } from './goals'\nimport { Knowledge, type KnowledgeOptions } from './knowledge'\nimport { Plans } from './plans/plans'\nimport { Purse } from './plans/purse'\nimport { type AiProfile, resolveProfile } from './profiles'\nimport { type AiDecision, type AiReport, type AiStats, Decisions, explainGoal, type KnowledgeReport, type ThreatReport } from './report'\nimport type { AiConditionTest, AiRule } from './rules'\nimport { CHURN_WINDOW, checkBrain, orderKey } from './checks'\nimport { debugChecks } from '#engine/debug'\nimport { type AiSettings, resolveSettings } from './settings'\nimport { Squads } from './squads'\nimport type { TeamBoard } from './team'\nimport type { Strength, StrengthFormula } from './strength'\nimport type { ThreatMap } from './threat'\nimport { AiView } from './view'\n\n/*\n * A brain is what a computer player is made of (AI plan, A1). It sits in a seat (`computer.ts` gives it a session of\n * its own: it sees what that player sees, and nothing else), and once in a while it thinks: it takes one picture of the\n * game (the seat's snapshot), and runs its modules over it, in order. A module is one part of a think with a name: the\n * economy, the army, a mission's rules. Each reads the picture and acts by sending commands, as a mouse would, through\n * the brain's `send`. What a module remembers between thinks is plain data kept under its id in the brain's memory,\n * which a save keeps and a load gives back (`save`, `restore`); the brain's own numbers (`rng`, seeded from the world's\n * seed and the player) are in it too, so a game loaded from a save goes on exactly as it would have.\n *\n * A brain is defined once (`defineBrain`: its id, its modules) and made once for each seat (`createBrain`), as a\n * system is made for each world: two brains of one definition never share state. A brain has its view of the game\n * (A2), its knowledge (A3), its strength and its threat map (A4), its goals (B1), its purse and its plans (B3), its\n * squads (C1), its micro (C2), its economy and its defence (C4), its scouting (C3), its team (C5), its waves (D2): each of them is a field on the brain that the modules\n * reach through the `ai` they are handed.\n *\n * A think may be sliced over ticks by its budget (`budget.ts`, F2): so many modules a tick, so many units looked at a\n * tick as the modules say, counted in work and never in milliseconds, so that the game is the same on every machine.\n * The think's picture is taken once and every tick of it reads the same one; what ran so far is kept as passes (the\n * module, the units the tick had looked at before it), which is how a save taken in the middle of a think is run on\n * from in a loaded game (`BrainMemory.thinking`).\n */\n\n/** A module definition's id, where it is known before the module is made: an object's, or a `defineModule`'s */\nconst idOf = (def: AiModuleDef): string | undefined => (typeof def === 'function' ? def.id : def.id)\n\n/**\n * What a computer player is made of, defined once (`defineBrain`) and seated as often as wanted\n * (`world.computers.seat`). A game lists the brains it seats in `GameModule.brains`, so that a save that remembers a\n * seat by its brain's id finds it again when loaded\n *\n * @beta\n */\nexport interface BrainDef {\n\t/** Unique among the brains of a game, prefixed as components are (the engine's `core.melee`, a game's `mygame.raiders`): what a save remembers a seat by */\n\tid: string\n\t/** The parts of a think, in the order they run where `before` and `after` say nothing */\n\tmodules: AiModuleDef[]\n\t/**\n\t * Modules of the list left out, by id (`meleeBrain.with({ without: ['scouting', 'melee.heroes'] })`): a variant of a\n\t * brain with a part fewer. A module whose id is not known before it is made (a plain function, not `defineModule`)\n\t * cannot be left out by name\n\t */\n\twithout?: string[]\n\t/**\n\t * Rules of its own (`when(…).do(…)`, B2), checked each think by its `rules()` module: the melee brain's reads them\n\t * (`meleeBrain.with({ rules: [...] })`); a brain of one's own gives them to its `rules()` module itself. Code,\n\t * registered again with the brain\n\t */\n\trules?: AiRule[]\n\t/**\n\t * Seconds between thinks, where the seat's options say none (`AiOptions.every`): 1 when left out. A function of the\n\t * seat's options, for a brain that thinks faster on a harder difficulty\n\t */\n\tevery?: number | ((options: AiOptions) => number)\n\t/**\n\t * What its picture of the game carries (`ComputerSeatOptions.snapshot`): `lean` when left out, what the kit reads (the\n\t * entities, the players, the items, the deaths, damage, healing, pings, chat and the game's own events) and none of\n\t * what a screen needs, which is cheaper. `full` for a brain of a game's own that reads the rest (projectiles, corpses,\n\t * reveals, the other events)\n\t */\n\tsnapshot?: 'lean' | 'full'\n\t/**\n\t * How it is seated at a player (`world.computers.seat`): what `defineBrain` gives it, the seat of the engine's kit\n\t * (`createBrainSystem`, with what the map says of the player under the options). The engine's core seats a brain\n\t * through it, and loads nothing of the kit for it\n\t */\n\tseat?: BrainSeat\n\t/**\n\t * How it remembers what it saw (`Brain.knowledge`): how long, how much, what counts as the enemy's army. `false` for\n\t * a brain that remembers nothing between thinks and would rather not pay for it (a tower defense's waves)\n\t */\n\tknowledge?: KnowledgeOptions | false\n\t/**\n\t * How strong a unit is, in place of the kit's formula (`defaultStrength`): what `odds`, the threat map and\n\t * `UnitSet.strength()` are made of. The seat's `AiOptions.strength` goes over it; this one is code the game registers\n\t * again, so it is there after a load\n\t */\n\tstrength?: StrengthFormula\n\t/** Conditions of its own, by id, for the data form (`{ is: id, args }`): over the game's of the same id (`GameAi.conditions`) */\n\tconditions?: Record<string, AiConditionTest>\n\t/**\n\t * What it could do, scored each think and run with what each claims (`defineGoal`, `ai.goals`): picked by the\n\t * `goals()` module in its place among the modules, or by a module of the brain's own. Code, registered again with\n\t * the brain: there after a load, where a goal in the seat's options is not\n\t */\n\tgoals?: GoalDef[]\n\t/** How it picks among its goals where a goal does not say for itself: the least score, the margin, the commitment */\n\tpicking?: PickingOptions\n\t/**\n\t * Its own settings (`AiSettings`, keyed by area: how it plans, how its squads go and the tasks they may be on, how it\n\t * fights, runs its economy, defends, scouts, plays with its team, its waves): the bottom layer, under the game's\n\t * defaults, the difficulty, the personality, the map's and the seat's (`resolveProfile`); what its modules were made\n\t * with under all of them. Code, registered again with the brain\n\t */\n\tsettings?: AiSettings\n\t/**\n\t * This brain and more: goals, modules, rules and `without` added to its own, its settings layered over its own,\n\t * anything else in place of its own (`meleeBrain.with({ goals: [raid] })`, `meleeBrain.with({ id: 'mygame.camp', rules, without: ['scouting'] })`).\n\t * Given by `defineBrain`\n\t */\n\twith?(more: BrainExtension): BrainDef\n}\n\n/**\n * What `BrainDef.with` adds to a brain: goals, modules, rules and modules left out beside its own, settings over its\n * own, the rest in place of its own\n *\n * @beta\n */\nexport type BrainExtension = Partial<Omit<BrainDef, 'with'>>\n\n/**\n * A word the game told a computer player (`world.computers.tell`), waiting for a module to take it\n *\n * @beta\n */\nexport interface Told {\n\t/** The word: what the game and the brain agreed on (`'raid'`) */\n\tword: string\n\t/** What came with it: plain data */\n\tdata?: unknown\n\t/** The tick it was told at */\n\ttick: number\n}\n\n/**\n * What a brain remembers between thinks, as a save keeps it: its own numbers, each module's memory with its version,\n * the words it was told and not yet taken\n *\n * @beta\n */\nexport interface BrainMemory {\n\t/** The version of this shape */\n\tv: 2\n\t/** Where the brain's own numbers are in their sequence (`Rng.save`) */\n\trng: number\n\t/** How many times it has thought: what `AiModule.everyThinks` counts in */\n\tthinks: number\n\t/** Whether it sits still (`world.computers.pause`) */\n\tpaused?: boolean\n\t/** The words it was told and no module has taken yet */\n\ttold: Told[]\n\t/** What each module remembers, under its id, with the version it was saved as */\n\tmodules: Record<string, { v: number; data: unknown }>\n\t/**\n\t * What each of its areas remembers, by the area's id (`AiArea`): its knowledge, goals, plans and squads, its economy,\n\t * scouting and the rest of the kit's, a game's own. Left out by an area with nothing to remember\n\t */\n\tareas?: AreaMemories\n\t/** What it decided last (`Brain.decisions`): the last fifty lines, for whoever reads a save */\n\tdecisions?: AiDecision[]\n\t/**\n\t * The orders it sent lately (`Brain.sentTo`), by unit: what keeps it from telling a unit again what it is doing, in a\n\t * game loaded from the save too. Left out while there are none\n\t */\n\torders?: { unit: number; key: string; tick: number }[]\n\t/**\n\t * What its seat heard since it last thought (`GameSession.pendingEvents`): the damage, deaths and pings its next think\n\t * reads, which a game loaded from the save would not have heard otherwise\n\t */\n\theard?: SessionEvent[]\n\t/**\n\t * A think under way across ticks as the game was saved (`BrainContext.budget`): the rest of this memory is the brain\n\t * as that think began, and this is how far it had got, over what picture: each pass run so far, as the module (its\n\t * index), the units the tick had looked at before it (`ThinkBudget.units`) and how many words it had been told by then\n\t * (`told`). A game loaded from the save runs the\n\t * same passes again under the same budget over the same picture, sending nothing (their commands are in the game\n\t * already), and goes on from there as the saved game did. `slice` is the form before passes: so many modules run once each\n\t */\n\tthinking?: { snapshot: Snapshot; passes?: [module: number, units: number, heard: number][]; slice?: number }\n}\n\n/**\n * What follows a brain's play from outside it (`Brain.watch`): the commands it sends, its thinks as each ends, what it\n * decides. For tests and tools (`watchComputer`, `recordDecisions`, the invariants of `ai/checks.ts`): a watcher reads,\n * it never changes what the brain does\n *\n * @beta\n */\nexport interface BrainWatcher {\n\t/** A command it sent, as it goes (`Brain.send`): not one held back past its profile's cap */\n\tsent?(command: PlayerCommand, brain: Brain): void\n\t/** A think ended, all its ticks where it was sliced: the picture it read is still `brain.view` */\n\tthought?(brain: Brain): void\n\t/** It wrote a decision down (`Brain.decide`) */\n\tdecided?(decision: AiDecision, brain: Brain): void\n}\n\n/**\n * What a seat hands a brain as it is made, besides its session and its options (`createComputerSystem`'s `make`)\n *\n * @beta\n */\nexport interface BrainContext {\n\t/** What the brain's own numbers start from: the world's seed and the player, as the seat works it out */\n\tseed?: number\n\t/**\n\t * How much of a think one tick may do (`ThinkBudgetOptions`: modules a tick, units looked at a tick, the milliseconds a\n\t * module is warned over), or the modules a tick as a number. A think with more goes on at the next tick, over the same\n\t * picture of the game, so that no tick does all of it. Everything in one tick when left out\n\t */\n\tbudget?: number | ThinkBudgetOptions\n\t/** Whether to time each module this think: on while the world's scheduler profiles. Timing never decides anything */\n\tprofiling?: () => boolean\n\t/**\n\t * The board of its team (`TeamBoard`), shared by the computers of one team and kept by the world (`core.ai.teams`):\n\t * read anew each time, for a load replaces it. A brain with none plays alone\n\t */\n\tteam?: () => TeamBoard\n\t/**\n\t * Whether every think is checked against the invariants (`checkBrain`): its world's (`world.checks.ai`), as its seat\n\t * says. The process's (`debugChecks.ai`) for a brain made by hand\n\t */\n\tchecks?: boolean\n}\n\n/**\n * What of what its seat heard since it last thought a save keeps (`BrainMemory.heard`): the facts a brain reads (deaths,\n * damage, healing, pings, chat, the game's own events). What is for the screen is left out: a builder's hammer blow\n * comes of a timer no save keeps, and the answers to its own commands name the seat's numbering of them, which a loaded\n * game's seat starts afresh\n */\nconst HEARD: ReadonlySet<SessionEvent['type']> = new Set(['death', 'damage', 'heal', 'ping', 'chat', 'game'])\n\n/** How much of each new think goes into a module's averaged time. Small: the panel shows a steady number */\nconst SMOOTHING = 0.1\n\n/** A timing averaged over thinks, the new one weighed in: the first stands as it is */\nconst averaged = (before: number | undefined, took: number): number => (before === undefined ? took : before + (took - before) * SMOOTHING)\n\n/**\n * A computer player made of modules (`defineBrain`), seated at a world (`world.computers.seat`). What\n * a module is handed as it thinks (`ai`): the picture of the game (`snapshot`), the seat it plays through (`session`),\n * its options, its numbers (`rng`), its log, and `send` for its commands. A brain is a `ComputerPlayer`: `think`, and\n * `save` and `restore` for what it remembers\n *\n * @beta\n */\nexport class Brain implements ComputerPlayer {\n\t/** Its modules, in the order they run */\n\treadonly modules: readonly AiModule[]\n\t/**\n\t * Its own numbers, for whatever it leaves to chance (which base to scout first): seeded from the world's and the\n\t * player's, kept in its memory, so that the same game plays the same way. Never `Math.random`\n\t */\n\treadonly rng: Rng\n\t/** Where it says what it does: the world's log, with the player it plays and its brain on each line */\n\treadonly log: Logger\n\t/** Whether it sits still (`world.computers.pause`). Kept in a save */\n\tpaused = false\n\t/**\n\t * What it sees, as of its last think: the snapshot of its seat, plain data, and the only input a brain has. Taken once\n\t * a think: every module of the think reads the same picture\n\t */\n\tsnapshot: Snapshot\n\t/**\n\t * Its reading of the picture (`AiView`): the snapshot indexed once a think and asked as sets (`view.mine.idle()`,\n\t * `view.enemies.near(home, 20)`), with what unit types are for (`view.roles`) and the map's facts. What a module\n\t * reads the game through\n\t */\n\tview: AiView\n\t/**\n\t * What it remembers of the enemy, the map and itself, with when (`Knowledge`): their bases and army as last seen,\n\t * when each place was last looked at, its own losses and income. Brought up to date as each think begins, after the\n\t * view; kept in a save\n\t */\n\treadonly knowledge: Knowledge\n\t/**\n\t * What it could do (`Goals`): its goals scored each think from their considerations, the best given what they\n\t * claim of its units and money, each run while it holds its claim. Its definition's goals and the seat's; a module\n\t * adds its own (`ai.goals.add`). Picked by the `goals()` module, or by one of the brain's own in its place\n\t */\n\treadonly goals: Goals\n\t/**\n\t * What it has to spend this think (`Purse`): its resources less what builders on their way will pay and what is\n\t * held (a goal's money claim, a want saving up), rebuilt from the picture as each think begins. The one ledger:\n\t * everything that spends, spends through it. `view.me.purse` is what is free\n\t */\n\treadonly purse: Purse\n\t/**\n\t * Its plans (`Plans`): the build plan (`plans.build`: wants, the steps to each through the tech tree, spots,\n\t * builders, saving up), the production plan (`plans.production`: the composition, counters, supply ahead,\n\t * research), the game's build order over both, and `plans.want` to add to them. Run by the `build()` and\n\t * `production()` modules, or by one of the brain's own\n\t */\n\treadonly plans: Plans\n\t/**\n\t * Its squads (`Squads`): named groups of its units, each with a task (attack there, defend here, gather and go), made\n\t * by its goals, rules and modules out of what they hold, and watched by the `squads()` module think after think:\n\t * orders sent once and watched, regroups, retreats on the odds, reinforcements. Kept in a save\n\t */\n\treadonly squads: Squads\n\t/**\n\t * How it plays (`AiProfile`), resolved (`resolveProfile`): how well it plays (the engine's, the game's, the\n\t * difficulty's, the personality's, the seat's `every` and `budget`) and its settings, the brain's, the game's, the\n\t * difficulty's, the personality's, the map's and the seat's each over the one before (a flag's function left out)\n\t */\n\treadonly profile: AiProfile\n\t/** Its settings' layers, lowest first (`ResolvedProfile.layers`): what `settings` is worked out from */\n\tprivate readonly layers: readonly AiSettings[]\n\t/** How many times it has thought */\n\tthinks = 0\n\t/**\n\t * What it decided, the last fifty (`decide`): the goals picked and stopped, with the reason that weighed most, and\n\t * what its modules write down. Kept in a save\n\t */\n\treadonly decisions = new Decisions()\n\t/** The board of its team, shared by its team's computers: what its seat was given (`BrainContext.team`), for its team play */\n\treadonly teamBoard: BrainContext['team']\n\t/** Its areas, in the order they were made (`area`) */\n\tprivate readonly areaList: AiArea[] = []\n\t/** What a save remembered of areas not made yet, by id: taken by each as a module first asks for it */\n\tprivate waiting: AreaMemories = {}\n\t/** What was worked out for this think, by key (`cache`): thrown away with the picture */\n\tprivate readonly memo = new Map<string, unknown>()\n\n\t/**\n\t * How strong things are (`Strength`): a unit, a group, one force against another (`odds`), what answers what\n\t * (`counterFor`). The view's: the kit's formula unless the brain or the seat was given one\n\t */\n\tget strength(): Strength {\n\t\treturn this.view.strength\n\t}\n\n\t/**\n\t * Where the strength is (`ThreatMap`): the friendly and the enemy strength that reaches each cell of a coarse grid\n\t * over the map, by layer. Made from the think's picture when first asked; `threat.at(undefined)` is all zeros\n\t */\n\tget threat(): ThreatMap {\n\t\treturn this.view.threat\n\t}\n\t/** Commands it sent this think */\n\tsent = 0\n\t/** Commands it would have sent this think past what its profile lets a think send (`commandsPerThink`): not sent */\n\theld = 0\n\t/**\n\t * What its play adds up to since it was seated (`AiStats`): commands sent, held and refused, seconds its fighters\n\t * stood idle, orders sent again for the same thing, seconds its building waited on money. For the report and\n\t * `simulate`, never for a decision; not kept in a save\n\t */\n\treadonly stats: AiStats = { commands: 0, held: 0, refused: 0, idleArmySeconds: 0, churn: 0, blockedOnMoney: 0, thinks: 0 }\n\t/** The tick of the think before, for what is counted by the seconds between thinks */\n\tprivate lastThink: number | undefined\n\t/** The last order each unit was sent, with the tick: what an order sent again for the same thing is counted against (`AiStats.churn`) */\n\tprivate readonly lastOrders = new Map<number, { key: string; tick: number }>()\n\t/**\n\t * How much of a think one tick may do (`ThinkBudget`): so many modules, so many units looked at as the modules say\n\t * (`budget.spent(n)`), the think going on at the next tick from where it stopped (`budget.later()`). Counted in work,\n\t * never in milliseconds, so that the game is the same on every machine. What the seat was given (`BrainContext.budget`)\n\t */\n\treadonly budget: ThinkBudget\n\t/** Milliseconds each module took, averaged over thinks, by id: while the world profiles (`BrainContext.profiling`) */\n\treadonly moduleTiming: Record<string, number> = {}\n\t/** The most milliseconds each module took in one pass, by id: always, as the warning (`ThinkBudgetOptions.warnAfterMs`) is */\n\treadonly moduleLongest: Record<string, number> = {}\n\t/** Milliseconds taking the picture of the game took (the seat's `snapshot()`), averaged: while the world profiles */\n\tsnapshotTiming: number | undefined\n\t/** Milliseconds reading the picture into the view took (`AiView`, the ledger with it), averaged: while the world profiles */\n\tviewTiming: number | undefined\n\t/** Milliseconds bringing the knowledge up to date took, averaged: while the world profiles */\n\tknowledgeTiming: number | undefined\n\t/** Ticks the last think took, all its passes: 1 unless its budget sliced it */\n\tthinkTicks = 0\n\t/** Ticks of the think under way so far */\n\tprivate ticksSoFar = 0\n\t/** The modules the log has warned of taking over `warnAfterMs`, once each */\n\tprivate readonly warned = new Set<string>()\n\t/**\n\t * The passes of the think under way: each module run, with the units the tick had looked at before it. What a save in\n\t * the middle of the think keeps (`BrainMemory.thinking`), kept only where the budget may slice\n\t */\n\tprivate passes: [module: number, units: number, heard: number][] = []\n\tprivate heard: Told[] = []\n\t/** Who follows its play from outside (`watch`): none in a game, so nothing is paid for it there */\n\tprivate watchers: BrainWatcher[] = []\n\t/** The module a think under way goes on from, at the next tick: none between thinks (`budget`) */\n\tprivate slice: number | undefined\n\t/**\n\t * What it remembered as the think under way began, for a think sliced across ticks: what a save taken before the\n\t * think ends keeps, with how far it got (`BrainMemory.thinking`)\n\t */\n\tprivate began: BrainMemory | undefined\n\t/** The words told it since the think under way began: a save taken before it ends keeps them beside what it began with */\n\tprivate toldDuring: Told[] = []\n\t/** A think a save was taken in the middle of: run again to where it was, then on, at the next tick (`restore`) */\n\tprivate resume: { passes: [module: number, units: number, heard: number][]; snapshot: Snapshot } | undefined\n\t/** While the modules a loaded game had run already are run again: nothing is sent, said or watched */\n\tprivate replaying = false\n\t/** While a pass is run again: how many of the words it was told the pass had heard then, the rest told it after */\n\tprivate replayHeard: number | undefined\n\tprivate readonly profiling: () => boolean\n\n\tconstructor(\n\t\t/** What it was made from */\n\t\treadonly def: BrainDef,\n\t\t/** The seat it plays through: the snapshots it sees, the commands it sends */\n\t\treadonly session: GameSession,\n\t\t/** What it was seated with: a brain's own options read theirs from it */\n\t\treadonly options: AiOptions,\n\t\tcontext: BrainContext = {}\n\t) {\n\t\tthis.rng = new Rng(context.seed ?? 1)\n\t\tthis.log = (session.log ?? rootLogger).child(() => ({ fields: { ai: session.playerId, brain: def.id } }))\n\t\tthis.snapshot = session.snapshot()\n\t\t// the race it plays as it is seated: the game's layer for it (`GameAi.races`)\n\t\tconst race = this.snapshot.players.find((player) => player.id === session.playerId)?.race\n\t\tconst { profile, layers, unknown } = resolveProfile(options, session.registry, def.settings, race)\n\t\tthis.profile = profile\n\t\tthis.layers = layers\n\t\tif (unknown.length)\n\t\t\tthis.log.warn('ai', `the computer player is seated with a ${unknown.join(' and a ')} the game does not have: the defaults stand in`)\n\t\tthis.budget = new ThinkBudget(context.budget)\n\t\tthis.profiling = context.profiling ?? (() => false)\n\t\tthis.view = new AiView(this.snapshot, session, { roles: options.roles, strength: options.strength ?? def.strength })\n\t\tthis.knowledge = new Knowledge(def.knowledge || {}, session.terrain, def.knowledge !== false)\n\t\tthis.goals = new Goals(this, def.picking)\n\t\tthis.goals.add(...(def.goals ?? []))\n\t\tthis.purse = new Purse(session.registry)\n\t\tthis.purse.begin(this.view)\n\t\tthis.plans = new Plans(this, profile.plans ?? {})\n\t\tthis.squads = new Squads(this, profile.squads?.tasks)\n\t\tthis.teamBoard = context.team\n\t\t// what every module shares, kept and reported as every area is: its other areas are made as a module asks (`area`)\n\t\tfor (const area of [this.knowledge, this.goals, this.plans, this.squads]) this.register(area)\n\t\t// the seat's goals, beside its definition's\n\t\tthis.goals.add(...(options.goals ?? []))\n\t\t// the modules left out by name (`without`) are never made: a module made configures the brain as it is made\n\t\tconst left = new Set(def.without ?? [])\n\t\tconst kept = def.modules.filter((module) => {\n\t\t\tconst id = idOf(module)\n\t\t\treturn id === undefined || !left.has(id)\n\t\t})\n\t\tfor (const id of left)\n\t\t\tif (!def.modules.some((module) => idOf(module) === id))\n\t\t\t\tthis.log.warn('ai', `the brain \"${def.id}\" leaves out a module \"${id}\" it does not have`)\n\t\tconst made = kept.map((module) => (typeof module === 'function' ? module(this) : module))\n\t\tconst ids = new Set<string>()\n\t\tfor (const module of made) {\n\t\t\tif (ids.has(module.id)) throw new Error(`The brain \"${def.id}\" has two modules called \"${module.id}\"`)\n\t\t\tids.add(module.id)\n\t\t}\n\t\t// in their order: phase by phase (one with none in the phase of the one listed before it), as listed within each,\n\t\t// then by what each says it comes before and after\n\t\tlet phase = 0\n\t\tconst phased = made.map((module, listed) => {\n\t\t\tif (module.phase) phase = AI_PHASES.indexOf(module.phase)\n\t\t\treturn { module, phase, listed }\n\t\t})\n\t\tphased.sort((a, b) => a.phase - b.phase || a.listed - b.listed)\n\t\tthis.modules = order(phased.map(({ module }) => ({ name: module.id, before: module.before, after: module.after, module }))).map(\n\t\t\t(each) => each.module\n\t\t)\n\t\t// the engine's own checks on (tests, development): every think checked against the invariants, the first broken one thrown\n\t\tif (context.checks ?? debugChecks.ai) checkBrain(this)\n\t}\n\n\t/**\n\t * An area of its (`AiArea`): its economy (`ai.area(Economy)`), its scouting, a game's own (`defineArea`), made the\n\t * first time it is asked for, with what a save remembered of it. What its modules share beyond what every module\n\t * does (`knowledge`, `goals`, `plans`, `squads`, `purse`)\n\t */\n\tarea<T extends AiArea>(key: AreaKey<T>): T {\n\t\tconst known = this.areaList.find((area) => area.id === key.id)\n\t\tif (known) return known as T\n\t\tconst made = key.make(this)\n\t\tif (made.id !== key.id) throw new Error(`The area \"${key.id}\" made an area called \"${made.id}\"`)\n\t\tthis.register(made)\n\t\treturn made\n\t}\n\n\t/**\n\t * An area made already, by id: none where no module has asked for it. For a part of the kit that reads another's\n\t * area where there is one and needs nothing of it where there is none (whether a squad's fights are the micro's)\n\t */\n\tmade<T extends AiArea>(id: string): T | undefined {\n\t\treturn this.areaList.find((area) => area.id === id) as T | undefined\n\t}\n\n\t/** Its areas, in the order they were made: what its memory and its report are made of */\n\tareas(): readonly AiArea[] {\n\t\treturn this.areaList\n\t}\n\n\t/** Puts an area among its own, with what a save remembered of it */\n\tprivate register(area: AiArea): void {\n\t\tthis.areaList.push(area)\n\t\tif (!(area.id in this.waiting)) return\n\t\tconst memory = this.waiting[area.id]\n\t\tdelete this.waiting[area.id]\n\t\tif (!area.restore(memory))\n\t\t\tthis.log.info('ai', area.afresh ?? `the save remembers the computer player's ${area.id} in a shape this brain does not read: it starts afresh`)\n\t}\n\n\t/**\n\t * Follows its play from outside (`BrainWatcher`): the commands it sends, its thinks as each ends, what it decides.\n\t * Returns the way to stop. What `watchComputer` and `recordDecisions` of `@v12-engine/engine/testing` stand on\n\t */\n\twatch(watcher: BrainWatcher): () => void {\n\t\tthis.watchers = [...this.watchers, watcher]\n\t\treturn () => {\n\t\t\tthis.watchers = this.watchers.filter((each) => each !== watcher)\n\t\t}\n\t}\n\n\t/** The player it plays */\n\tget playerId(): PlayerId {\n\t\treturn this.session.playerId\n\t}\n\n\t/** The game's definitions, as the seat has them */\n\tget registry(): Registry {\n\t\treturn this.session.registry\n\t}\n\n\t/** The tick of its picture of the game */\n\tget tick(): number {\n\t\treturn this.snapshot.tick\n\t}\n\n\t/** Seconds into the game, as of its picture of it */\n\tget time(): number {\n\t\treturn this.snapshot.tick / this.session.tickRate\n\t}\n\n\t/** The player it plays, as its picture shows them: resources, supply, tech (`own`). Nothing once out of the game. `view.me` is the same, never nothing */\n\tget me(): PlayerState | undefined {\n\t\treturn this.view.player(this.session.playerId)\n\t}\n\n\t/** A module of its, by key with its shape (`MELEE_ARMY`, `moduleKey`), or by id */\n\tmodule<M extends AiModule>(key: ModuleKey<M>): M | undefined\n\tmodule(id: string): AiModule | undefined\n\tmodule(key: string | ModuleKey<AiModule>): AiModule | undefined {\n\t\tconst id = typeof key === 'string' ? key : key.id\n\t\treturn this.modules.find((module) => module.id === id)\n\t}\n\n\t/**\n\t * What its areas play by this think (`AiSettings`): its settings' layers worked out, a flag that is a function of the\n\t * brain asked now. Each area reads its own (`ai.settings.economy`), over what its module was made with\n\t */\n\tget settings(): AiSettings {\n\t\treturn this.cache('settings', () => resolveSettings(this.layers, this))\n\t}\n\n\t/**\n\t * What was worked out once for this think, by key: a consideration asked by several goals, a set a few modules\n\t * read (`ai.cache('intruders', () => ...)`). Thrown away as the next think takes its picture\n\t */\n\tcache<T>(key: string, compute: () => T): T {\n\t\tif (this.memo.has(key)) return this.memo.get(key) as T\n\t\tconst value = compute()\n\t\tthis.memo.set(key, value)\n\t\treturn value\n\t}\n\n\t/** Whether a think is under way across ticks (`budget`): the seat asks it to think on at the next tick */\n\tget busy(): boolean {\n\t\treturn this.slice !== undefined || this.resume !== undefined\n\t}\n\n\t/**\n\t * One think, or one tick of it. A new picture of the game is taken, and the modules run over it in their order, as\n\t * many a tick as the budget allows (`budget`): so many modules, so many units looked at as they say. A module's error\n\t * is the seat's to catch, as a system's is\n\t */\n\tthink(): void {\n\t\tif (this.paused) return\n\t\tconst resume = this.resume\n\t\tthis.resume = undefined\n\t\tif (this.slice === undefined) {\n\t\t\tconst timed = this.profiling()\n\t\t\tconst start = timed ? performance.now() : 0\n\t\t\t// the one picture of the game this think reads: what the seat's session cuts to its fog. Timed apart, for\n\t\t\t// it is the part of a think the brain does not choose (F1); a think a loaded game resumes reads the picture it began with\n\t\t\tconst snapshot = resume?.snapshot ?? this.session.snapshot()\n\t\t\tconst taken = timed ? performance.now() : 0\n\t\t\tif (timed) this.snapshotTiming = averaged(this.snapshotTiming, taken - start)\n\t\t\tif (snapshot.outcome !== 'playing') return\n\t\t\tthis.snapshot = snapshot\n\t\t\tthis.memo.clear()\n\t\t\t// the picture read once, for every module: what cost and did not change (the roles) comes over from the last\n\t\t\tconst before = this.view\n\t\t\tthis.view = new AiView(snapshot, this.session, { before, roles: this.options.roles, strength: this.options.strength ?? this.def.strength })\n\t\t\tconst read = timed ? performance.now() : 0\n\t\t\t// and remembered: what the picture before says of this one's dead, what is out of sight now and was not. A think a\n\t\t\t// loaded game goes on with remembered its picture already: its knowledge is as the saved game's was, with the picture read\n\t\t\tif (this.def.knowledge !== false) {\n\t\t\t\tif (resume) this.knowledge.resume(this.view)\n\t\t\t\telse this.knowledge.update(this.view, before)\n\t\t\t\tthis.view.me.income = this.knowledge.own.incomes()\n\t\t\t}\n\t\t\tconst remembered = timed ? performance.now() : 0\n\t\t\tif (timed && this.def.knowledge !== false) this.knowledgeTiming = averaged(this.knowledgeTiming, remembered - read)\n\t\t\t// the ledger of the think: what is free, less what the goals hold from the think before\n\t\t\tthis.purse.begin(this.view)\n\t\t\tconst holds = this.goals.all()\n\t\t\tfor (const id in holds) if (holds[id].money) this.purse.reserve(id, holds[id].money!)\n\t\t\tthis.view.me.purse = this.purse.free\n\t\t\t// a think a loaded game goes on with was counted by the saved game\n\t\t\tif (!resume) {\n\t\t\t\tthis.thinks++\n\t\t\t\tthis.count()\n\t\t\t}\n\t\t\tthis.sent = 0\n\t\t\tthis.held = 0\n\t\t\tthis.slice = 0\n\t\t\tthis.passes = []\n\t\t\tthis.ticksSoFar = 0\n\t\t\tif (timed) this.viewTiming = averaged(this.viewTiming, read - taken + (performance.now() - remembered))\n\t\t\t// a think its budget may slice over ticks remembers how it began, for a save taken before it ends: the brain as it\n\t\t\t// stands here, its picture read and remembered and nothing run yet, which is what the passes are run again over\n\t\t\tif (this.budget.slices) {\n\t\t\t\tthis.began = this.memory()\n\t\t\t\tthis.toldDuring = []\n\t\t\t}\n\t\t\tif (resume) {\n\t\t\t\t// the passes the saved game had run this think, again, over the same picture, memory and budget, each hearing the\n\t\t\t\t// words it heard then: what they sent is in the game already, and what they wrote down in the save's log; so\n\t\t\t\t// nothing goes out, and they leave the brain as they did\n\t\t\t\tthis.replaying = true\n\t\t\t\ttry {\n\t\t\t\t\tfor (const [module, units, heard] of resume.passes) {\n\t\t\t\t\t\tthis.slice = module\n\t\t\t\t\t\tthis.budget.begin(units)\n\t\t\t\t\t\tthis.replayHeard = heard\n\t\t\t\t\t\tthis.pass(module)\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\tthis.replaying = false\n\t\t\t\t\tthis.replayHeard = undefined\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.ticksSoFar++\n\t\tthis.budget.begin()\n\t\tlet ran = 0\n\t\tlet at = this.slice as number\n\t\twhile (at < this.modules.length && ran < this.budget.modulesPerTick && this.budget.room) {\n\t\t\tconst module = this.modules[at]\n\t\t\tconst every = module.everyThinks ?? 1\n\t\t\t// `thinks` counts this one already: the first think is round 0. A module not run this think costs the budget nothing\n\t\t\tif (every !== 1 && (this.thinks - 1) % every !== (module.offset ?? 0) % every) {\n\t\t\t\tat++\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tran++\n\t\t\t// a module that stops for the tick ends it: it goes on first at the next\n\t\t\tconst more = this.pass(at)\n\t\t\tat = this.slice as number\n\t\t\tif (!more) break\n\t\t}\n\t\tthis.slice = at\n\t\tif (at >= this.modules.length) {\n\t\t\tthis.slice = undefined\n\t\t\tthis.began = undefined\n\t\t\tthis.passes = []\n\t\t\tthis.thinkTicks = this.ticksSoFar\n\t\t\t// what the think came to: the seconds since the last one spent waiting on money, where its building was\n\t\t\tif (this.plans.build.savingFor !== undefined) this.stats.blockedOnMoney += this.sinceLastThink()\n\t\t\tthis.lastThink = this.tick\n\t\t\tfor (const watcher of this.watchers) watcher.thought?.(this)\n\t\t}\n\t}\n\n\t/**\n\t * One pass of a module: run once, timed, and the think moved on past it, unless it stopped for the tick with more to\n\t * do (`budget.later()`), in which case it is where the think goes on at the next tick. Gives whether the think may go\n\t * on this tick\n\t */\n\tprivate pass(index: number): boolean {\n\t\tconst module = this.modules[index]\n\t\tconst { budget } = this\n\t\tconst before = budget.units\n\t\tif (budget.slices) this.passes.push([index, before, this.heard.length])\n\t\tbudget.deferred = false\n\t\tconst start = performance.now()\n\t\tmodule.think(this)\n\t\tconst took = performance.now() - start\n\t\tif (!(took <= (this.moduleLongest[module.id] ?? 0))) this.moduleLongest[module.id] = took\n\t\tif (this.profiling()) this.moduleTiming[module.id] = averaged(this.moduleTiming[module.id], took)\n\t\t// a module over its time is said once, and never cut: the budget is work, so that the game is the same everywhere\n\t\tif (budget.warnAfterMs !== undefined && took > budget.warnAfterMs && !this.warned.has(module.id) && !this.replaying) {\n\t\t\tthis.warned.add(module.id)\n\t\t\tthis.log.warn('ai', `the module \"${module.id}\" took ${took.toFixed(1)} ms, over ${budget.warnAfterMs}: said once`, {\n\t\t\t\tmodule: module.id,\n\t\t\t\tms: Math.round(took * 100) / 100\n\t\t\t})\n\t\t}\n\t\tif (budget.deferred) {\n\t\t\t// honoured where it looked at something this tick: one that did not and asks to go on would never end\n\t\t\tif (budget.units > before) return false\n\t\t\tif (!this.replaying && !this.warned.has(`later:${module.id}`)) {\n\t\t\t\tthis.warned.add(`later:${module.id}`)\n\t\t\t\tthis.log.warn('ai', `the module \"${module.id}\" asked to go on at the next tick having looked at nothing: taken to be done, said once`, {\n\t\t\t\t\tmodule: module.id\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tthis.slice = index + 1\n\t\treturn budget.room\n\t}\n\n\t/** Seconds between the think before and this one's picture: 0 for the first think */\n\tprivate sinceLastThink(): number {\n\t\treturn this.lastThink === undefined ? 0 : (this.tick - this.lastThink) / this.session.tickRate\n\t}\n\n\t/**\n\t * Counts, as a think begins, what its play adds up to (`stats`): the fighters that stood idle since the last think,\n\t * the commands the game refused since, and the orders it no longer needs to remember for the churn\n\t */\n\tprivate count(): void {\n\t\tconst { stats, view } = this\n\t\tstats.thinks++\n\t\tconst seconds = this.sinceLastThink()\n\t\tif (seconds > 0) stats.idleArmySeconds += view.mine.fighters().idle().length * seconds\n\t\tfor (const event of view.events.of('command')) if (event.refusal) stats.refused++\n\t\tconst forgotten = this.tick - CHURN_WINDOW * this.session.tickRate\n\t\tfor (const [id, last] of this.lastOrders) if (last.tick < forgotten || !view.mine.has(id)) this.lastOrders.delete(id)\n\t}\n\n\t/**\n\t * Sends a command, as the player would: counted (`sent`), carried out at the next tick. Returns the command's number;\n\t * -1 for one past what its profile lets a think send (`commandsPerThink`, a person's hands), which is not sent\n\t */\n\tsend(command: PlayerCommand): number {\n\t\t// run again in a loaded game: what it sent is in the game already, and what it remembers of it (`sentTo`) is remembered again\n\t\tif (this.replaying) {\n\t\t\tthis.sent++\n\t\t\tthis.churn(command)\n\t\t\treturn -1\n\t\t}\n\t\tconst cap = this.profile.commandsPerThink\n\t\tif (cap !== undefined && this.sent >= cap) {\n\t\t\tthis.held++\n\t\t\tthis.stats.held++\n\t\t\treturn -1\n\t\t}\n\t\tthis.sent++\n\t\tthis.stats.commands++\n\t\tthis.churn(command)\n\t\tfor (const watcher of this.watchers) watcher.sent?.(command, this)\n\t\treturn this.session.send(command)\n\t}\n\n\t/**\n\t * Counts an order sent to a unit for the same thing as its last within a few seconds (`AiStats.churn`): a unit told\n\t * to attack-move there every think never arrives, it stops and starts. The squads send an order once and watch it;\n\t * this is how a test or `simulate` sees that they do\n\t */\n\tprivate churn(command: PlayerCommand): void {\n\t\tconst key = orderKey(command)\n\t\t// a queued order is what comes after, not what the unit is told to do now\n\t\tif (key === undefined || (command as { queue?: boolean }).queue) return\n\t\tconst window = CHURN_WINDOW * this.session.tickRate\n\t\tfor (const id of (command as { entities: readonly number[] }).entities) {\n\t\t\tconst last = this.lastOrders.get(id)\n\t\t\tif (last && last.key === key && this.tick - last.tick <= window) this.stats.churn++\n\t\t\tthis.lastOrders.set(id, { key, tick: this.tick })\n\t\t}\n\t}\n\n\t/**\n\t * The last order it sent a unit lately (within a few seconds), as a key (`orderKey`: its kind, its target, its\n\t * place to the cell) with the tick: what keeps a module from telling a unit again what it is already doing, when the\n\t * unit changed hands (a squad of another goal) since. None for a unit told nothing lately\n\t */\n\tsentTo(unit: number): { key: string; tick: number } | undefined {\n\t\tconst last = this.lastOrders.get(unit)\n\t\treturn last && this.tick - last.tick <= CHURN_WINDOW * this.session.tickRate ? last : undefined\n\t}\n\n\t/**\n\t * The words the game told it and no module has taken yet (`world.computers.tell`), oldest first; those of one word\n\t * where given. Reading them takes nothing: `takeTold` does, as a told rule (`when.told`) does when it fires\n\t */\n\ttold(word?: string): readonly Told[] {\n\t\tconst heard = this.replayHeard === undefined ? this.heard : this.heard.slice(0, this.replayHeard)\n\t\treturn word === undefined ? heard : heard.filter((told) => told.word === word)\n\t}\n\n\t/**\n\t * Writes down a decision (`decisions`), with the reason that weighed most, in words: what the report's log and the\n\t * debug panel show, and the world's log at its `debug` level. `kind` says what it is about (`army`, `build`)\n\t */\n\tdecide(line: string, about: { kind?: string; goal?: string } = {}): void {\n\t\t// run again in a loaded game: the save's log has it already\n\t\tif (this.replaying) return\n\t\tconst decision: AiDecision = { tick: this.tick, kind: about.kind ?? 'other', line, ...(about.goal !== undefined && { goal: about.goal }) }\n\t\tthis.decisions.add(decision)\n\t\tfor (const watcher of this.watchers) watcher.decided?.(decision, this)\n\t\tif (this.log.says('debug'))\n\t\t\tthis.log.debug('ai', line, { player: this.playerId, kind: decision.kind, ...(about.goal !== undefined && { goal: about.goal }) })\n\t}\n\n\t/**\n\t * What it is thinking, as plain data (`AiReport`): its goals with their considerations, what it knows, its roles,\n\t * its economy, what it was told, what it decided, and each module's section. Made when asked: nothing in a think\n\t * waits for it. What `inspect` gives, and the debug panel's AI tab draws\n\t */\n\treport(): AiReport {\n\t\tconst { view } = this\n\t\tconst me = view.me\n\t\tconst sections: Record<string, unknown> = {}\n\t\tconst report: AiReport = {\n\t\t\tv: 1,\n\t\t\tbrain: this.def.id,\n\t\t\tplayer: this.playerId,\n\t\t\ttick: this.tick,\n\t\t\ttime: this.time,\n\t\t\ttickRate: this.session.tickRate,\n\t\t\tthinks: this.thinks,\n\t\t\t...(this.paused && { paused: true as const }),\n\t\t\tprofile: plainParts(this.options).kept as Record<string, unknown>,\n\t\t\tplaying: plainParts(this.profile).kept as AiProfile,\n\t\t\t...(this.goals.best !== undefined && { goal: this.goals.best }),\n\t\t\tgoals: this.goals.report(),\n\t\t\t...(this.def.knowledge !== false && { knowledge: this.knowledge.inspect() as unknown as KnowledgeReport }),\n\t\t\troles: view.inspect().roles as Record<string, string[]>,\n\t\t\teconomy: { resources: { ...me.resources }, income: { ...(me.income ?? {}) }, supply: [me.supplyUsed, me.supplyCap] },\n\t\t\tplans: this.plans.report(),\n\t\t\tsquads: this.squads.report(),\n\t\t\tthreat: threatOf(view.threat),\n\t\t\ttold: this.heard.map((told) => ({ word: told.word, tick: told.tick })),\n\t\t\tsent: this.sent,\n\t\t\t...(this.held && { held: this.held }),\n\t\t\t...(this.budget.slices && { budget: { ...this.budget.report(), ticks: this.thinkTicks } }),\n\t\t\tstats: { ...this.stats },\n\t\t\tdecisions: this.decisions.save(),\n\t\t\tsections\n\t\t}\n\t\t// what each area of its own says beside (its economy, its scouting, a game's own)\n\t\tfor (const area of this.areaList) area.reportTo?.(report)\n\t\tfor (const module of this.modules) {\n\t\t\tmodule.report?.(report)\n\t\t\tconst what = module.inspect?.()\n\t\t\tif (what !== undefined) sections[module.id] = what\n\t\t}\n\t\treturn report\n\t}\n\n\t/**\n\t * A goal's row of the report as a sentence: what it scored and why, whether it runs and with what, or what kept it\n\t * from running. Nothing for a goal the brain does not have\n\t */\n\texplain(goal: string): string | undefined {\n\t\tconst row = this.goals.report().find((each) => each.id === goal)\n\t\treturn row && explainGoal(row, (tick) => tick / this.session.tickRate, this.time)\n\t}\n\n\t/** Takes in a word from the game: a module takes it with `takeTold`. What the seat calls for `world.computers.tell` */\n\ttell(word: string, data: unknown, tick: number): void {\n\t\t// a paused brain thinks of nothing, so nothing of it would hear this one: it is answered here and now\n\t\tif (word === 'resume' && this.paused) {\n\t\t\tthis.paused = false\n\t\t\tthis.decide('resumes: told to', { kind: 'word' })\n\t\t\treturn\n\t\t}\n\t\tthis.heard.push({ word, ...(data !== undefined && { data }), tick })\n\t\tif (this.slice !== undefined && this.began) this.toldDuring.push({ word, ...(data !== undefined && { data }), tick })\n\t}\n\n\t/** Takes the words of one kind out of what it was told, oldest first, as many as `count` (all when left out): they are heard no more */\n\ttakeTold(word: string, count = Infinity): Told[] {\n\t\tconst taken: Told[] = []\n\t\t// a pass run again takes among the words it had heard then, not those told after it\n\t\tconst among = this.replayHeard ?? Infinity\n\t\tthis.heard = this.heard.filter((told, index) => {\n\t\t\tif (index >= among || told.word !== word || taken.length >= count) return true\n\t\t\ttaken.push(told)\n\t\t\treturn false\n\t\t})\n\t\tif (this.replayHeard !== undefined) this.replayHeard -= taken.length\n\t\treturn taken\n\t}\n\n\t/**\n\t * What it remembers, for a save: its numbers, each module's memory with its version, what it was told. A think under\n\t * way (`budget`) is kept as it began, with how far it got and its picture (`BrainMemory.thinking`): the game loaded\n\t * from the save runs it on to its end as the saved game does\n\t */\n\tsave(): BrainMemory {\n\t\tconst heard = this.session.can.computer?.pendingEvents().filter((event) => HEARD.has(event.type))\n\t\t// a think under way: the brain as it began, with how far it got over what picture, for a loaded game to run on\n\t\tif (this.slice !== undefined && this.began)\n\t\t\treturn {\n\t\t\t\t...this.began,\n\t\t\t\ttold: [...this.began.told, ...this.toldDuring.map((told) => ({ ...told }))],\n\t\t\t\t...(heard?.length && { heard }),\n\t\t\t\t// what the passes so far decided is in the log already; run again, they write nothing down\n\t\t\t\t...(this.decisions.list().length > 0 && { decisions: this.decisions.save() }),\n\t\t\t\tthinking: { snapshot: this.snapshot, passes: this.passes.map((pass) => [...pass] as [number, number, number]) }\n\t\t\t}\n\t\treturn { ...this.memory(), ...(heard?.length && { heard }) }\n\t}\n\n\t/** What its areas remember, by id: those that remember anything, and what a save had of areas not made since */\n\tprivate areaMemories(): AreaMemories {\n\t\tconst areas: AreaMemories = { ...this.waiting }\n\t\tfor (const area of this.areaList) if (area.remembers()) areas[area.id] = area.save()\n\t\treturn areas\n\t}\n\n\t/** What it remembers, but what its seat heard since it last thought */\n\tprivate memory(): BrainMemory {\n\t\tconst modules: BrainMemory['modules'] = {}\n\t\tfor (const module of this.modules) {\n\t\t\tconst data = module.save?.()\n\t\t\tif (data !== undefined) modules[module.id] = { v: module.version ?? 1, data }\n\t\t}\n\t\treturn {\n\t\t\tv: 2,\n\t\t\trng: this.rng.save(),\n\t\t\tthinks: this.thinks,\n\t\t\t...(this.paused && { paused: true }),\n\t\t\ttold: this.heard.map((told) => ({ ...told })),\n\t\t\tmodules,\n\t\t\tareas: this.areaMemories(),\n\t\t\t...(this.decisions.list().length > 0 && { decisions: this.decisions.save() }),\n\t\t\t...(this.lastOrders.size > 0 && { orders: [...this.lastOrders].map(([unit, last]) => ({ unit, ...last })) })\n\t\t}\n\t}\n\n\t/**\n\t * Takes back what `save` gave. A module's memory of another version goes through its `migrate`; without one, or with\n\t * nothing in the save for it, the module starts afresh, and the log says so once. Memory of a module the brain no\n\t * longer has is dropped, said too\n\t */\n\trestore(memory: BrainMemory): void {\n\t\tif (!memory || typeof memory !== 'object' || memory.v !== 2) {\n\t\t\tthis.log.warn('ai', 'the save remembers the computer player in a shape this brain does not read: it starts afresh', { brain: this.def.id })\n\t\t\treturn\n\t\t}\n\t\tthis.rng.restore(memory.rng)\n\t\tthis.thinks = memory.thinks ?? 0\n\t\t// a think the save was taken in the middle of: at the next tick, run again to where it was and on\n\t\tthis.resume = memory.thinking && {\n\t\t\tsnapshot: memory.thinking.snapshot,\n\t\t\t// the form before passes: so many modules run once each, the tick having looked at nothing before each\n\t\t\tpasses:\n\t\t\t\tmemory.thinking.passes ??\n\t\t\t\tArray.from({ length: memory.thinking.slice ?? 0 }, (_, module) => [module, 0, (memory.told ?? []).length] as [number, number, number])\n\t\t}\n\t\tthis.paused = !!memory.paused\n\t\tthis.heard = (memory.told ?? []).map((told) => ({ ...told }))\n\t\tthis.decisions.restore(memory.decisions)\n\t\tthis.lastOrders.clear()\n\t\tfor (const order of memory.orders ?? []) this.lastOrders.set(order.unit, { key: order.key, tick: order.tick })\n\t\tif (memory.heard?.length) this.session.can.computer?.restoreEvents(memory.heard)\n\t\t// before the modules: a module's own memory of an older shape may be brought into it (the melee player's `seen`). An\n\t\t// area not made yet takes its memory as a module first asks for it\n\t\tthis.waiting = { ...memory.areas }\n\t\tfor (const area of [...this.areaList]) {\n\t\t\tif (!(area.id in this.waiting)) continue\n\t\t\tconst kept = this.waiting[area.id]\n\t\t\tdelete this.waiting[area.id]\n\t\t\tif (!area.restore(kept))\n\t\t\t\tthis.log.info(\n\t\t\t\t\t'ai',\n\t\t\t\t\tarea.afresh ?? `the save remembers the computer player's ${area.id} in a shape this brain does not read: it starts afresh`\n\t\t\t\t)\n\t\t}\n\t\tconst read = new Set<string>()\n\t\tfor (const module of this.modules) {\n\t\t\t// under its id, or under one it was called before (`wasCalled`): a save made then\n\t\t\tlet kept = memory.modules?.[module.id]\n\t\t\tif (kept) read.add(module.id)\n\t\t\telse\n\t\t\t\tfor (const was of module.wasCalled ?? []) {\n\t\t\t\t\tkept = memory.modules?.[was]\n\t\t\t\t\tif (!kept) continue\n\t\t\t\t\tread.add(was)\n\t\t\t\t\tthis.log.info('ai', `the module \"${module.id}\" reads what the save kept as \"${was}\"`, { module: module.id, was })\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\tif (!kept) {\n\t\t\t\tif (module.save) this.log.info('ai', `the save has nothing for the module \"${module.id}\": it starts afresh`, { module: module.id })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst version = module.version ?? 1\n\t\t\tlet data = kept.data\n\t\t\tif (kept.v !== version) {\n\t\t\t\tdata = module.migrate?.(kept.data, kept.v)\n\t\t\t\tif (data === undefined) {\n\t\t\t\t\tthis.log.info('ai', `the module \"${module.id}\" saved version ${kept.v} and reads ${version}: it starts afresh`, {\n\t\t\t\t\t\tmodule: module.id,\n\t\t\t\t\t\tfrom: kept.v\n\t\t\t\t\t})\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tmodule.restore?.(data)\n\t\t}\n\t\tfor (const id of Object.keys(memory.modules ?? {}))\n\t\t\tif (!this.module(id) && !read.has(id))\n\t\t\t\tthis.log.info('ai', `the save remembers a module \"${id}\" this brain does not have: dropped`, { module: id })\n\t}\n\n\t/** What it is thinking, for the debug tools: its report (`report`) */\n\tinspect(): AiReport {\n\t\treturn this.report()\n\t}\n\n\t/** Lets its modules go of what they hold outside the brain */\n\tdispose(): void {\n\t\tfor (const module of this.modules) module.dispose?.()\n\t}\n}\n\n/**\n * Makes a brain from its definition for a seat: the session it plays through, the options it is seated with. What\n * a brain's seat does (`createBrainSystem`); for a seat made another way (`createComputerSystem`'s `make`)\n *\n * @beta\n */\nexport function createBrain(def: BrainDef, session: GameSession, options: AiOptions, context: BrainContext = {}): Brain {\n\treturn new Brain(def, session, options, context)\n}\n\n/** The threat map as the report has it: its cells with something in them, on the ground, what it remembers counted */\nfunction threatOf(map: ThreatMap): ThreatReport {\n\tconst round = (x: number) => Math.round(x * 10) / 10\n\treturn {\n\t\tcell: map.cell,\n\t\tcols: map.cols,\n\t\trows: map.rows,\n\t\tcells: map.cells({ remembered: true }).map((cell) => [cell.col, cell.row, round(cell.friendly), round(cell.enemy)])\n\t}\n}\n"],"mappings":"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"}