@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
package/dist/ai.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","names":["FLEE_AWAY","OWNER","build","build","reachOf"],"sources":["../src/ai/defence.ts","../src/ai/team.ts","../src/ai/computer.ts","../src/ai/define.ts","../src/ai/economy.ts","../src/ai/micro.ts","../src/ai/scouting.ts","../src/ai/waves.ts","../src/ai/melee/build.ts","../src/ai/melee/goals.ts","../src/ai/melee/heroes.ts","../src/ai/melee/production.ts","../src/ai/melee/surrender.ts","../src/ai/melee/index.ts","../src/ai/mission.ts","../src/ai/lanes.ts","../src/ai/missionRules.ts"],"sourcesContent":["import { distSq, type Vec2 } from '#engine/math'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { consider, curve, defineGoal, type GoalDef } from './goals'\nimport type { Squad } from './squads'\nimport type { Base, UnitSet } from './view'\nimport { pair, point, where } from './geometry'\n\n/*\n * Defence (AI plan, C4): what comes at the bases, and the answer to it. The old melee player sent the fighters\n * nearest any rival unit at its buildings, half again as strong, and nothing kept count: a raid at the mine every\n * minute was met the same way every minute, and the computer never thought of a tower there. This is what a player\n * does when the minimap flashes:\n *\n * - **Intruders** are the rivals' units within `radius` of one of its buildings (creeps are not: they camp, and are\n * for creeping). They are taken base by base: a **raid** is the intruders at one base, with their strength.\n * - **The answer is sized to the raid.** For each raid, strongest first, the fighters nearest it that make the odds of\n * the fight (`Strength.odds`, A4: Lanchester's square law, a number of the chance to win) at least `odds` (two in\n * three): one footman for a peasant that came to look, five for a party of four, not the whole army for a scout.\n * Each raid gets a squad of its own (`defence`, `defence 2`, …), sent to defend the place, which fights what comes\n * within the radius and goes back once it is gone. What nothing holds goes first, so that the wave out goes on.\n * - **The army comes home** (`recall`) when a raid is more than what is at home can meet: the goal is urgent then,\n * and as it scores past the wave (a raid over half the army's strength) it takes the squads out, whole.\n * - **Raids are counted** a base at a time: one is over once the base has stood clear `quiet` seconds. A base raided\n * `towerAfter` times wants `towers` towers (the build plan builds them by the base, and anew when lost).\n * - **Help** from an ally is C5's (`defendUsers`): the team's requests.\n *\n * The defence is a goal on the brain's picker (`defend`, the `defence()` module adds it), so it competes with the\n * others for units as any goal does, and the one order of who may move a unit holds. What it remembers (the raids of\n * each base) is plain data in the brain's memory (`BrainMemory.defence`).\n */\n\n/** The share of the army's strength a raid scores the whole point at: one as strong as the army is everything */\nconst SCORE_FROM = 0.6\n\n/**\n * How a brain defends its bases (`BrainDef.defence`, the seat's `AiOptions.defence` over it, the `defence()` module's\n * own under both). Data, kept in a save\n *\n * @beta\n */\nexport interface DefenceOptions {\n\t/** How near one of its buildings a rival's unit is an intruder: the seat's `defendRadius`, else 16 */\n\tradius?: number\n\t/**\n\t * The odds of the fight (`Strength.odds`) the defenders sent against a raid are to have: two in three when left out\n\t * (about four tenths stronger than the raid)\n\t */\n\todds?: number\n\t/**\n\t * Whether a raid more than what is at home can meet brings the army home (the goal is urgent: it takes squads out,\n\t * whole, once it scores past what they are on): yes when left out\n\t */\n\trecall?: boolean\n\t/** Towers a base wants once raided `towerAfter` times: 1 when left out. 0 for none */\n\ttowers?: number\n\t/** Raids at one base before it wants towers: 2 when left out */\n\ttowerAfter?: number\n\t/** The tower to build, by type id: the cheapest of the `tower` role its workers build when left out */\n\ttower?: string\n\t/** Seconds a base stands clear before a raid on it is over: 15 when left out */\n\tquiet?: number\n}\n\n/**\n * What the defence remembers between thinks, as a save keeps it: each base's raids\n *\n * @beta\n */\nexport interface DefenceMemory {\n\tv: 1\n\t/** By base (the id of what it is around): where, how many raids, the one on now (since when), when last seen, the strongest */\n\traids: Record<string, { at: Vec2; count: number; since?: number; last: number; most: number }>\n}\n\n/**\n * The intruders at one base, as the defence sees them this think (`ai.defence.raids()`)\n *\n * @beta\n */\nexport interface Raid {\n\t/** The base raided */\n\tbase: Base\n\t/** What the defence remembers it by: the id of what the base is around */\n\tkey: string\n\t/** The rivals' units there */\n\tintruders: UnitSet\n\t/** Their strength together (`Strength.of`) */\n\tstrength: number\n}\n\n/**\n * The defence as the report shows it (`AiReport.defence`): the raids on now with what answers each, every base's raids\n * so far, the towers it wants\n *\n * @beta\n */\nexport interface DefenceReport {\n\traids: { at: [number, number]; intruders: number[]; strength: number; squad?: string; defenders: number; since: number; count: number }[]\n\tbases: { at: [number, number]; raids: number; last: number }[]\n\ttowers: { at: [number, number]; want: string; status: string }[]\n}\n\n/**\n * The id of the defence's goal: what a game weighs it by (`AiOptions.weigh`)\n *\n * @beta\n */\nexport const DEFEND = 'defend'\n/** The name of the squad that answers the strongest raid; the others are `defence 2`, `defence 3` */\nconst SQUAD = 'defence'\nconst squadName = (i: number) => (i === 0 ? SQUAD : `${SQUAD} ${i + 1}`)\n\n/**\n * A brain's defence (`ai.defence`): the raids on its bases and the answer to each, through its goal (`defend`), and the\n * towers a raided base wants. Run by the `defence()` module each think; asked by whoever wants to know (`intruders`,\n * `raids`). Kept in the brain's memory (`BrainMemory.defence`)\n *\n * @internal\n */\nexport class Defence implements AiArea {\n\t/** What finds it on a brain (`ai.area(Defence)`): made the first time a module asks for it */\n\tstatic readonly id = 'defence'\n\tstatic make(ai: Brain): Defence {\n\t\treturn new Defence(ai)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'defence'\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 raids on the computer player in a shape this brain does not read: it starts afresh'\n\n\t/** Whether a `defence()` module is in the brain: without one, nothing here runs, and the goal is not the brain's */\n\tenabled = false\n\tprivate memory: DefenceMemory = { v: 1, raids: {} }\n\tprivate moduleOptions: DefenceOptions = {}\n\tprivate thoughtAt = -1\n\t/** The goal it answers raids through: added to the brain's picker by the module */\n\treadonly goal: GoalDef\n\n\tconstructor(\n\t\t/** The brain it defends for */\n\t\treadonly ai: Brain\n\t) {\n\t\tthis.goal = this.makeGoal()\n\t}\n\n\t/** Puts the `defence()` module's options under the brain's settings, and its goal on the picker */\n\tconfigure(options: DefenceOptions): void {\n\t\tthis.moduleOptions = options\n\t\tif (!this.enabled) this.ai.goals.add(this.goal)\n\t\tthis.enabled = true\n\t}\n\n\t/** How it defends: the module's options, the brain's settings over them (`ai.settings.defence`) */\n\tget options(): DefenceOptions {\n\t\treturn this.ai.cache('defence.options', () => ({ ...this.moduleOptions, ...this.ai.settings.defence }))\n\t}\n\n\t/** How near its buildings a rival's unit is an intruder */\n\tget radius(): number {\n\t\treturn this.options.radius ?? 16\n\t}\n\n\t/** How much stronger than a raid the defenders sent are: from the odds asked, by the square law (two in three: √2) */\n\tget margin(): number {\n\t\tconst odds = Math.min(0.95, Math.max(0.05, this.options.odds ?? 2 / 3))\n\t\treturn Math.sqrt(odds / (1 - odds))\n\t}\n\n\t/** The rivals' units at its buildings, once a think: not creeps that camp near (they are for creeping) */\n\tintruders(): UnitSet {\n\t\tconst { ai } = this\n\t\treturn ai.cache('defence.intruders', () => {\n\t\t\tconst { view } = ai\n\t\t\tconst buildings = view.mine.buildings()\n\t\t\tconst reach = this.radius * this.radius\n\t\t\treturn view.enemies\n\t\t\t\t.units()\n\t\t\t\t.alive()\n\t\t\t\t.where((enemy) => buildings.some((building) => distSq(building, enemy) < reach))\n\t\t})\n\t}\n\n\t/** The intruders base by base (each at the base whose buildings it is nearest), strongest first, once a think */\n\traids(): Raid[] {\n\t\tconst { ai } = this\n\t\treturn ai.cache('defence.raids', () => {\n\t\t\tconst { view } = ai\n\t\t\tconst intruders = this.intruders()\n\t\t\tif (!intruders.length) return []\n\t\t\tconst bases = view.bases()\n\t\t\tconst by = new Map<Base, EntityState[]>()\n\t\t\tfor (const enemy of intruders) {\n\t\t\t\tlet best: Base | undefined\n\t\t\t\tlet bestDistance = Infinity\n\t\t\t\tfor (const base of bases) {\n\t\t\t\t\tfor (const building of base.buildings) {\n\t\t\t\t\t\tconst d = distSq(building, enemy)\n\t\t\t\t\t\tif (d < bestDistance) {\n\t\t\t\t\t\t\tbestDistance = d\n\t\t\t\t\t\t\tbest = base\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (best) (by.get(best) ?? by.set(best, []).get(best)!).push(enemy)\n\t\t\t}\n\t\t\tconst raids: Raid[] = []\n\t\t\tfor (const [base, enemies] of by) {\n\t\t\t\tconst set = intruders.where((entity) => enemies.includes(entity))\n\t\t\t\traids.push({ base, key: String(base.centre.id), intruders: set, strength: set.strength() })\n\t\t\t}\n\t\t\treturn raids.sort((a, b) => b.strength - a.strength || a.base.centre.id - b.base.centre.id)\n\t\t})\n\t}\n\n\t/** Its fighters: what is gathering (a ghoul at the trees) is at work, not in the army */\n\tprivate army(units: UnitSet): UnitSet {\n\t\treturn units.fighters().where((entity) => entity.own?.order !== 'harvest')\n\t}\n\n\t/**\n\t * What is at home to meet a raid: the fighters nothing else holds (the pool) and what the defence holds already. What\n\t * a raid is weighed against for the army to come home\n\t */\n\tprivate atHome(): number {\n\t\tconst { ai } = this\n\t\treturn ai.cache('defence.home', () => {\n\t\t\tconst { goals } = ai\n\t\t\treturn this.army(ai.view.mine.where((unit) => !goals.holder(unit.id) || goals.holder(unit.id) === DEFEND)).strength()\n\t\t})\n\t}\n\n\t/** Whether the army is to come home: a raid more than what is at home can meet, where it may */\n\tprivate recalling(): boolean {\n\t\tif (this.options.recall === false) return false\n\t\tconst strongest = this.raids()[0]\n\t\treturn !!strongest && strongest.strength * this.margin > this.atHome()\n\t}\n\n\t/** The goal: scored on the raids against the army, urgent when the army is to come home, run with a squad a raid */\n\tprivate makeGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: DEFEND,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('intruders at my buildings', () => this.intruders().length, curve.step(1)),\n\t\t\t\t// six tenths for any intruder, the whole point for a raid as strong as the army: a lone scout at home does not\n\t\t\t\t// call the wave back, a raid does\n\t\t\t\tconsider(\n\t\t\t\t\t'the raid against my army',\n\t\t\t\t\t() => this.intruders().strength() / Math.max(1e-9, this.army(this.ai.view.mine).strength()),\n\t\t\t\t\tcurve.custom((x) => SCORE_FROM + (1 - SCORE_FROM) * Math.min(1, x))\n\t\t\t\t)\n\t\t\t],\n\t\t\t// it may break what the army out is committed to when what is at home cannot meet the raid\n\t\t\turgent: () => this.recalling(),\n\t\t\tclaims: { units: (_ai, available) => this.claim(available) },\n\t\t\tcommitment: 3,\n\t\t\trun: (_ai, claimed) => this.answer(claimed.units)\n\t\t})\n\t}\n\n\t/**\n\t * What the goal claims as it is picked: for each raid, strongest first, the fighters nearest it that make it as much\n\t * stronger as asked, out of what it may have: those nothing holds first, then (where the army is to come home) whole\n\t * squads, the nearest first\n\t */\n\tprivate claim(available: UnitSet): EntityState[] {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst chosen: EntityState[] = []\n\t\tconst taken = new Set<number>()\n\t\tconst fighters = this.army(available)\n\t\tfor (const raid of this.raids()) {\n\t\t\tconst target = raid.intruders.first()!\n\t\t\tconst need = raid.strength * this.margin\n\t\t\tlet got = 0\n\t\t\tconst free = fighters.items.filter((unit) => !taken.has(unit.id) && !ai.goals.holder(unit.id))\n\t\t\tfree.sort((a, b) => distSq(a, target) - distSq(b, target) || a.id - b.id)\n\t\t\tfor (const unit of free) {\n\t\t\t\tif (got >= need && chosen.length) break\n\t\t\t\tchosen.push(unit)\n\t\t\t\ttaken.add(unit.id)\n\t\t\t\tgot += view.strength.of(unit)\n\t\t\t}\n\t\t\tif (got >= need) continue\n\t\t\t// short: what others hold and it may take, a squad at a time\n\t\t\tconst squads = new Map<Squad | undefined, EntityState[]>()\n\t\t\tfor (const unit of fighters) {\n\t\t\t\tif (taken.has(unit.id) || !ai.goals.holder(unit.id)) continue\n\t\t\t\tconst squad = ai.squads.squadOf(unit)\n\t\t\t\t;(squads.get(squad) ?? squads.set(squad, []).get(squad)!).push(unit)\n\t\t\t}\n\t\t\tconst groups = [...squads.values()].sort((a, b) => distSq(a[0], target) - distSq(b[0], target) || a[0].id - b[0].id)\n\t\t\tfor (const group of groups) {\n\t\t\t\tif (got >= need) break\n\t\t\t\tfor (const unit of group) {\n\t\t\t\t\tchosen.push(unit)\n\t\t\t\t\ttaken.add(unit.id)\n\t\t\t\t\tgot += view.strength.of(unit)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn chosen\n\t}\n\n\t/**\n\t * The goal's run, each think it holds its claim: a squad for each raid, strongest first. A squad keeps answering the\n\t * raid at the base it was sent to while that goes on; what it lacks is made up from what the goal holds and no squad\n\t * has, then from what nothing holds, the nearest first; and where the army is to come home, from the squads of other\n\t * goals, whole\n\t */\n\tprivate answer(held: UnitSet): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst raids = this.raids()\n\t\tconst radius = this.radius\n\t\tconst margin = this.margin\n\t\t// the squads answering, each matched to the raid at the base it defends; a squad whose raid is over is let go of\n\t\tconst mine = ai.squads.of(DEFEND).squads.filter((squad) => squad.name === SQUAD || squad.name.startsWith(`${SQUAD} `))\n\t\tconst matched = new Map<Raid, Squad>()\n\t\tfor (const squad of mine) {\n\t\t\tconst at = squad.current?.data.at as Vec2 | undefined\n\t\t\tconst raid =\n\t\t\t\tat && raids.find((each) => !matched.has(each) && each.base.buildings.some((building) => distSq(building, at) <= radius * radius * 4))\n\t\t\tif (raid) matched.set(raid, squad)\n\t\t}\n\t\tconst inSquads = new Set(mine.filter((squad) => [...matched.values()].includes(squad)).flatMap((squad) => squad.data.units))\n\t\tconst spare = this.army(held).where((unit) => !inSquads.has(unit.id))\n\t\tconst used = new Set<number>()\n\t\tconst recall = this.recalling()\n\t\traids.forEach((raid, i) => {\n\t\t\tconst target = raid.intruders.nearest(matched.get(raid)?.centre() ?? raid.base.at)!\n\t\t\tlet squad = matched.get(raid)\n\t\t\tlet got = squad ? squad.strength() : 0\n\t\t\tconst need = raid.strength * margin\n\t\t\tconst more: number[] = []\n\t\t\tconst add = (units: Iterable<EntityState>) => {\n\t\t\t\tfor (const unit of units) {\n\t\t\t\t\tif (got >= need && (squad?.length || more.length)) return\n\t\t\t\t\tif (used.has(unit.id) || inSquads.has(unit.id)) continue\n\t\t\t\t\tused.add(unit.id)\n\t\t\t\t\tmore.push(unit.id)\n\t\t\t\t\tgot += view.strength.of(unit)\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst byDistance = (units: readonly EntityState[]) => [...units].sort((a, b) => distSq(a, target) - distSq(b, target) || a.id - b.id)\n\t\t\tadd(byDistance(spare.items))\n\t\t\tif (got < need) add(byDistance(this.army(ai.squads.pool()).idle().items))\n\t\t\tif (got < need && recall) {\n\t\t\t\t// the army home: other goals' squads, whole, the nearest first\n\t\t\t\tconst others = ai.squads\n\t\t\t\t\t.all()\n\t\t\t\t\t.squads.filter((each) => each.owner !== DEFEND && ai.goals.get(each.owner) && each.length)\n\t\t\t\t\t.sort((a, b) => distSq(a.centre() ?? target, target) - distSq(b.centre() ?? target, target))\n\t\t\t\tfor (const other of others) {\n\t\t\t\t\tif (got >= need) break\n\t\t\t\t\t// what the goal claimed of it already is its own: only the rest is taken\n\t\t\t\t\tconst ids = other.data.units.filter((id) => ai.goals.holder(id) !== DEFEND && !used.has(id))\n\t\t\t\t\tif (!ids.length) continue\n\t\t\t\t\t// only what the raid needs of it: the rest stays with its goal (taken and left in the pool, its goal would\n\t\t\t\t\t// pick it up again, and its squad be made anew: orders sent twice)\n\t\t\t\t\tconst before = more.length\n\t\t\t\t\t// its fighters: a worker on another goal's errand (a scout) goes on with it, and is not sent to a fight (AI1)\n\t\t\t\t\tadd(this.army(view.mine.where((unit) => ids.includes(unit.id))).items)\n\t\t\t\t\tconst called = more.slice(before)\n\t\t\t\t\tif (!called.length) continue\n\t\t\t\t\tai.goals.take(called, 'urgent')\n\t\t\t\t\tai.decide(\n\t\t\t\t\t\t`calls ${called.length === ids.length ? other.name : `${called.length} of ${other.name}`} home to meet a raid of ${raid.intruders.length} at ${where(raid.base.at)}`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tkind: 'defence',\n\t\t\t\t\t\t\tgoal: DEFEND\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!squad) {\n\t\t\t\tif (!more.length) return\n\t\t\t\tsquad = ai.squads.make(squadName(i), more, { retreatAt: false, owner: DEFEND })\n\t\t\t\tsquad.defend(point(target), radius)\n\t\t\t\tai.decide(\n\t\t\t\t\t`answers a raid of ${raid.intruders.length} at ${where(raid.base.at)} with ${more.length} (strength ${Math.round(got)} to ${Math.round(raid.strength)})`,\n\t\t\t\t\t{ kind: 'defence', goal: DEFEND }\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (more.length) squad.add(more, 'sent to meet the raid')\n\t\t\t// a squad that holds the place the raid is at, sent on to where it went next once that is out of its reach\n\t\t\tconst at = squad.current?.data.at as Vec2 | undefined\n\t\t\tif (!at || squad.done !== undefined || distSq(at, target) > radius * radius) squad.defend(point(target), radius)\n\t\t})\n\t\t// the squads whose raid is over: let go of, their units back to the pool for the goal to give up\n\t\tfor (const squad of mine) if (![...matched.values()].includes(squad) && squad.alive) ai.squads.disband(squad, 'its raid is over')\n\t}\n\n\t/**\n\t * The think, once a think: the raids counted base by base (one begins as intruders come to a base that stood clear,\n\t * and is over once it stood clear `quiet` seconds again), and the towers a base raided often enough wants\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\tconst { view } = ai\n\t\tconst options = this.options\n\t\tconst quiet = (options.quiet ?? 15) * ai.session.tickRate\n\t\tconst raids = this.raids()\n\t\tconst kept = this.memory.raids\n\t\tfor (const raid of raids) {\n\t\t\tconst record = (kept[raid.key] ??= { at: point(raid.base.at), count: 0, last: ai.tick, most: 0 })\n\t\t\tif (record.since === undefined) {\n\t\t\t\trecord.count++\n\t\t\t\trecord.since = ai.tick\n\t\t\t\trecord.most = 0\n\t\t\t\tai.decide(\n\t\t\t\t\t`raid ${record.count} on the base at ${where(raid.base.at)}: ${raid.intruders.length} of theirs, strength ${Math.round(raid.strength)}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tkind: 'defence'\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t}\n\t\t\trecord.last = ai.tick\n\t\t\trecord.most = Math.max(record.most, raid.strength)\n\t\t}\n\t\tconst bases = new Set(view.bases().map((base) => String(base.centre.id)))\n\t\tfor (const key in kept) {\n\t\t\tconst record = kept[key]\n\t\t\tif (record.since !== undefined && ai.tick - record.last > quiet) delete record.since\n\t\t\t// a base that is no more is forgotten\n\t\t\tif (!bases.has(key)) {\n\t\t\t\tdelete kept[key]\n\t\t\t\tai.plans.build.drop(`defence.tower:${key}`)\n\t\t\t}\n\t\t}\n\t\tthis.towers()\n\t}\n\n\t/** The tower it builds: the one named, or the cheapest of the `tower` role its workers build */\n\ttowerType(): string | undefined {\n\t\tconst { ai } = this\n\t\tconst named = this.options.tower\n\t\tif (named) return ai.registry.units.has(named) ? named : undefined\n\t\tconst { view, registry } = ai\n\t\tconst builds = new Set(view.typesOf('worker').flatMap((def) => def.builds ?? []))\n\t\tconst money = registry.currency ?? registry.resources[0]?.id ?? ''\n\t\tconst towers = view.typesOf('tower').filter((def) => builds.has(def.id))\n\t\treturn [...towers].sort((a, b) => (a.cost?.[money] ?? 0) - (b.cost?.[money] ?? 0))[0]?.id\n\t}\n\n\t/** The towers a base raided often enough wants: a standing want of the build plan, by the base */\n\tprivate towers(): void {\n\t\tconst { ai } = this\n\t\tconst options = this.options\n\t\tconst wanted = options.towers ?? 1\n\t\tconst after = options.towerAfter ?? 2\n\t\tconst type = this.towerType()\n\t\tif (!type || wanted <= 0) return\n\t\tconst { view } = ai\n\t\tfor (const base of view.bases()) {\n\t\t\tconst key = String(base.centre.id)\n\t\t\tconst record = this.memory.raids[key]\n\t\t\tconst id = `defence.tower:${key}`\n\t\t\tif (!record || record.count < after) continue\n\t\t\tconst at = point(base.at)\n\t\t\tif (!ai.plans.build.get(id))\n\t\t\t\tai.decide(`wants ${wanted === 1 ? 'a tower' : `${wanted} towers`} at the base at ${where(at)}: raided ${record.count} times`, {\n\t\t\t\t\tkind: 'defence'\n\t\t\t\t})\n\t\t\tai.plans.build.want({\n\t\t\t\tid,\n\t\t\t\ttype,\n\t\t\t\t// the towers elsewhere, and so many here\n\t\t\t\tcount: (brain) => {\n\t\t\t\t\tconst all = brain.view.mine.ofType(type)\n\t\t\t\t\treturn all.length - all.near(at, 14).length + wanted\n\t\t\t\t},\n\t\t\t\tnear: at,\n\t\t\t\twithin: 12,\n\t\t\t\tpriority: 45,\n\t\t\t\tkeep: true,\n\t\t\t\tby: 'defence'\n\t\t\t})\n\t\t}\n\t}\n\n\t/** The defence as the report shows it */\n\treport(): DefenceReport {\n\t\tconst { ai } = this\n\t\tif (!this.enabled) return { raids: [], bases: [], towers: [] }\n\t\tconst squads = ai.squads.of(DEFEND).squads\n\t\treturn {\n\t\t\traids: this.raids().map((raid) => {\n\t\t\t\tconst squad = squads.find((each) => {\n\t\t\t\t\tconst at = each.current?.data.at as Vec2 | undefined\n\t\t\t\t\treturn !!at && raid.base.buildings.some((building) => distSq(building, at) <= this.radius * this.radius * 4)\n\t\t\t\t})\n\t\t\t\tconst record = this.memory.raids[raid.key]\n\t\t\t\treturn {\n\t\t\t\t\tat: pair(raid.base.at),\n\t\t\t\t\tintruders: raid.intruders.map((unit) => unit.id),\n\t\t\t\t\tstrength: Math.round(raid.strength),\n\t\t\t\t\t...(squad && { squad: squad.name }),\n\t\t\t\t\tdefenders: squad?.length ?? 0,\n\t\t\t\t\tsince: record?.since ?? ai.tick,\n\t\t\t\t\tcount: record?.count ?? 1\n\t\t\t\t}\n\t\t\t}),\n\t\t\tbases: Object.values(this.memory.raids).map((record) => ({ at: pair(record.at), raids: record.count, last: record.last })),\n\t\t\ttowers: ai.plans.build\n\t\t\t\t.list()\n\t\t\t\t.filter((want) => want.id?.startsWith('defence.tower:'))\n\t\t\t\t.map((want) => ({ at: pair(want.near as Vec2), want: want.id!, status: ai.plans.build.status(want.id!) ?? 'new' }))\n\t\t}\n\t}\n\n\t/** What it remembers, 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.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\treport.defence = this.report()\n\t}\n\n\tsave(): DefenceMemory {\n\t\treturn structuredClone(this.memory)\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 DefenceMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = { v: 1, raids: structuredClone(given.raids ?? {}) }\n\t\treturn true\n\t}\n}\n\n/**\n * The defence module: the raids on the bases counted each think, the towers a raided base wants (`ai.defence.think`),\n * and the `defend` goal put on the brain's picker, which answers each raid with a squad of its own. With how it defends\n * where the brain's definition and the seat's options say nothing (`DefenceOptions`)\n *\n * @beta\n */\nexport const defence = (options: DefenceOptions = {}): AiModuleDef =>\n\tdefineModule('defence', (ai: Brain): AiModule => {\n\t\tai.area(Defence).configure(options)\n\t\treturn {\n\t\t\tid: 'defence',\n\t\t\t// before the goals are picked: the raids are counted as the goal reads them\n\t\t\tphase: 'sense',\n\t\t\tthink: () => ai.area(Defence).think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tdefence?: DefenceMemory\n\t}\n}\n","import type { PlayerId } from '#engine/entity'\nimport { DEFEND, Defence } from './defence'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { consider, curve, defineGoal, type GoalDef } from './goals'\nimport type { UnitSet } from './view'\nimport { pair, point, where } from './geometry'\n\n/*\n * Team play (AI plan, C5): computers that play on one side as one side. Before this, a computer ally neither helped\n * nor answered: a person's ping went unheard, an ally's hall burned in plain sight, two computers of a team sent their\n * waves a minute apart and lost them one after the other. This is the word between them, and with the people on\n * their side:\n *\n * - **The team's board** (`TeamBoard`): one per team, shared by the team's computers, kept in the world as a state\n * of its own (`core.ai.teams`) so that a save keeps it. It is never replicated: no player, human or computer, gets\n * it in a snapshot, and only the debug panel's AI tab shows it (through the report). Pooling what the computers of a\n * team know is fair by construction: sight is per team already, so the board holds nothing a human ally could not\n * see. Each computer writes to it through its brain (`ai.team`) as it thinks, in the seats' order, which is the same\n * every game.\n * - **Requests** (`request`): `help` at a place, with the strength seen there, for so long. A computer posts one when a\n * raid on it is more than it can meet at home; it hears a person's ping as one (`danger` and `assist` at a place: help\n * there; `look` and `onMyWay` noted); and damage it sees done to an ally's units or buildings is one, sized by the\n * enemies seen there. The `help` goal (`defendUsers`, the classic Defend Users) weighs a request against what it can\n * send (`helpOdds`): it sends a squad of its idle fighters, as many as make the odds, and never its last defence.\n * - **Attacking together** (`together`): the first computer of the team whose wave is ready proposes a target and a\n * time a little ahead (`gatherFor`); the others join by their next think if their wave is ready, or decline; at the\n * time every computer that joined sends its wave to the target. Who proposes first follows the seats' think offsets,\n * the same every game: the lowest seat often leads, which is fine.\n * - **What they know of the enemy, pooled** (`enemyBases`): each computer puts the bases it remembers on the board;\n * any computer of the team reads them all.\n * - **Saying things** (`say`, off by default): a line of chat to its side as it sends a wave, comes to help, falls\n * back. The lines are the game's (`lines`): the kit never puts words in a game.\n */\n\n/**\n * Something one computer of a team asks of the others, on the team's board: help at a place\n *\n * @beta\n */\nexport interface TeamRequest {\n\t/** Its number on the board */\n\tid: number\n\tkind: 'help' | 'attack' | 'defend' | 'rally'\n\t/** Who asks: a computer of the team, or a person whose ping or plight it is */\n\tfrom: PlayerId\n\tat: Vec2\n\t/** The enemy strength seen there as it was asked (0 for none seen: a ping on a place) */\n\tstrength: number\n\t/** The tick it is asked until */\n\tuntil: number\n\t/** What it came of: a raid on a computer, a person's ping, damage seen done to an ally, a word of the game's */\n\tby: 'raid' | 'ping' | 'damage' | 'word'\n\t/** The computers that answered it */\n\tanswered: PlayerId[]\n}\n\n/**\n * An attack the computers of a team agree on (`together`): where, when, who proposed it, who joined and who did not\n *\n * @beta\n */\nexport interface AttackPlan {\n\ttarget: Vec2\n\t/** The tick the waves go at */\n\tat: number\n\tby: PlayerId\n\tjoined: PlayerId[]\n\tdeclined: PlayerId[]\n\t/** The tick it was proposed at */\n\tsince: number\n}\n\n/**\n * A team's board as the world keeps it (`core.ai.teams`, by team): plain data, kept in a save, never replicated\n *\n * @beta\n */\nexport interface TeamBoard {\n\tv: 1\n\trequests: TeamRequest[]\n\tplan?: AttackPlan\n\t/** What each computer of the team remembers of the enemy's bases, and when it last thought */\n\tknown: Record<string, { tick: number; bases: { owner: PlayerId; at: Vec2; last: number }[] }>\n\t/** The next request's number */\n\tnext: number\n}\n\n/**\n * How a brain plays with its team (`BrainDef.team`, the seat's `AiOptions.team` over it, the `team()` module's own\n * under both). Data\n *\n * @beta\n */\nexport interface TeamOptions {\n\t/** Whether it helps its allies, people and computers, where asked (the classic Defend Users): yes when left out */\n\tdefendUsers?: boolean\n\t/**\n\t * Whether it does what an ally's ping asks besides help (`GameRules.talk.pings.meanings`): a squad sent to fight at\n\t * an `attack` (a push), one to hold a place at a `defend` (a hold), its squads out brought home at a `rally` (a\n\t * retreat). Yes when left out\n\t */\n\tanswerPings?: boolean\n\t/** The odds of the fight (`Strength.odds`) what it sends to help is to have: one in two when left out */\n\thelpOdds?: number\n\t/** Whether it asks its team for help with a raid more than it can meet: yes when left out */\n\taskForHelp?: boolean\n\t/** Whether its waves wait for the team's plan and go together: no when left out */\n\ttogether?: boolean\n\t/** Seconds ahead of the proposal the waves of a plan go: 20 when left out */\n\tgatherFor?: number\n\t/** Seconds a request stands: 30 when left out */\n\trequestFor?: number\n\t/** Whether it says a line to its side as it sends a wave, comes to help, falls back: no when left out */\n\tsay?: boolean\n\t/** Its lines, the game's words: `{ attacking, helping, retreating }`. Nothing is said for a line not given */\n\tlines?: Partial<Record<'attacking' | 'helping' | 'retreating', string>>\n}\n\n/**\n * What a brain remembers of its team play between thinks (`BrainMemory.team`): up to when it heard, when it last said\n * each line\n *\n * @beta\n */\nexport interface TeamPlayMemory {\n\tv: 1\n\theard: number\n\tsaid: Record<string, number>\n}\n\n/**\n * Team play as the report shows it (`AiReport.team`): the team, its computers, the requests on its board, the plan of\n * an attack together, how many enemy bases the team knows\n *\n * @beta\n */\nexport interface TeamReport {\n\tteam: number\n\tcomputers: PlayerId[]\n\trequests: {\n\t\tid: number\n\t\tkind: TeamRequest['kind']\n\t\tfrom: PlayerId\n\t\tat: [number, number]\n\t\tstrength: number\n\t\tby: TeamRequest['by']\n\t\tanswered: PlayerId[]\n\t\tleft: number\n\t}[]\n\tplan?: { target: [number, number]; in: number; by: PlayerId; joined: PlayerId[]; declined: PlayerId[] }\n\tenemyBases: number\n}\n\n/** How near two requests of one asker are to be one */\nconst SAME_PLACE = 16\n/** How near the place of a request the enemies seen there are counted in its strength */\nconst SEEN_NEAR = 16\n/** How far a computer's fighters go to help: further is across the map */\nconst HELP_REACH = 80\n/** The most units sent to a call with no enemy seen there: enough to look and to hold a little */\nconst HELP_UNSEEN = 3\n/** Seconds a plan waits past its time for the waves of those that joined, before it is over */\nconst PLAN_OVER = 30\n/**\n * The id of the help goal\n *\n * @beta\n */\nexport const HELP = 'help'\n\n/**\n * The id of the goal that does what an ally's ping asks (`push`, `hold`): `pinged`\n *\n * @beta\n */\nexport const PINGED = 'pinged'\n/** What is sent at a ping, by what it asks: the squad's name */\nconst PING_SQUADS = { attack: 'push', defend: 'hold' } as const\n\n/**\n * An empty board\n *\n * @internal\n */\nexport const emptyTeam = (): TeamBoard => ({ v: 1, requests: [], known: {}, next: 1 })\n\n/**\n * A brain's team play (`ai.team`): the team's board (`board`: requests, the plan of an attack together, what each\n * computer knows), the `help` goal, and what it says. The board is the world's (`core.ai.teams`) where the seat hands\n * it over (`BrainContext.team`), else its own: a brain made by hand plays alone\n *\n * @internal\n */\nexport class Team implements AiArea {\n\t/** What finds it on a brain (`ai.area(Team)`): made the first time a module asks for it */\n\tstatic readonly id = 'team'\n\tstatic make(ai: Brain): Team {\n\t\treturn new Team(ai, ai.teamBoard)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'team'\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 team play in a shape this brain does not read: it starts afresh'\n\n\t/** Whether a `team()` module is in the brain */\n\tenabled = false\n\tprivate memory: TeamPlayMemory = { v: 1, heard: -1, said: {} }\n\tprivate moduleOptions: TeamOptions = {}\n\tprivate own: TeamBoard = emptyTeam()\n\t/** The help goal: added to the brain's picker by the module, where it defends users */\n\treadonly goal: GoalDef\n\t/** The goal that does what an ally's ping asks (`answerPings`): added with the help goal */\n\treadonly pingGoal: GoalDef\n\n\tconstructor(\n\t\t/** The brain it plays for */\n\t\treadonly ai: Brain,\n\t\t/** The team's board, as the seat hands it over: the world's, read anew each time (a load replaces it) */\n\t\tprivate readonly shared?: () => TeamBoard\n\t) {\n\t\tthis.goal = this.makeGoal()\n\t\tthis.pingGoal = this.makePingGoal()\n\t}\n\n\t/** Puts the `team()` module's options under the brain's settings, and the help goal on the picker */\n\tconfigure(options: TeamOptions): void {\n\t\tthis.moduleOptions = options\n\t\tif (!this.enabled && (this.options.defendUsers ?? true)) this.ai.goals.add(this.goal)\n\t\tif (!this.enabled && (this.options.answerPings ?? true)) this.ai.goals.add(this.pingGoal)\n\t\tthis.enabled = true\n\t}\n\n\t/** How it plays with its team: the module's options, the brain's settings over them (`ai.settings.team`) */\n\tget options(): TeamOptions {\n\t\treturn this.ai.cache('team.options', () => ({ ...this.moduleOptions, ...this.ai.settings.team }))\n\t}\n\n\t/** Whether its waves wait for the team's plan (`together`) */\n\tget together(): boolean {\n\t\treturn this.enabled && !!this.options.together\n\t}\n\n\t/** The team's board: the world's, shared by the team's computers, or its own where the seat gave none */\n\tget board(): TeamBoard {\n\t\treturn this.shared?.() ?? this.own\n\t}\n\n\t/** Its team's number */\n\tget team(): number {\n\t\treturn this.ai.view.me.team\n\t}\n\n\t/** The computers of its team, as seen on the board lately (each writes itself as it thinks), itself among them */\n\tcomputers(): PlayerId[] {\n\t\tconst { board, ai } = this\n\t\tconst recent = ai.tick - 10 * ai.session.tickRate\n\t\treturn Object.entries(board.known)\n\t\t\t.filter(([, known]) => known.tick >= recent)\n\t\t\t.map(([id]) => Number(id))\n\t\t\t.sort((a, b) => a - b)\n\t}\n\n\t/** The requests on the board, those of a kind where given: those still standing */\n\trequests(kind?: TeamRequest['kind']): TeamRequest[] {\n\t\tconst { tick } = this.ai\n\t\treturn this.board.requests.filter((each) => each.until > tick && (kind === undefined || each.kind === kind))\n\t}\n\n\t/**\n\t * Asks the team for something at a place: a request on the board, or the one of the same asker, kind and place made\n\t * to stand longer, with the strength seen now. Gives back the request\n\t */\n\trequest(\n\t\tkind: TeamRequest['kind'],\n\t\tat: Vec2,\n\t\tstrength: number,\n\t\tby: TeamRequest['by'],\n\t\tfrom: PlayerId = this.ai.playerId,\n\t\tseconds?: number\n\t): TeamRequest {\n\t\tconst { ai, board } = this\n\t\tconst until = ai.tick + Math.round((seconds ?? this.options.requestFor ?? 30) * ai.session.tickRate)\n\t\tconst same = board.requests.find(\n\t\t\t(each) => each.from === from && each.kind === kind && each.until > ai.tick && distSq(each.at, at) <= SAME_PLACE * SAME_PLACE\n\t\t)\n\t\tif (same) {\n\t\t\tsame.until = Math.max(same.until, until)\n\t\t\tsame.strength = Math.max(same.strength, strength)\n\t\t\treturn same\n\t\t}\n\t\tconst request: TeamRequest = { id: board.next++, kind, from, at: point(at), strength, until, by, answered: [] }\n\t\tboard.requests.push(request)\n\t\tai.decide(`asks for ${kind} at ${where(at)}${from === ai.playerId ? '' : ` for player ${from}`} (${by}, strength ${Math.round(strength)})`, {\n\t\t\tkind: 'team'\n\t\t})\n\t\treturn request\n\t}\n\n\t/** The enemy's bases the team knows, every computer's put together: one a place, the latest seen */\n\tenemyBases(): { owner: PlayerId; at: Vec2; last: number }[] {\n\t\tconst merged: { owner: PlayerId; at: Vec2; last: number }[] = []\n\t\tconst known = this.board.known\n\t\tfor (const id of Object.keys(known).sort((a, b) => Number(a) - Number(b))) {\n\t\t\tfor (const base of known[id].bases) {\n\t\t\t\tconst same = merged.find((each) => each.owner === base.owner && distSq(each.at, base.at) < SAME_PLACE * SAME_PLACE)\n\t\t\t\tif (same) same.last = Math.max(same.last, base.last)\n\t\t\t\telse merged.push({ ...base, at: point(base.at) })\n\t\t\t}\n\t\t}\n\t\treturn merged\n\t}\n\n\t/** The plan of an attack together, while it stands */\n\tget plan(): AttackPlan | undefined {\n\t\tconst plan = this.board.plan\n\t\treturn plan && this.ai.tick <= plan.at + PLAN_OVER * this.ai.session.tickRate ? plan : undefined\n\t}\n\n\t/** Proposes an attack together: a target, the waves to go `gatherFor` seconds from now. Joined by the proposer */\n\tpropose(target: Vec2): AttackPlan {\n\t\tconst { ai } = this\n\t\tconst plan: AttackPlan = {\n\t\t\ttarget: point(target),\n\t\t\tat: ai.tick + Math.round((this.options.gatherFor ?? 20) * ai.session.tickRate),\n\t\t\tby: ai.playerId,\n\t\t\tjoined: [ai.playerId],\n\t\t\tdeclined: [],\n\t\t\tsince: ai.tick\n\t\t}\n\t\tthis.board.plan = plan\n\t\tai.decide(`proposes an attack together on ${where(target)} in ${this.options.gatherFor ?? 20} s`, { kind: 'team' })\n\t\treturn plan\n\t}\n\n\t/** Joins the plan standing: its wave goes with the others' */\n\tjoin(): void {\n\t\tconst plan = this.plan\n\t\tif (!plan || plan.joined.includes(this.ai.playerId)) return\n\t\tplan.joined.push(this.ai.playerId)\n\t\tplan.declined = plan.declined.filter((each) => each !== this.ai.playerId)\n\t\tthis.ai.decide(`joins player ${plan.by}'s attack on ${where(plan.target)}`, { kind: 'team' })\n\t}\n\n\t/** Says no to the plan standing: its wave goes on its own time */\n\tdecline(): void {\n\t\tconst plan = this.plan\n\t\tif (!plan || plan.declined.includes(this.ai.playerId) || plan.joined.includes(this.ai.playerId)) return\n\t\tplan.declined.push(this.ai.playerId)\n\t\tthis.ai.decide(`declines player ${plan.by}'s attack on ${where(plan.target)}: its wave is not ready`, { kind: 'team' })\n\t}\n\n\t/** Says a line of the game's to its side (`say`, `lines`), no more than once in ten seconds a line */\n\tsay(line: 'attacking' | 'helping' | 'retreating'): void {\n\t\tconst { ai } = this\n\t\tconst options = this.options\n\t\tconst text = options.lines?.[line]\n\t\tif (!this.enabled || !options.say || !text) return\n\t\tconst last = this.memory.said[line]\n\t\tif (last !== undefined && ai.tick - last < 10 * ai.session.tickRate) return\n\t\tthis.memory.said[line] = ai.tick\n\t\tai.send({ type: 'chat', text, to: 'allies' })\n\t}\n\n\t/**\n\t * The think, once a think: the board brought up to date (what is over dropped, itself and what it knows written),\n\t * the people heard (pings, damage to allies), its own raids asked help for, the plan answered\n\t */\n\tthink(): void {\n\t\tconst { ai, board } = this\n\t\tconst tick = ai.tick\n\t\tboard.requests = board.requests.filter((each) => each.until > tick)\n\t\tif (board.plan && tick > board.plan.at + PLAN_OVER * ai.session.tickRate) delete board.plan\n\t\tif (ai.def.knowledge !== false) {\n\t\t\tboard.known[ai.playerId] = {\n\t\t\t\ttick,\n\t\t\t\tbases: ai.knowledge.enemy\n\t\t\t\t\t.bases()\n\t\t\t\t\t.filter((base) => !base.gone)\n\t\t\t\t\t.map((base) => ({ owner: base.owner, at: point(base.at), last: base.last }))\n\t\t\t}\n\t\t} else board.known[ai.playerId] = { tick, bases: [] }\n\t\tconst heardFrom = this.memory.heard\n\t\tthis.memory.heard = tick\n\t\tif (ai.def.knowledge !== false && heardFrom >= 0) this.hear(heardFrom)\n\t\tif (this.options.answerPings ?? true) this.fallBack()\n\t\tif ((this.options.askForHelp ?? true) && ai.area(Defence).enabled) {\n\t\t\tfor (const raid of ai.area(Defence).raids()) {\n\t\t\t\tif (raid.strength * ai.area(Defence).margin <= this.homeStrength()) continue\n\t\t\t\tthis.request('help', raid.base.at, raid.strength, 'raid')\n\t\t\t}\n\t\t}\n\t\t// a plan of another's not joined by the think after it was proposed: declined\n\t\tconst plan = this.plan\n\t\tif (plan && plan.by !== ai.playerId && !plan.joined.includes(ai.playerId) && plan.since < heardFrom) this.decline()\n\t}\n\n\t/**\n\t * An ally's ping to fall back (`rally`), not answered yet: its squads out (waves, raids, harassers, a push; not what\n\t * defends, helps or looks) come home, and it says so. What that ally pinged to push or hold before is not done any\n\t * more (`pinged`): the latest ping of a person's is what it asks\n\t */\n\tprivate fallBack(): void {\n\t\tconst { ai } = this\n\t\tconst home = ai.view.home()\n\t\tif (!home) return\n\t\tfor (const request of this.requests('rally')) {\n\t\t\tif (request.by !== 'ping' || request.from === ai.playerId || request.answered.includes(ai.playerId)) continue\n\t\t\trequest.answered.push(ai.playerId)\n\t\t\tconst out = ai.squads\n\t\t\t\t.all()\n\t\t\t\t.squads.filter(\n\t\t\t\t\t(squad) =>\n\t\t\t\t\t\tsquad.alive &&\n\t\t\t\t\t\tsquad.length &&\n\t\t\t\t\t\t(![DEFEND, HELP, PINGED, 'scout'].includes(squad.owner ?? '') || squad.name === PING_SQUADS.attack) &&\n\t\t\t\t\t\tsquad.current?.kind !== 'retreat'\n\t\t\t\t)\n\t\t\tfor (const squad of out) squad.retreat(home, `player ${request.from} asks to fall back`)\n\t\t\tai.decide(`falls back home at player ${request.from}'s ping: ${out.length ? out.map((squad) => squad.name).join(', ') : 'nothing out'}`, {\n\t\t\t\tkind: 'team'\n\t\t\t})\n\t\t\tif (out.length) this.say('retreating')\n\t\t}\n\t}\n\n\t/**\n\t * The ping of an ally's it does now: the latest standing `attack` or `defend` of another's, in reach of home, and\n\t * not before a `rally` of theirs since (a retreat asked after a push is what they want now)\n\t */\n\tprivate pinged(): TeamRequest | undefined {\n\t\tconst { ai } = this\n\t\treturn ai.cache('team.pinged', () => {\n\t\t\tconst home = ai.view.home()\n\t\t\tif (!home) return undefined\n\t\t\tconst rallies = this.requests('rally').filter((each) => each.by === 'ping')\n\t\t\tconst candidates = [...this.requests('attack'), ...this.requests('defend')].filter(\n\t\t\t\t(each) =>\n\t\t\t\t\teach.by === 'ping' &&\n\t\t\t\t\teach.from !== ai.playerId &&\n\t\t\t\t\tdistSq(each.at, home) <= HELP_REACH * HELP_REACH &&\n\t\t\t\t\t!rallies.some((rally) => rally.from === each.from && rally.id > each.id)\n\t\t\t)\n\t\t\tcandidates.sort((a, b) => b.id - a.id)\n\t\t\treturn candidates[0]\n\t\t})\n\t}\n\n\t/**\n\t * The goal that does what an ally's ping asks: a squad to fight there (`push`), or to hold the place (`hold`). One at\n\t * a time: a later ping takes the units of the one before\n\t */\n\tprivate makePingGoal(): GoalDef {\n\t\tconst sent = (available: UnitSet, request: TeamRequest) => this.helpers(available, { at: request.at, strength: this.seenAt(request.at) })\n\t\treturn defineGoal({\n\t\t\tid: PINGED,\n\t\t\tweight: 0.75,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('an ally pings to push or hold', () => (this.pinged() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'enough to send',\n\t\t\t\t\t(ai) => {\n\t\t\t\t\t\tconst request = this.pinged()\n\t\t\t\t\t\treturn request ? sent(ai.goals.pool(), request).length : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t)\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst request = this.pinged()\n\t\t\t\t\treturn request ? sent(available, request) : []\n\t\t\t\t}\n\t\t\t},\n\t\t\tcommitment: 10,\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tconst request = this.pinged()\n\t\t\t\tif (!request || (request.kind !== 'attack' && request.kind !== 'defend')) return\n\t\t\t\tconst name = PING_SQUADS[request.kind]\n\t\t\t\t// sent there already: it goes on while the ping stands\n\t\t\t\tconst there = ai.squads.named(name)\n\t\t\t\tconst at = there?.current?.data.at as Vec2 | undefined\n\t\t\t\tif (there && at && distSq(at, request.at) <= SAME_PLACE * SAME_PLACE && there.done === undefined) return\n\t\t\t\tconst squad = claimed.squad(name, claimed.units)\n\t\t\t\tif (request.kind === 'attack') squad.attack(request.at)\n\t\t\t\telse squad.defend(request.at, SEEN_NEAR)\n\t\t\t\tif (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId)\n\t\t\t\tai.decide(\n\t\t\t\t\t`${request.kind === 'attack' ? 'pushes' : 'holds'} at ${where(request.at)} with ${claimed.units.length}, at player ${request.from}'s ping`,\n\t\t\t\t\t{ kind: 'team', goal: PINGED }\n\t\t\t\t)\n\t\t\t\tif (request.kind === 'attack') this.say('attacking')\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Its fighters at home nothing holds: what it meets a raid with before it asks */\n\tprivate homeStrength(): number {\n\t\tconst { ai } = this\n\t\treturn ai.goals.pool().fighters().strength()\n\t}\n\n\t/** What was heard since the last think: the people's pings at a place, damage done to an ally where it was seen */\n\tprivate hear(since: number): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst ally = (player: PlayerId) => player !== ai.playerId && view.player(player)?.relation === 'ally'\n\t\tfor (const ping of ai.knowledge.events.pings()) {\n\t\t\tif (ping.tick <= since || !ally(ping.player)) continue\n\t\t\t// what the kind asks, as the game's rules say (`GameRules.talk.pings.meanings`)\n\t\t\tconst meaning = ai.session.registry.rules.talk.pings.meanings?.[ping.kind]\n\t\t\tif (meaning && meaning !== 'ignore') this.request(meaning, ping.at, meaning === 'help' ? this.seenAt(ping.at) : 0, 'ping', ping.player)\n\t\t\telse ai.decide(`hears player ${ping.player}'s ${ping.kind} at ${where(ping.at)}`, { kind: 'team' })\n\t\t}\n\t\tfor (const hit of ai.knowledge.events.damage()) {\n\t\t\tif (hit.tick <= since || !ally(hit.owner)) continue\n\t\t\tconst strength = this.seenAt(hit.at)\n\t\t\tif (strength > 0) this.request('help', hit.at, strength, 'damage', hit.owner)\n\t\t}\n\t}\n\n\t/** The strength of the enemies in sight near a place */\n\tprivate seenAt(at: Vec2): number {\n\t\treturn this.ai.view.enemies.units().alive().near(at, SEEN_NEAR).strength()\n\t}\n\n\t/** The request it would answer now: the strongest standing of another, in reach of home, it can send enough to */\n\tprivate calling(): TeamRequest | undefined {\n\t\tconst { ai } = this\n\t\treturn ai.cache('team.calling', () => {\n\t\t\tconst home = ai.view.home()\n\t\t\tif (!home) return undefined\n\t\t\tconst candidates = this.requests('help').filter((each) => each.from !== ai.playerId && distSq(each.at, home) <= HELP_REACH * HELP_REACH)\n\t\t\tcandidates.sort((a, b) => b.strength - a.strength || a.id - b.id)\n\t\t\treturn candidates[0]\n\t\t})\n\t}\n\n\t/** How much stronger than a call what is sent to it is: from the odds asked, by the square law (one in two: as strong) */\n\tget margin(): number {\n\t\tconst odds = Math.min(0.95, Math.max(0.05, this.options.helpOdds ?? 0.5))\n\t\treturn Math.sqrt(odds / (1 - odds))\n\t}\n\n\t/** Who it sends to a call: its idle fighters nothing holds, the nearest first, as many as make the odds asked */\n\tprivate helpers(available: UnitSet, request: Pick<TeamRequest, 'strength' | 'at'>): UnitSet {\n\t\tconst { ai } = this\n\t\tconst need = request.strength * this.margin\n\t\tconst idle = available\n\t\t\t.fighters()\n\t\t\t.idle()\n\t\t\t.items.slice()\n\t\t\t.sort((a, b) => distSq(a, request.at) - distSq(b, request.at) || a.id - b.id)\n\t\tconst chosen: EntityState[] = []\n\t\tlet got = 0\n\t\tfor (const unit of idle) {\n\t\t\tif (request.strength > 0 ? got >= need : chosen.length >= HELP_UNSEEN) break\n\t\t\tchosen.push(unit)\n\t\t\tgot += ai.view.strength.of(unit)\n\t\t}\n\t\t// not enough to make the odds: none sent, rather than a few to their deaths\n\t\tif (request.strength > 0 && got < need) return available.where(() => false)\n\t\treturn available.where((unit) => chosen.includes(unit))\n\t}\n\n\t/** The help goal: a call of an ally's standing, and enough to send to it */\n\tprivate makeGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: HELP,\n\t\t\tweight: 0.7,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('an ally calls for help', () => (this.calling() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'enough to send',\n\t\t\t\t\t(ai) => {\n\t\t\t\t\t\tconst request = this.calling()\n\t\t\t\t\t\treturn request ? this.helpers(ai.goals.pool(), request).length : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t)\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst request = this.calling()\n\t\t\t\t\treturn request ? this.helpers(available, request) : []\n\t\t\t\t}\n\t\t\t},\n\t\t\tcommitment: 10,\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tconst request = this.calling()\n\t\t\t\tif (!request) return\n\t\t\t\tconst squad = ai.squads.named('help')\n\t\t\t\tconst at = squad?.current?.data.at as Vec2 | undefined\n\t\t\t\tif (squad && at && distSq(at, request.at) <= SAME_PLACE * SAME_PLACE && squad.done === undefined) {\n\t\t\t\t\t// there already: made up to what the call is now (more of them seen there), from what nothing holds\n\t\t\t\t\tconst more = this.helpers(ai.goals.pool(), {\n\t\t\t\t\t\t...request,\n\t\t\t\t\t\tstrength: Math.max(0, request.strength * this.margin - squad.strength()) / this.margin\n\t\t\t\t\t})\n\t\t\t\t\tif (request.strength > 0 && more.length) squad.add(more, 'more seen there')\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tclaimed.squad('help', claimed.units).defend(request.at, SEEN_NEAR)\n\t\t\t\tif (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId)\n\t\t\t\tai.decide(`answers player ${request.from}'s call for help at ${where(request.at)} with ${claimed.units.length}`, { kind: 'team', goal: HELP })\n\t\t\t\tthis.say('helping')\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Team play as the report shows it */\n\treport(): TeamReport {\n\t\tconst { ai } = this\n\t\tconst tickRate = ai.session.tickRate\n\t\tconst plan = this.plan\n\t\treturn {\n\t\t\tteam: this.team,\n\t\t\tcomputers: this.computers(),\n\t\t\trequests: this.requests().map((each) => ({\n\t\t\t\tid: each.id,\n\t\t\t\tkind: each.kind,\n\t\t\t\tfrom: each.from,\n\t\t\t\tat: pair(each.at),\n\t\t\t\tstrength: Math.round(each.strength),\n\t\t\t\tby: each.by,\n\t\t\t\tanswered: [...each.answered],\n\t\t\t\tleft: Math.max(0, Math.round((each.until - ai.tick) / tickRate))\n\t\t\t})),\n\t\t\t...(plan && {\n\t\t\t\tplan: {\n\t\t\t\t\ttarget: pair(plan.target),\n\t\t\t\t\tin: Math.round((plan.at - ai.tick) / tickRate),\n\t\t\t\t\tby: plan.by,\n\t\t\t\t\tjoined: [...plan.joined],\n\t\t\t\t\tdeclined: [...plan.declined]\n\t\t\t\t}\n\t\t\t}),\n\t\t\tenemyBases: this.enemyBases().length\n\t\t}\n\t}\n\n\t/** What it remembers, for a save: a copy (the board is the world's, saved with it) */\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.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\tif (this.enabled) report.team = this.report()\n\t}\n\n\tsave(): TeamPlayMemory {\n\t\treturn { v: 1, heard: this.memory.heard, said: { ...this.memory.said } }\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 TeamPlayMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = { v: 1, heard: given.heard ?? -1, said: { ...(given.said ?? {}) } }\n\t\treturn true\n\t}\n}\n\n/**\n * The team module: the team's board brought up to date each think (`ai.team.think`: itself and what it knows written,\n * pings and an ally's damage heard as calls for help, its own raids asked help for, the plan of an attack together\n * answered), and the `help` goal on the picker. With how it plays where the brain's definition and the seat's options\n * say nothing (`TeamOptions`)\n *\n * @beta\n */\nexport const team = (options: TeamOptions = {}): AiModuleDef =>\n\tdefineModule('team', (ai: Brain): AiModule => {\n\t\tai.area(Team).configure(options)\n\t\treturn {\n\t\t\tid: 'team',\n\t\t\tphase: 'sense',\n\t\t\tafter: ['defence'],\n\t\t\tthink: () => ai.area(Team).think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tteam?: TeamPlayMemory\n\t}\n}\n","import { defineComponent } from '#engine/components'\nimport { listKitComponents } from '#engine/coreComponents'\nimport type { PlayerId } from '#engine/entity'\nimport type { System } from '#engine/registry'\nimport { LocalSession } from '#engine/session/local'\nimport { invalidateStats } from '#engine/stats'\nimport type { HookDef } from '#engine/hooks'\nimport type { World } from '#engine/world'\nimport { MISSION_RULES, type RulesWatcher } from '#engine/missionRules'\nimport { evaluate } from './rules'\nimport type { AiOptions } from './options'\nimport { Brain, type BrainContext, type BrainDef, createBrain } from './brain'\nimport type { ThinkBudgetOptions } from './budget'\nimport { emptyTeam, type TeamBoard } from './team'\nimport { type AiProfile, resolveProfile } from './profiles'\nimport { type AiSettings, resolveSettings } from './settings'\n\n/*\n * The seat of a computer player (AI plan, A1): the one place the kit touches the world. A computer player is a player:\n * it gets a session of its own at the world (`LocalSession`: what that player sees, under their fog, and nothing else)\n * and plays by sending commands through it, as a mouse does. `createComputerSystem` makes the system that asks it to\n * think once in a while, each seat at another tick, so that twelve computers do not all think at once; it also times\n * the thinks, for the report. `world.computers` is who is seated: it keeps each seat in the world (`core.computers`,\n * kept in a save, so that a loaded game has its computers back by itself), and is how the game reaches a seated brain\n * (`tell`, `pause`, `get`). A seat with no brain named gets the first brain the game lists (`GameModule.brains`). It names no brain of its own: the engine's (`meleeBrain`) are\n * `@v12-engine/engine/ai`'s, and a game that does not list one carries none of them. Nothing else in `ai/` imports the\n * world (a test asserts it): a brain that had the world could see through the fog\n */\n\n/**\n * A computer player: whatever plays a seat of a world from what it sees, through commands as a player does. The\n * engine's own is a `Brain` of modules (`defineBrain`), the melee player among them; a game gives its own in code\n * (`defineComputer`, listed in `GameModule.brains`). `think` is asked about once a second (`createComputerSystem`); `save` and `restore` keep what\n * it remembers through a save\n *\n * @beta\n */\nexport interface ComputerPlayer {\n\tthink(): void\n\tsave?(): unknown\n\trestore?(memory: unknown): void\n\t/** What it is thinking, as plain data: what the debug tools show of the player it plays (its goal, its scores) */\n\tinspect?(): unknown\n\t/** Whether a think is under way across ticks (a brain's budget): it is asked to think on at the next tick */\n\treadonly busy?: boolean\n\t/** Whether it sits still (`world.computers.pause`). A player without the field cannot be paused */\n\tpaused?: boolean\n\t/** Takes in a word from the game (`world.computers.tell`), with the tick it is told at */\n\ttell?(word: string, data: unknown, tick: number): void\n\t/** Lets go of what it holds outside its seat, once unseated */\n\tdispose?(): void\n}\n\n/**\n * Milliseconds a computer player's thinks took: for the report and the stats panel, never for a decision\n *\n * @beta\n */\nexport interface ComputerTiming {\n\t/** The last think, all its ticks where it was sliced */\n\tlast: number\n\t/** Averaged over its thinks */\n\taverage: number\n\t/** The longest think there was */\n\tlongest: number\n\t/** Ticks the last think took: 1, unless the brain's budget sliced it over ticks */\n\tticks?: number\n\t/** By module, averaged, while the world profiles (`Scheduler.profiling`): a brain's */\n\tmodules?: Record<string, number>\n\t/** By module, the most one pass of it took, always: a brain's. What `ThinkBudgetOptions.warnAfterMs` is measured against */\n\tlongestByModule?: Record<string, number>\n\t/** Of a think, what taking the picture of the game took (the seat's `snapshot()`), averaged, while the world profiles: a brain's */\n\tsnapshot?: number\n\t/** Of a think, what reading the picture into the view took (`AiView`), averaged, while the world profiles: a brain's */\n\tview?: number\n\t/** Of a think, what bringing the brain's knowledge up to date took, averaged, while the world profiles: a brain's */\n\tknowledge?: number\n}\n\n/**\n * The system a computer player plays from: it is asked to think about once a second (`every`, in seconds), each seat\n * at another tick of it, to spread the work; it is named for its seat (`ai-<player>`), which a save keeps what it\n * remembers by\n *\n * @beta\n */\nexport interface ComputerSystem<C extends ComputerPlayer = ComputerPlayer> extends System {\n\treadonly computer: C\n\t/** The player it plays */\n\treadonly player: PlayerId\n\t/** The seat it plays through */\n\treadonly session: LocalSession\n\t/** Milliseconds its thinks took: the last, an average, the longest, and by module while the world profiles */\n\ttiming(): ComputerTiming\n\t/** Lets go of its seat: the session's listeners, what the computer player holds. The world stays */\n\tdispose(): void\n}\n\n/**\n * What a save keeps of a computer's seat (`ComputerSystem.save`): the number of the last command it sent, and what the\n * computer player remembers (`ComputerPlayer.save`), when it does\n *\n * @internal\n */\nexport interface ComputerSave {\n\tsent: number\n\tmemory?: unknown\n}\n\n/**\n * How a seat asks its computer player to think (`createComputerSystem`)\n *\n * @beta\n */\nexport interface ComputerSeatOptions {\n\t/** Seconds between thinks: 1 when left out */\n\tevery?: number\n\t/**\n\t * How much of a think one tick may do (`ThinkBudgetOptions`: modules a tick, units looked at a tick as the modules say,\n\t * the milliseconds a module is warned over), or the modules a tick as a number: a think with more goes on at the next\n\t * tick, over the same picture. Everything in one tick when left out\n\t */\n\tbudget?: number | ThinkBudgetOptions\n\t/** The tick in each round the seat thinks at: seven times the player's id when left out, so that seats think at different moments */\n\toffset?: number\n\t/**\n\t * What the seat's picture of the game carries: `lean`, what a computer reads (the entities, the players, the items, the\n\t * deaths, damage, pings, chat and the game's own events) and none of what a screen needs (projectiles, missiles,\n\t * corpses, reveals, the effects and the rest of the events), which is cheaper to take and to hear; `full`, everything a\n\t * player's seat gets. `full` when left out here; a brain's seat is `lean` unless its definition says otherwise\n\t * (`BrainDef.snapshot`)\n\t */\n\tsnapshot?: 'lean' | 'full'\n\t/**\n\t * Whether the seat sees everything, as an observer does (`LocalSession`'s `observer`): the one way a computer sees\n\t * through the fog, for a profile with `vision: 'all'` (insane). Its own seat's sight when left out\n\t */\n\tobserver?: boolean\n\t/**\n\t * How well the seat plays (`AiProfile`): its `handicap` (what its workers bring in, the health of what it has, the\n\t * damage it deals, how long what it makes takes, made more or less through hooks that go with the seat) and `vision: 'all'` (it sees everything, as `observer`). A brain's seat and a game's\n\t * own computer (`defineComputer`) are both given the profile of their difficulty\n\t */\n\tprofile?: AiProfile\n\t/** Called as the seat is taken away (`dispose`): to undo what seating did outside the computer (a hook added) */\n\tonDispose?: () => void\n}\n\n/**\n * The hooks a profile's handicap (`AiProfile.handicap`) is given to the world by, for one player: what its workers bring\n * in (`beforeDeposit`), the health of what it has (`stats`), the damage it deals (`beforeDamage`), how long what it\n * makes takes (`beforeProduce`). None for a handicap of 1, or none given. Ids `core.ai.handicap.<player>` and\n * `core.ai.handicap.<what>.<player>`\n */\nfunction handicapHooks(player: PlayerId, handicap: AiProfile['handicap']): HookDef[] {\n\tconst hooks: HookDef[] = []\n\tconst { income, health, damage, buildTime } = handicap ?? {}\n\tif (income !== undefined && income !== 1)\n\t\thooks.push({\n\t\t\tid: `core.ai.handicap.${player}`,\n\t\t\thook: 'beforeDeposit',\n\t\t\trun: (_world, event) => {\n\t\t\t\tif (event.player === player) event.amount = Math.round(event.amount * income)\n\t\t\t}\n\t\t})\n\tif (health !== undefined && health !== 1)\n\t\thooks.push({\n\t\t\tid: `core.ai.handicap.health.${player}`,\n\t\t\thook: 'stats',\n\t\t\trun: (_world, event) => {\n\t\t\t\tif (event.entity.owner === player) event.add({ percent: { health: health - 1 } })\n\t\t\t}\n\t\t})\n\tif (damage !== undefined && damage !== 1)\n\t\thooks.push({\n\t\t\tid: `core.ai.handicap.damage.${player}`,\n\t\t\thook: 'beforeDamage',\n\t\t\trun: (_world, event) => {\n\t\t\t\tif (event.source?.owner === player) event.amount *= damage\n\t\t\t}\n\t\t})\n\tif (buildTime !== undefined && buildTime !== 1)\n\t\thooks.push({\n\t\t\tid: `core.ai.handicap.buildTime.${player}`,\n\t\t\thook: 'beforeProduce',\n\t\t\trun: (_world, event) => {\n\t\t\t\tif (event.player === player) event.time *= buildTime\n\t\t\t}\n\t\t})\n\treturn hooks\n}\n\n/** How much of each new think goes into the averaged time of a seat. Small: the panel shows a steady number */\nconst SMOOTHING = 0.1\n\n/** What a computer player's own numbers start from: the world's seed and the player, mixed so that two seats of one game draw differently */\nconst seedOf = (seed: number, player: PlayerId) => (Math.imul((seed ^ 0x9e3779b9) >>> 0, 1664525) + player * 1013904223) >>> 0\n\n/**\n * Seats a computer player at a world: made of a session of its own (it sees what that player sees, and plays through\n * commands, so it cannot cheat), asked to think about once a second. `make` is handed the session and what a brain\n * takes besides (`BrainContext`: a seed of its own, the budget, whether the world profiles). Add the result to the\n * world (`world.addSystem`), or seat through `world.computers.seat`, which remembers it for a save\n *\n * @beta\n */\nexport function createComputerSystem<C extends ComputerPlayer>(\n\tworld: World,\n\tplayerId: PlayerId,\n\tmake: (session: LocalSession, context: BrainContext) => C,\n\toptions: ComputerSeatOptions = {}\n): ComputerSystem<C> {\n\tconst session = new LocalSession(world, playerId, {\n\t\tobserver: !!options.observer || options.profile?.vision === 'all',\n\t\tforComputer: options.snapshot === 'lean'\n\t})\n\t// its handicaps, asked of the game's rules through their hooks: the profile's, not the computer's doing\n\tconst handicaps = handicapHooks(playerId, options.profile?.handicap)\n\tfor (const hook of handicaps) world.hooks.add(hook)\n\tif (handicaps.some((hook) => hook.hook === 'stats')) invalidateStats(world)\n\t// the board of the player's team, shared by its computers: read anew each time, for a load replaces the world's states\n\tconst team = () => {\n\t\tconst boards = world.state(aiTeams)\n\t\tconst id = String(world.players.get(playerId)?.team ?? playerId)\n\t\treturn (boards[id] ??= emptyTeam())\n\t}\n\tconst computer = make(session, {\n\t\tseed: seedOf(world.seed, playerId),\n\t\tbudget: options.budget,\n\t\tprofiling: () => world.scheduler.profiling,\n\t\tteam,\n\t\tchecks: world.checks.ai\n\t})\n\tconst interval = Math.max(1, Math.round((options.every ?? 1) * world.tickRate))\n\t// players think at different moments, to spread the work\n\tconst offset = options.offset ?? playerId * 7\n\tconst timing: ComputerTiming = { last: 0, average: 0, longest: 0 }\n\t/** Milliseconds of the think under way, across its ticks */\n\tlet spent = 0\n\treturn {\n\t\tname: `ai-${playerId}`,\n\t\tcomputer,\n\t\tplayer: playerId,\n\t\tsession,\n\t\tupdate() {\n\t\t\tif (computer.paused) return\n\t\t\tif ((world.tick + offset) % interval !== 0 && !computer.busy) return\n\t\t\tconst start = performance.now()\n\t\t\tcomputer.think()\n\t\t\tspent += performance.now() - start\n\t\t\tif (computer.busy) return\n\t\t\ttiming.last = spent\n\t\t\ttiming.average = timing.average === 0 ? spent : timing.average + (spent - timing.average) * SMOOTHING\n\t\t\tif (spent > timing.longest) timing.longest = spent\n\t\t\tspent = 0\n\t\t},\n\t\ttiming() {\n\t\t\tconst brain = computer instanceof Brain ? computer : undefined\n\t\t\tif (!brain) return { ...timing }\n\t\t\tconst modules = Object.keys(brain.moduleTiming).length ? { ...brain.moduleTiming } : undefined\n\t\t\tconst longestByModule = Object.keys(brain.moduleLongest).length ? { ...brain.moduleLongest } : undefined\n\t\t\tconst { snapshotTiming: snapshot, viewTiming: view, knowledgeTiming: knowledge } = brain\n\t\t\treturn {\n\t\t\t\t...timing,\n\t\t\t\t...(brain.thinkTicks > 0 && { ticks: brain.thinkTicks }),\n\t\t\t\t...(modules && { modules }),\n\t\t\t\t...(longestByModule && { longestByModule }),\n\t\t\t\t...(snapshot !== undefined && { snapshot }),\n\t\t\t\t...(view !== undefined && { view }),\n\t\t\t\t...(knowledge !== undefined && { knowledge })\n\t\t\t}\n\t\t},\n\t\tdispose() {\n\t\t\tcomputer.dispose?.()\n\t\t\tsession.dispose()\n\t\t\tfor (const hook of handicaps) world.hooks.remove(hook.hook, hook.id)\n\t\t\tif (handicaps.some((hook) => hook.hook === 'stats')) invalidateStats(world)\n\t\t\toptions.onDispose?.()\n\t\t},\n\t\t// what it remembers goes into a save, with the number of the last command its seat sent; a game loaded from it\n\t\t// adds the computer player again, and it carries on\n\t\tsave: (): ComputerSave => {\n\t\t\tconst memory = computer.save?.()\n\t\t\treturn { sent: session.lastSeq, ...(memory !== undefined && { memory }) }\n\t\t},\n\t\trestore: (_world: World, data: unknown) => {\n\t\t\tconst { sent, memory } = data as ComputerSave\n\t\t\tsession.lastSeq = sent\n\t\t\tif (memory !== undefined) computer.restore?.(memory)\n\t\t}\n\t}\n}\n\n/**\n * The boards of the teams' computers (`TeamBoard`, AI plan C5), by team: in the world, so that a save keeps the\n * requests and the plan of an attack together, and never replicated, so that no player gets it in a snapshot\n *\n * @beta\n */\nexport const aiTeams = defineComponent<Record<string, TeamBoard>>('core.ai.teams', { default: () => ({}) })\n// the engine's own, found in every world's registry where the kit is loaded\nlistKitComponents(aiTeams)\n\n/**\n * Seats a brain at a world as one of its players, asked to think as its definition or the options say (`every`), with\n * the budget the options give. Add the result to the world, or go through `world.computers.seat`\n *\n * @beta\n */\nexport function createBrainSystem(world: World, playerId: PlayerId, brain: BrainDef, options: AiOptions = {}): ComputerSystem<Brain> {\n\t// its profile (D1): how often it thinks where the seat and the brain say nothing, whether it sees everything, its handicaps\n\tconst { profile } = resolveProfile(options, world.registry, undefined, world.players.get(playerId)?.race)\n\tconst every = options.every ?? (typeof brain.every === 'function' ? brain.every(options) : brain.every) ?? profile.every ?? 1\n\treturn createComputerSystem(world, playerId, (session, context) => createBrain(brain, session, options, context), {\n\t\tevery,\n\t\t// the budget (F2): the profile's, with the seat's own over it\n\t\tbudget: profile.budget,\n\t\tprofile,\n\t\t// the picture cut to what a brain reads, unless the brain says it reads everything\n\t\tsnapshot: brain.snapshot ?? 'lean'\n\t})\n}\n\n/**\n * A computer player of the game's own that is not made of modules (a `ComputerPlayer`: anything that thinks), as a brain\n * the game lists (`GameModule.brains`) and seats as it does any (`world.computers.seat(player, { brain })`): found again\n * by its id when a save is loaded. `make` is handed the seat's session, its context and what it was seated with, the\n * map's under the seat's; it thinks as often as those say (`every`, 1 second when left out)\n *\n * @beta\n */\nexport function defineComputer<C extends ComputerPlayer>(\n\tid: string,\n\tmake: (session: LocalSession, context: BrainContext, options: AiOptions) => C\n): BrainDef {\n\treturn {\n\t\tid,\n\t\tmodules: [],\n\t\tseat: (world, player, given) => {\n\t\t\tconst options = withMapAi(world, player, given)\n\t\t\treturn createComputerSystem(world, player, (session, context) => make(session, context, options), {\n\t\t\t\tevery: options.every,\n\t\t\t\tbudget: options.budget,\n\t\t\t\t// the difficulty's handicap and vision, as a brain's seat has them\n\t\t\t\tprofile: resolveProfile(options, world.registry, undefined, world.players.get(player)?.race).profile\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * What a map says of how its computer player plays (`MapPlayer.data.ai`, decision 6 of the AI plan), for a player the map\n * gives the computer (`controller: 'computer'`): a difficulty and a personality by name, and settings (`AiSettings`:\n * its flags, its build order as `plans.order`, its waves as `waves.waves`, any area's numbers). Plain data, as the map's\n * file holds it\n *\n * @beta\n */\nexport interface MapAi {\n\t/** The brain the player is seated with, by id (`GameModule.brains`): over its race's (`GameAi.races`), under the seat's */\n\tbrain?: string\n\tdifficulty?: string\n\tpersonality?: string\n\tsettings?: AiSettings\n\t/**\n\t * Settings by the race the player plays (`GameModule.races`), over `settings`: for a player whose race the lobby\n\t * chooses or draws (`random`), a build order or waves for each\n\t */\n\traces?: Record<string, AiSettings>\n}\n\n/**\n * The seat's options with what the map says of the player under them (`MapPlayer.data.ai`), where the map gives the player\n * to the computer: the lobby's and the scene's say goes over the map's (decision 10), its settings layered over the map's\n * (the map's for the race the player plays over the rest of the map's)\n *\n * @internal\n */\nexport function withMapAi(world: World, playerId: PlayerId, options: AiOptions): AiOptions {\n\tconst player = world.map.player(playerId)\n\tconst map = player?.controller === 'computer' ? (player.data?.ai as MapAi | undefined) : undefined\n\tif (!map || typeof map !== 'object') return options\n\tconst race = world.players.get(playerId)?.race\n\tconst raced = race !== undefined ? map.races?.[race] : undefined\n\treturn {\n\t\t...(map.difficulty !== undefined && { difficulty: map.difficulty }),\n\t\t...(map.personality !== undefined && { personality: map.personality }),\n\t\t...options,\n\t\t...((map.settings || raced || options.settings) && { settings: resolveSettings([map.settings, raced, options.settings]) })\n\t}\n}\n\n/** A seed of a watcher's own numbers: the world's, mixed with the player's */\nconst watcherSeedOf = (seed: number, player: PlayerId) => (Math.imul((seed ^ 0x7f4a7c15) >>> 0, 1664525) + player * 1013904223) >>> 0\n\n/** The watcher's brain: nothing of its own, the kit's reading of the picture alone */\nconst WATCHER: BrainDef = { id: MISSION_RULES, modules: [] }\n\n/**\n * Seats a watcher for the mission rules (`missionRules`, campaign plan MS1): a brain with no modules of its own, at a\n * player, on an observer's session (it sees the whole map; `mine` and `enemy` are that player's), which reads the\n * picture as a brain does when asked to (`think`) and answers a rule's condition (`ask`: the kit's `evaluate`). Its\n * numbers are seeded from the world's and the player's, and its memory is the rules' to save\n *\n * @internal\n */\nexport function ruleWatcher(world: World, player: PlayerId): RulesWatcher {\n\tconst session = new LocalSession(world, player, { observer: true, forComputer: true })\n\tconst brain = createBrain(WATCHER, session, {}, { seed: watcherSeedOf(world.seed, player) })\n\treturn {\n\t\tthink: () => brain.think(),\n\t\task: (condition) => evaluate(condition, brain),\n\t\ttell: (word, data, tick) => brain.tell(word, data, tick),\n\t\ttakeTold: (word) => void brain.takeTold(word),\n\t\tsave: () => brain.save(),\n\t\trestore: (memory) => brain.restore(memory as never)\n\t}\n}\n","/**\n * A brain defined (`defineBrain`): checked, given its `with` for variants, and its seat (`BrainDef.seat`), which is the\n * kit's (`createBrainSystem`). Apart from the brain itself (`brain.ts`), which the seat is made of\n */\nimport type { BrainDef, BrainExtension } from './brain'\nimport { createBrainSystem, withMapAi } from './computer'\nimport { resolveSettings } from './settings'\n\n/**\n * A brain as `defineBrain` gives it: with its `with`, for variants of it\n *\n * @beta\n */\nexport interface DefinedBrain extends BrainDef {\n\twith(more: BrainExtension): DefinedBrain\n}\n\n/**\n * Defines a brain: what a computer player is made of, to seat at a world (`world.computers.seat(player, { ...options, brain })`,\n * `world.computers.seat`) and to list in `GameModule.brains`, for a save to find it by its id. Modules that keep state\n * are given as functions of the brain, as systems are of the world\n *\n * @beta\n */\nexport function defineBrain(def: BrainDef): DefinedBrain {\n\tif (!def.id) throw new Error('A brain needs an id')\n\tif (!Array.isArray(def.modules)) throw new Error(`The brain \"${def.id}\" needs its modules, as a list`)\n\t// a brain of its own: what it was given is left as it is (AI4: a frozen literal would have thrown)\n\tconst brain = { ...def } as DefinedBrain\n\tbrain.with = (more) =>\n\t\tdefineBrain({\n\t\t\t...def,\n\t\t\t...more,\n\t\t\t// its own seat, of the variant: not the one it was made from\n\t\t\tseat: more.seat,\n\t\t\tmodules: [...def.modules, ...(more.modules ?? [])],\n\t\t\tgoals: [...(def.goals ?? []), ...(more.goals ?? [])],\n\t\t\t...((def.settings || more.settings) && { settings: resolveSettings([def.settings, more.settings]) }),\n\t\t\t...((def.rules || more.rules) && { rules: [...(def.rules ?? []), ...(more.rules ?? [])] }),\n\t\t\t...((def.without || more.without) && { without: [...(def.without ?? []), ...(more.without ?? [])] })\n\t\t})\n\t// seated as the kit seats a brain, so that the core does not have to know how (`world.computers.seat`)\n\tbrain.seat ??= (world, player, options) => createBrainSystem(world, player, brain, withMapAi(world, player, options))\n\treturn brain\n}\n","import { baseStats, constructionOf, type ResourceKind, type UnitTypeDef } from '#engine/defs'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { queueOf } 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 { gathers } from '#engine/shared'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { type AiCondition, evaluate } from './rules'\nimport type { Base, UnitSet } from './view'\nimport { pair, point, where } from './geometry'\nimport { ENGAGED, HALL_REACH } from './reach'\n\n/*\n * The economy (AI plan, C4): the workers, base by base. The old melee player sent an idle worker to the nearest mine\n * with a hall by it and trained workers while it had fewer than so many a hall; nothing kept count of where they\n * worked, so a new hall by a second mine was staffed only by what it trained itself, a mine past what it could take\n * kept getting more, and a raid on the mine was met by workers mining on. This is what a player watches on their\n * economy, written down:\n *\n * - **Workers per base, per resource** (`workersPer`): so many on the money at each base, so many on the other\n * resource (harvest priorities, a town at a time). An idle worker goes where the most are missing, the\n * nearest base first among equals.\n * - **Saturation** (`saturate`): a mine takes only so many workers before more of them only queue at it. A worker in\n * a mine it enters one at a time (`resource.entered`, `slots`) is inside for its gather time, then walks to the hall\n * and back: while it walks, others go in, so a mine serves as many as fit in one round trip, `slots × (1 + walk /\n * gather)`, rounded up (five, for a mine twelve steps from a hall). A deposit worked from beside it (a tree) serves\n * as many as it has slots, by home or, where none is near home, the woods nearest it however far. What stands on a\n * mine to gather it (`builtOn`, a cursed mine) serves its `gatherers`.\n * Workers past what their base's deposits serve are not trained.\n * - **Rebalancing**: a base whose deposits ran out, or that has more on them than they serve, gives what it has spare\n * to a base that is short (a new expansion): workers walk over rather than wait for the new hall to train its own.\n * - **Training** workers at every hall that stands, up to what the bases want together, and a builder or so more\n * (`builders`): a worker sent to build is off its mine meanwhile.\n * - **Expansions** (`expansions`, `expandWhen`): another hall by a mine nobody has a hall at, near enough home, once\n * the condition holds (time and an army building, when left out): a want of the build plan, which saves up for it,\n * sends a worker to look at the ground first where nobody has (the settler), and builds it anew when lost.\n * - **Workers flee a raid** (`workersFlee`): workers a raid is on, at a base its fighters do not hold, walk to the\n * nearest base no enemy is at, and back to work at their own once it has stood clear a while.\n * - **What goes up by builders** gets one where nobody works on it, and **what the money is gathered at** where it\n * has to stand on the mine first (`builtOn`) is built at each hall before anything else.\n *\n * Mending and building anew what was lost are the build plan's (B3: `repair`, `rebuild`). What the economy remembers\n * (who fled from where) is plain data in the brain's memory (`BrainMemory.economy`).\n */\n\n/** How far from home a mine is taken for another hall: further is across the map */\nconst EXPAND_REACH = 64\n/** A point so far from a place on the way to another */\nfunction towards(from: Vec2, to: Vec2, distance: number): Vec2 {\n\tconst length = Math.sqrt(distSq(from, to))\n\tif (length <= distance) return { x: to.x, z: to.z }\n\treturn { x: from.x + ((to.x - from.x) / length) * distance, z: from.z + ((to.z - from.z) / length) * distance }\n}\n\n/** How far from a mine's middle its side is, a mine being 3 or 4 wide: where a route to it goes */\nconst MINE_SIDE = 3.5\n/** How far from a mine's middle a route may end and the mine still count as walked to: by its side, a mine being 3 or 4 wide */\nconst MINE_WALK_REACH = 6\n/** How near a base what is at it is */\nconst AT_BASE = 20\n/** How far round the nearest tree the woods go that home gathers from, where none is near home */\nconst WOODS = 12\n/** The odds of the base's fighters near a worker against the foes on it, under which the worker runs */\nconst FLEE_UNDER = 0.5\n/** Seconds a base a worker fled from stands clear before it goes back */\nconst CLEAR_FOR = 5\n/** How near its builder a building half built is being worked on */\nconst AT_SITE = 10\n/** How many workers rebalancing moves in a think: a few at a time, so that a base never empties at once */\nconst MOVE_AT_ONCE = 3\n/** Seconds the other resource runs short, with the money piling up, before one more worker goes to it (AI2) */\nconst BLOCKED = 15\n/** What counts as the other resource running short, and as the money piling up: what little a building or a unit costs of it, and enough for most */\nconst SHORT_UNDER = 100\nconst PILED = 300\n/** How many more workers on the other resource at most, for what waits on it */\nconst MORE_AT_MOST = 3\n/** What the economy holds the workers that fled by (`ai.goals.take`): no goal sends them anywhere until they are back */\nconst FLED = 'economy:fled'\n\n/**\n * How many workers a base wants on each resource (`EconomyOptions.workersPer`): as numbers by resource id, or a\n * function of the base (`index` 0 is home)\n *\n * @beta\n */\nexport type WorkersPer = Partial<Record<ResourceKind, number>> | ((ai: Brain, base: Base, index: number) => Partial<Record<ResourceKind, number>>)\n\n/**\n * How a brain runs its economy (`BrainDef.economy`, the seat's `AiOptions.economy` over it, the `economy()` module's\n * own under both). Every field has a data form a save keeps; the function forms are the brain's to give again\n *\n * @beta\n */\nexport interface EconomyOptions {\n\t/** Workers on the game's money at each base, where `workersPer` says nothing of it: 8 when left out */\n\tworkers?: number\n\t/** Workers on the other resource, at home only, where `workersPer` says nothing of it: 3 when left out */\n\tlumberjacks?: number\n\t/**\n\t * Workers on each resource at each base (`WorkersPer`): `{ gold: 5, lumber: 3 }` at every base, or a function of the\n\t * base for one that differs (home, an expansion). What it leaves out is `workers` and `lumberjacks`\n\t */\n\tworkersPer?: WorkersPer\n\t/** Whether a base wants no more workers on a deposit than it serves (see the file's comment): yes when left out */\n\tsaturate?: boolean\n\t/** Whether its halls train workers up to what the bases want: yes when left out */\n\ttrainWorkers?: boolean\n\t/**\n\t * Workers trained past what the bases want, to build with: a worker sent to build is off the mine meanwhile, and a\n\t * mine with only as many as it serves would gather less. 1 when left out\n\t */\n\tbuilders?: number\n\t/** Halls to have past the first, each by a mine nobody has a hall at: the seat's `expansions`, else none */\n\texpansions?: number\n\t/**\n\t * When it may expand: a condition (`AiCondition`, as data or a function). Four minutes in and with a building that\n\t * trains soldiers, when left out\n\t */\n\texpandWhen?: AiCondition\n\t/** Whether workers a raid is on walk to a base no enemy is at, and back once theirs is clear: yes when left out */\n\tworkersFlee?: boolean\n}\n\n/**\n * What the economy remembers between thinks, as a save keeps it: the workers that fled a raid\n *\n * @beta\n */\nexport interface EconomyMemory {\n\tv: 1\n\t/** Each worker that fled, by id: the base it fled (its middle), where to, since when, and since when its base stood clear */\n\tfled: Record<string, { from: Vec2; to: Vec2; since: number; clear?: number }>\n\t/**\n\t * Workers more on the other resource at home, while it runs short with the money piling up (AI2): one more each\n\t * `BLOCKED` seconds it stays so, at most `MORE_AT_MOST`, one fewer each twice that once it is not. Since when it has\n\t * been short (`since`) or not (`easy`), and who was sent to it lately (`moved`)\n\t */\n\tmaterial?: { more: number; since?: number; easy?: number; moved?: Record<string, number> }\n}\n\n/**\n * One base as the economy sees it (`ai.economy.bases()`, the report): its deposits, what they serve, the workers it\n * wants and has on each resource\n *\n * @beta\n */\nexport interface EconomyBase {\n\t/** The view's base */\n\tbase: Base\n\t/** Its deposits it gathers from, by resource: those of the money with a hall by them (or something of its own on them), the rest near it */\n\tdeposits: Partial<Record<ResourceKind, EntityState[]>>\n\t/** How many workers its deposits of each resource serve at once */\n\tserves: Partial<Record<ResourceKind, number>>\n\t/** How many it wants on each resource: what it is to have, no more than what is served where it saturates */\n\twants: Partial<Record<ResourceKind, number>>\n\t/** The workers at work on each resource at it, by id */\n\tworking: Partial<Record<ResourceKind, number[]>>\n}\n\n/**\n * The economy as the report shows it (`AiReport.economy.bases`, `fled`): each base with what it wants and has, the\n * workers that fled, how many it trains, what the next expansion waits for\n *\n * @beta\n */\nexport interface EconomyReport {\n\tbases: { at: [number, number]; hall: number; workers: Record<ResourceKind, [working: number, wants: number, serves: number]> }[]\n\tfled: { unit: number; from: [number, number]; since: number }[]\n\t/** Workers it has, those queued counted, and what its bases want together */\n\tworkers: [have: number, want: number]\n\t/** Where the next hall goes, and what it waits for: the build plan's status of the want */\n\texpansion?: string\n}\n\n/**\n * The id of the want for another hall, on the build plan\n *\n * @internal\n */\nexport const EXPAND_WANT = 'economy.expand'\n\n/**\n * A brain's economy (`ai.economy`): its workers, base by base, run by the `economy()` module each think (`think`), or\n * by the melee player's turn, and asked by whoever wants to know (`bases`, `freeMine`, `waiting`). Kept in the brain's\n * memory (`BrainMemory.economy`)\n *\n * @internal\n */\nexport class Economy implements AiArea {\n\t/** What finds it on a brain (`ai.area(Economy)`): made the first time a module asks for it */\n\tstatic readonly id = 'economy'\n\tstatic make(ai: Brain): Economy {\n\t\treturn new Economy(ai)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'economy'\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 economy in a shape this brain does not read: it starts afresh'\n\n\t/** Whether an `economy()` module is in the brain, or the melee player runs it: without one, nothing here runs by itself */\n\tenabled = false\n\t/**\n\t * Whether everything else waits for what the money is gathered at (`builtOn`, a cursed mine), with none of it\n\t * standing and none on its way: there is no money without it\n\t */\n\twaiting = false\n\tprivate memory: EconomyMemory = { v: 1, fled: {} }\n\tprivate moduleOptions: EconomyOptions = {}\n\tprivate thoughtAt = -1\n\tprivate found: { tick: number; bases: EconomyBase[] } | undefined\n\tprivate trained = 0\n\n\tconstructor(\n\t\t/** The brain it runs the economy of */\n\t\treadonly ai: Brain\n\t) {}\n\n\t/** Puts the `economy()` module's options under the brain's settings: what the module is made with */\n\tconfigure(options: EconomyOptions): void {\n\t\tthis.moduleOptions = options\n\t\tthis.enabled = true\n\t}\n\n\t/** How it runs the economy: the module's options, the brain's settings over them (`ai.settings.economy`) */\n\tget options(): EconomyOptions {\n\t\treturn this.ai.cache('economy.options', () => ({ ...this.moduleOptions, ...this.ai.settings.economy }))\n\t}\n\n\t/** How many of a unit type its buildings have queued: on their way, for what is counted as had */\n\tprivate queued(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/** What a base wants on a resource where nothing caps it: `workersPer`, then `workers` on the money everywhere, `lumberjacks` on the other at home */\n\tprivate asked(kind: ResourceKind, base: Base, index: number): number {\n\t\tconst options = this.options\n\t\tconst per = typeof options.workersPer === 'function' ? options.workersPer(this.ai, base, index) : (options.workersPer ?? {})\n\t\tconst asked = per[kind] ?? (kind === this.money ? (options.workers ?? 8) : index === 0 ? (options.lumberjacks ?? 3) : 0)\n\t\t// more at home while what it saves for waits on it (AI2)\n\t\treturn kind === this.material && index === 0 ? asked + (this.memory.material?.more ?? 0) : asked\n\t}\n\n\t/** The game's money: what most things cost (`Registry.currency`), the first resource where it names none */\n\tget money(): ResourceKind {\n\t\tconst { registry } = this.ai\n\t\treturn registry.currency ?? registry.resources[0]?.id ?? ''\n\t}\n\n\t/** The other resource workers gather, where the game has one (lumber, in melee) */\n\tget material(): ResourceKind | undefined {\n\t\treturn this.ai.registry.resources.find((resource) => resource.id !== this.money)?.id\n\t}\n\n\t/** What gathers: the first worker type the player can make (`worker` role) */\n\tget worker(): UnitTypeDef | undefined {\n\t\treturn this.ai.view.typesOf('worker')[0]\n\t}\n\n\t/** What stands on a mine to gather it there (`topper` role: `builtOn` the money), where the game has one */\n\tget topper(): UnitTypeDef | undefined {\n\t\treturn this.ai.view.typesOf('topper')[0]\n\t}\n\n\t/**\n\t * What gathers the other resource where the worker does not (a ghoul, who fights too): of the gatherers the player\n\t * can make, the first that gathers it. The worker where it does\n\t */\n\tget lumberjack(): UnitTypeDef | undefined {\n\t\tconst { worker, material } = this\n\t\tif (material === undefined || !worker || gathers(worker, material)) return worker\n\t\treturn this.ai.view.typesOf('gatherer').find((def) => def.kind === 'unit' && def !== worker && gathers(def, material))\n\t}\n\n\t/** Whether a building takes deposits of a resource (`dropOff`) */\n\tprivate takes(def: UnitTypeDef, kind: ResourceKind): boolean {\n\t\treturn def.dropOff === true || (Array.isArray(def.dropOff) && def.dropOff.includes(kind))\n\t}\n\n\t/**\n\t * Its bases as the economy sees them, once a think: each of the view's bases (home first) with the deposits it\n\t * gathers from, what they serve, the workers it wants and those at work there\n\t */\n\tbases(): EconomyBase[] {\n\t\tconst { ai } = this\n\t\tif (this.found?.tick === ai.tick) return this.found.bases\n\t\tconst { view } = ai\n\t\tconst { money, material, topper, worker } = this\n\t\tconst saturate = this.options.saturate ?? true\n\t\tconst halls = view.mine\n\t\t\t.buildings()\n\t\t\t.finished()\n\t\t\t.where((_, def) => this.takes(def, money))\n\t\tconst toppers = topper ? view.mine.ofType(topper.id).finished() : undefined\n\t\tconst mines = view.resources.ofResource(money).alive()\n\t\tconst reach = HALL_REACH * HALL_REACH\n\t\tconst bases: EconomyBase[] = view.bases().map((base, index) => {\n\t\t\tconst deposits: EconomyBase['deposits'] = {}\n\t\t\tconst serves: EconomyBase['serves'] = {}\n\t\t\t// the money: the mines with a hall of its own by them, at this base; or, where the money is gathered at what\n\t\t\t// stands on a mine, those with one of its own on them\n\t\t\tconst served = mines.filter((each) =>\n\t\t\t\ttoppers\n\t\t\t\t\t? toppers.some((top) => top.x === each.x && top.z === each.z && base.buildings.has(top.id))\n\t\t\t\t\t: halls.some((hall) => distSq(hall, each) < reach && base.buildings.has(hall.id))\n\t\t\t)\n\t\t\tdeposits[money] = served\n\t\t\tserves[money] = served.reduce((sum, each) => sum + this.serving(each, base), 0)\n\t\t\tif (material !== undefined) {\n\t\t\t\tlet trees = view.resourcesNear(base).ofResource(material).alive().items\n\t\t\t\t// none by home (a hall away from the woods): the woods nearest it, however far, or home would never want any\n\t\t\t\tif (!trees.length && index === 0) {\n\t\t\t\t\tconst nearest = view.resources.ofResource(material).alive().nearest(base.at)\n\t\t\t\t\tif (nearest) trees = view.resourcesNear(nearest, WOODS).ofResource(material).alive().items\n\t\t\t\t}\n\t\t\t\tdeposits[material] = trees as EntityState[]\n\t\t\t\tserves[material] = trees.reduce((sum, each) => sum + (view.def(each).resource?.slots ?? 1), 0)\n\t\t\t}\n\t\t\tconst wants: EconomyBase['wants'] = {}\n\t\t\tfor (const kind of [money, ...(material !== undefined ? [material] : [])]) {\n\t\t\t\t// the workers only want what they can gather: the other resource is the lumberjacks' where they do not\n\t\t\t\tif (!worker || !gathers(worker, kind)) continue\n\t\t\t\tconst want = this.asked(kind, base, index)\n\t\t\t\twants[kind] = saturate ? Math.min(want, serves[kind] ?? 0) : (serves[kind] ?? 0) > 0 ? want : 0\n\t\t\t}\n\t\t\treturn { base, deposits, serves, wants, working: {} }\n\t\t})\n\t\t// who works where: each harvesting worker at the base nearest where it walks to (the mine, or the hall it brings\n\t\t// what it carries to: either is its base's; one sent to another base counts there on its way), else where it is,\n\t\t// on what it carries (or what it walks to)\n\t\tif (worker) {\n\t\t\tfor (const unit of view.mine.ofType(worker.id)) {\n\t\t\t\tif (unit.own?.order !== 'harvest') continue\n\t\t\t\tconst kind = snapshotOf(unit, gathering)?.kind ?? this.kindNear(unit.own.goal ?? unit)\n\t\t\t\tconst at = unit.own.goal ?? unit\n\t\t\t\tlet best: EconomyBase | undefined\n\t\t\t\tlet bestDistance = Infinity\n\t\t\t\tfor (const each of bases) {\n\t\t\t\t\tconst d = distSq(each.base.at, at)\n\t\t\t\t\tif (d < bestDistance) {\n\t\t\t\t\t\tbestDistance = d\n\t\t\t\t\t\tbest = each\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (best) (best.working[kind] ??= []).push(unit.id)\n\t\t\t}\n\t\t}\n\t\tthis.found = { tick: ai.tick, bases }\n\t\treturn bases\n\t}\n\n\t/** The resource of the deposit nearest a place: what a worker walking there will gather. The money where none is near */\n\tprivate kindNear(at: Vec2): ResourceKind {\n\t\tconst near = this.ai.view.resources.nearest(at)\n\t\treturn near && distSq(near, at) < 6 * 6 ? (this.ai.view.def(near).resource?.kind ?? this.money) : this.money\n\t}\n\n\t/**\n\t * How many workers one deposit of the money serves at once, as worked by this base (see the file's comment): what\n\t * stands on it to gather it says (`gatherers`); one entered serves its slots for every round trip from the hall\n\t * nearest it; one worked from beside, its slots\n\t */\n\tserving(deposit: EntityState, base: Base): number {\n\t\tconst { view, registry } = this.ai\n\t\tconst def = view.def(deposit)\n\t\tconst resource = def.resource\n\t\tconst { topper, worker } = this\n\t\tif (topper?.builtOn === resource?.kind && topper) return topper.gatherers ?? 5\n\t\tif (!resource?.entered || !worker) return resource?.slots ?? 1\n\t\tconst hall = base.buildings.where((_, each) => this.takes(each, resource.kind)).nearest(deposit)\n\t\tif (!hall) return resource.slots\n\t\t// the walk between the two edges: what has no size of its own (a deposit) stands in for nothing\n\t\tconst size = (each: UnitTypeDef) => (each.stats ? baseStats(each, registry).radius : 0) || 0\n\t\tconst speed = baseStats(worker, registry).moveSpeed || 0\n\t\tconst gap = Math.max(0, Math.sqrt(distSq(hall, deposit)) - size(view.def(hall)) - size(def))\n\t\tconst gather = resource.gatherTime ?? worker.harvester?.gatherTime ?? 1\n\t\tconst walk = speed > 0 ? (2 * gap) / speed : 0\n\t\treturn Math.max(1, Math.ceil((resource.slots || 1) * (1 + walk / Math.max(0.1, gather))))\n\t}\n\n\t/** Whether a unit is busy for someone else: in a squad (on an errand), held by a rule, or fled */\n\tprivate busy(unit: EntityState): boolean {\n\t\tconst { ai } = this\n\t\treturn ai.squads.squadOf(unit) !== undefined || ai.goals.ruled(unit.id) || this.memory.fled[unit.id] !== undefined\n\t}\n\n\t/**\n\t * A gold mine near enough home that nobody has a hall by, and nothing of anyone's stands on, and that a worker can\n\t * walk to from home: the nearest, for another hall. None where every one is taken, or none is known. A mine on\n\t * ground cut off from home (a plateau with no ramp, an island) is left out: the walk to it is asked of the ground\n\t * the player knows each time, nearest first, so the answer is the picture's alone\n\t */\n\tfreeMine(): Vec2 | undefined {\n\t\tconst { view } = this.ai\n\t\tconst home = view.home()\n\t\tif (!home) return undefined\n\t\tconst money = this.money\n\t\t// anyone's hall that takes the money, in sight or remembered\n\t\tconst halls = view.all.filter((entity) => view.def(entity).kind === 'building' && this.takes(view.def(entity), money))\n\t\tconst reach = HALL_REACH * HALL_REACH\n\t\tconst most = EXPAND_REACH * EXPAND_REACH\n\t\tconst free = [...view.mines()]\n\t\t\t.map((mine) => ({ mine, d: distSq(mine, home) }))\n\t\t\t.filter(({ mine, d }) => d < most && !halls.some((hall) => distSq(hall, mine) < reach))\n\t\t\t.sort((a, b) => a.d - b.d || a.mine.id - b.mine.id)\n\t\t// from the hall's side towards each mine: the ground under the hall itself has no route out\n\t\tconst out = (view.def(home).radius ?? 2) + 1.5\n\t\tfor (const { mine } of free) if (this.walkable(towards(home, mine, out), mine)) return { x: mine.x, z: mine.z }\n\t\treturn undefined\n\t}\n\n\t/** Whether a worker walks from one place to a mine: the route over the ground known to its side (the mine itself is in the way) ends by it */\n\tprivate walkable(from: Vec2, mine: Vec2): boolean {\n\t\tconst route = this.ai.view.findPath(from, towards(mine, from, MINE_SIDE))\n\t\tconst end = route?.[route.length - 1]\n\t\treturn !!end && distSq(end, mine) <= MINE_WALK_REACH * MINE_WALK_REACH\n\t}\n\n\t/**\n\t * The think, once a think: a builder to every building half built that nobody works on, workers off a raid and back,\n\t * idle workers to where they are missing, the spare moved where short, the other resource's gatherers, what the\n\t * money is gathered at, workers trained, the next hall wanted. A second call in the same think does nothing\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 = 0\n\t\tthis.prune()\n\t\tconst options = this.options\n\t\tthis.sites()\n\t\tif (options.workersFlee ?? true) this.flee()\n\t\tthis.back()\n\t\tthis.blocked()\n\t\tthis.assign()\n\t\tthis.rebalance()\n\t\tthis.toMaterial()\n\t\tthis.lumberjacks()\n\t\tthis.toppers()\n\t\tif (options.trainWorkers ?? true) this.train()\n\t\tthis.expand()\n\t}\n\n\t/**\n\t * Whether the other resource holds it up (lumber, where gold is the money): under `SHORT_UNDER` of it with `PILED` of\n\t * the money or more, what it has as the snapshot says. One more worker on it at home each `BLOCKED` seconds it is so,\n\t * at most `MORE_AT_MOST`; one fewer each twice that once it is not\n\t */\n\tprivate blocked(): void {\n\t\tconst { ai } = this\n\t\tconst { material } = this\n\t\tif (material === undefined) return\n\t\tconst tick = ai.tick\n\t\tconst period = BLOCKED * ai.session.tickRate\n\t\tconst kept = this.memory.material\n\t\tconst have = ai.view.me.resources\n\t\tif ((have[material] ?? 0) < SHORT_UNDER && (have[this.money] ?? 0) >= PILED) {\n\t\t\tconst state = (this.memory.material ??= { more: 0 })\n\t\t\tdelete state.easy\n\t\t\tstate.since ??= tick\n\t\t\tif (tick - state.since < period || state.more >= MORE_AT_MOST) return\n\t\t\tstate.more++\n\t\t\tstate.since = tick\n\t\t\tai.decide(`puts ${state.more} more on ${material} at home: ${this.money} piles up while ${material} runs short`, { kind: 'economy' })\n\t\t\treturn\n\t\t}\n\t\tif (!kept) return\n\t\tdelete kept.since\n\t\tif (kept.more <= 0) {\n\t\t\tdelete this.memory.material\n\t\t\treturn\n\t\t}\n\t\tkept.easy ??= tick\n\t\tif (tick - kept.easy < period * 2) return\n\t\tkept.more--\n\t\tkept.easy = tick\n\t}\n\n\t/**\n\t * Home short on the other resource while more are put on it (`blocked`), and nobody idle to send: a worker of the\n\t * money at home, carrying nothing, goes to the trees by home. One a think\n\t */\n\tprivate toMaterial(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { material, money, worker } = this\n\t\tif (material === undefined || !(this.memory.material?.more ?? 0) || !worker || !gathers(worker, material)) return\n\t\tconst home = this.bases()[0]\n\t\tif (!home || (home.wants[material] ?? 0) - (home.working[material]?.length ?? 0) <= 0) return\n\t\tconst tree = nearestOf(home.deposits[material] ?? [], home.base.at)\n\t\tif (!tree) return\n\t\t// those sent this way a little while ago are on their way still, counted on what they carried last\n\t\tconst state = this.memory.material!\n\t\tconst moved = (state.moved ??= {})\n\t\tfor (const id in moved) {\n\t\t\tconst unit = view.byId(Number(id))\n\t\t\t// there once it gathers it, or no longer at it; a minute at the most\n\t\t\tif (!unit || unit.own?.order !== 'harvest' || snapshotOf(unit, gathering)?.kind === material || ai.tick - moved[id] >= 60 * ai.session.tickRate)\n\t\t\t\tdelete moved[id]\n\t\t}\n\t\tconst missing = (home.wants[material] ?? 0) - (home.working[material]?.length ?? 0) - Object.keys(moved).length\n\t\tif (missing <= 0) return\n\t\tconst from = (home.working[money] ?? [])\n\t\t\t.map((id) => view.byId(id)!)\n\t\t\t.filter((unit) => unit && moved[unit.id] === undefined && !unit.own?.hidden && !snapshotOf(unit, gathering)?.carrying && !this.busy(unit))\n\t\t\t.sort((a, b) => distSq(a, tree) - distSq(b, tree) || a.id - b.id)[0]\n\t\tif (!from) return\n\t\tai.send({ type: 'order', entities: [from.id], order: { type: 'harvest', target: tree.id } })\n\t\tmoved[from.id] = ai.tick\n\t\tai.decide(`moves a worker from ${money} to ${material} at home`, { kind: 'economy' })\n\t}\n\n\t/** Whether it has run at all: by the module, or the melee player's turn */\n\tget running(): boolean {\n\t\treturn this.enabled || this.thoughtAt >= 0\n\t}\n\n\t/** Marks the think's economy done another way (a brain's own turn that ran it itself): `think` does nothing more this think */\n\tdone(): void {\n\t\tthis.thoughtAt = this.ai.tick\n\t}\n\n\t/** What is remembered of the dead, or of what is no longer its own, let go of */\n\tprivate prune(): void {\n\t\tconst { view, goals } = this.ai\n\t\tfor (const id in this.memory.fled) if (!view.mine.has(Number(id))) delete this.memory.fled[id]\n\t\t// what it holds and no longer remembers as fled (a save of before, a unit given away) is let go of\n\t\tconst held = goals.held(FLED)\n\t\tif (held) {\n\t\t\tconst away = held.units.filter((id) => this.memory.fled[id] === undefined)\n\t\t\tif (away.length) goals.drop(FLED, away)\n\t\t}\n\t}\n\n\t/** Its workers, as of the think */\n\tprivate workers(): UnitSet {\n\t\tconst { worker } = this\n\t\tconst { view } = this.ai\n\t\treturn worker ? view.mine.ofType(worker.id) : view.mine.where(() => false)\n\t}\n\n\t/** A builder to every building of its own going up by builders that nobody works on: the nearest free worker */\n\tprivate sites(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst workers = this.workers()\n\t\tfor (const site of view.mine) {\n\t\t\t// what goes up on its own needs nobody\n\t\t\tif (builtSoFar(site) === undefined || constructionOf(view.def(site)) !== 'builder') continue\n\t\t\tconst busy = workers.some(\n\t\t\t\t(worker) => (worker.own?.order === 'build' || worker.own?.order === 'construct') && distSq(worker, site) < AT_SITE * AT_SITE\n\t\t\t)\n\t\t\t// one sent to it lately is on its way, whatever a picture a few ticks old says (a think sliced by its budget)\n\t\t\tconst sent = `construct:${site.id}:`\n\t\t\tif (busy || workers.some((worker) => ai.sentTo(worker.id)?.key === sent)) continue\n\t\t\tconst helper = workers.where((worker) => !worker.own?.hidden && worker.own?.order !== 'build' && !this.busy(worker)).nearest(site)\n\t\t\tif (helper) ai.send({ type: 'order', entities: [helper.id], order: { type: 'construct', target: site.id } })\n\t\t}\n\t}\n\n\t/**\n\t * Workers a raid is on, at a base its fighters do not hold: off to the nearest base no enemy is at. A worker with no\n\t * such base stays at work: there is nowhere better to be\n\t */\n\tprivate flee(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst foes = view.hostile\n\t\t\t.alive()\n\t\t\t.units()\n\t\t\t.where((entity, def) => !entity.asleep && !!def.attacks?.length)\n\t\tif (!foes.length) return\n\t\tconst bases = view.bases()\n\t\tconst safe = bases.filter((base) => !foes.near(base.at, AT_BASE).length)\n\t\tif (!safe.length) return\n\t\tconst fled: EntityState[] = []\n\t\tfor (const unit of this.workers()) {\n\t\t\tif (unit.own?.hidden || this.busy(unit) || unit.own?.order === 'build') continue\n\t\t\tconst on = foes.near(unit, ENGAGED)\n\t\t\tif (!on.length) continue\n\t\t\t// held, where the base's fighters near it stand a fair chance against what is on it\n\t\t\tconst guards = view.mine.fighters().near(unit, ENGAGED * 2)\n\t\t\tif (guards.length && view.strength.odds(guards, on) >= FLEE_UNDER) continue\n\t\t\tconst from = bases.reduce((best, base) => (distSq(base.at, unit) < distSq(best.at, unit) ? base : best), bases[0])\n\t\t\tconst to = safe\n\t\t\t\t.filter((base) => base !== from)\n\t\t\t\t.reduce<Base | undefined>((best, base) => (!best || distSq(base.at, unit) < distSq(best.at, unit) ? base : best), undefined)\n\t\t\tif (!to) continue\n\t\t\tthis.memory.fled[unit.id] = { from: point(from.at), to: point(to.at), since: ai.tick }\n\t\t\tfled.push(unit)\n\t\t}\n\t\tif (!fled.length) return\n\t\t// by where they go: one order for those going the same way\n\t\tconst byDestination = new Map<string, { to: Vec2; ids: number[] }>()\n\t\tfor (const unit of fled) {\n\t\t\tconst to = this.memory.fled[unit.id].to\n\t\t\tconst key = `${to.x},${to.z}`\n\t\t\tconst entry = byDestination.get(key) ?? byDestination.set(key, { to, ids: [] }).get(key)!\n\t\t\tentry.ids.push(unit.id)\n\t\t}\n\t\t// held while away, so that nothing else sends them off (a scout wanted: the pool's workers are a goal's to take)\n\t\tai.goals.take(\n\t\t\tfled.map((unit) => unit.id),\n\t\t\t'told',\n\t\t\t{ id: FLED, seconds: Infinity }\n\t\t)\n\t\tfor (const { to, ids } of byDestination.values()) {\n\t\t\tai.send({ type: 'order', entities: ids, order: { type: 'move', point: to } })\n\t\t\tai.decide(`${ids.length === 1 ? '1 worker flees' : `${ids.length} workers flee`} a raid to the base at ${where(to)}`, { kind: 'economy' })\n\t\t}\n\t}\n\n\t/** Those that fled, back to work at their own base once it has stood clear long enough */\n\tprivate back(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst foes = view.hostile\n\t\t\t.alive()\n\t\t\t.units()\n\t\t\t.where((entity, def) => !entity.asleep && !!def.attacks?.length)\n\t\tconst back: number[] = []\n\t\tfor (const id in this.memory.fled) {\n\t\t\tconst fled = this.memory.fled[id]\n\t\t\tif (foes.near(fled.from, AT_BASE).length) {\n\t\t\t\tdelete fled.clear\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tfled.clear ??= ai.tick\n\t\t\tif (ai.tick - fled.clear < CLEAR_FOR * ai.session.tickRate) continue\n\t\t\tback.push(Number(id))\n\t\t\tdelete this.memory.fled[id]\n\t\t}\n\t\tif (!back.length) return\n\t\tai.goals.drop(FLED, back)\n\t\t// to the deposit of the money nearest each: to work where they were\n\t\tconst bases = this.bases()\n\t\tconst byDeposit = new Map<number, number[]>()\n\t\tfor (const id of back) {\n\t\t\tconst unit = view.byId(id)!\n\t\t\tconst deposit = bases\n\t\t\t\t.flatMap((each) => each.deposits[this.money] ?? [])\n\t\t\t\t.reduce<EntityState | undefined>((best, each) => (!best || distSq(each, unit) < distSq(best, unit) ? each : best), undefined)\n\t\t\tif (deposit) (byDeposit.get(deposit.id) ?? byDeposit.set(deposit.id, []).get(deposit.id)!).push(id)\n\t\t}\n\t\tfor (const [target, entities] of byDeposit) ai.send({ type: 'order', entities, order: { type: 'harvest', target } })\n\t\tai.decide(`${back.length === 1 ? '1 worker goes' : `${back.length} workers go`} back to work: the raid is over`, { kind: 'economy' })\n\t}\n\n\t/**\n\t * The idle workers, each to the base and resource where the most are missing (the nearest base among equals); with\n\t * nothing missing anywhere, to the money at the nearest base that has some, rather than stand about\n\t */\n\tprivate assign(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst home = view.home()\n\t\tconst idle = this.workers().where((unit) => !!unit.own && !unit.own.order && !unit.own.hidden && !this.busy(unit))\n\t\tif (!idle.length || !home) return\n\t\tconst bases = this.bases()\n\t\tconst { money } = this\n\t\t// how many each base is short on each resource, as it stands, less what this think sends\n\t\tconst short = bases.map((each) => {\n\t\t\tconst missing: Partial<Record<ResourceKind, number>> = {}\n\t\t\tfor (const kind in each.wants) missing[kind] = each.wants[kind]! - (each.working[kind]?.length ?? 0)\n\t\t\treturn missing\n\t\t})\n\t\tconst orders = new Map<number, number[]>()\n\t\tfor (const unit of idle) {\n\t\t\tlet best: { at: number; kind: ResourceKind; missing: number; distance: number } | undefined\n\t\t\tbases.forEach((each, at) => {\n\t\t\t\tfor (const kind in short[at]) {\n\t\t\t\t\tconst missing = short[at][kind]!\n\t\t\t\t\tif (missing <= 0 || !each.deposits[kind]?.length) continue\n\t\t\t\t\tconst distance = distSq(each.base.at, unit)\n\t\t\t\t\tif (!best || missing > best.missing || (missing === best.missing && distance < best.distance)) best = { at, kind, missing, distance }\n\t\t\t\t}\n\t\t\t})\n\t\t\tlet deposit: EntityState | undefined\n\t\t\tif (best) {\n\t\t\t\tshort[best.at][best.kind]! -= 1\n\t\t\t\tconst base = bases[best.at]\n\t\t\t\t// the money: the deposit of the base nearest the worker; the other: the deposit nearest the base's middle, where\n\t\t\t\t// the walk to the hall is shortest\n\t\t\t\tdeposit = best.kind === money ? nearestOf(base.deposits[money]!, unit) : nearestOf(base.deposits[best.kind]!, base.base.at)\n\t\t\t} else {\n\t\t\t\t// nothing missing anywhere: on the money nearest it all the same; with no hall by any mine, the mine nearest home\n\t\t\t\tconst served = bases.flatMap((each) => each.deposits[money] ?? [])\n\t\t\t\tdeposit = served.length ? nearestOf(served, unit) : this.topper ? undefined : view.resources.ofResource(money).alive().nearest(home)\n\t\t\t}\n\t\t\tif (deposit) (orders.get(deposit.id) ?? orders.set(deposit.id, []).get(deposit.id)!).push(unit.id)\n\t\t}\n\t\tfor (const [target, entities] of orders) ai.send({ type: 'order', entities, order: { type: 'harvest', target } })\n\t}\n\n\t/**\n\t * A base with more on the money than its deposits serve (or with none left) gives its spare to a base that is short,\n\t * a few a think: those not carrying anything, so that nothing gathered is lost on the way\n\t */\n\tprivate rebalance(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { money } = this\n\t\tconst bases = this.bases()\n\t\tif (bases.length < 2) return\n\t\tlet moved = 0\n\t\tfor (const from of bases) {\n\t\t\tconst working = from.working[money] ?? []\n\t\t\tconst spare = working.length - (from.wants[money] ?? 0)\n\t\t\tif (spare <= 0) continue\n\t\t\tconst to = bases\n\t\t\t\t.filter((each) => each !== from && (each.wants[money] ?? 0) - (each.working[money]?.length ?? 0) > 0 && each.deposits[money]?.length)\n\t\t\t\t.sort((a, b) => distSq(a.base.at, from.base.at) - distSq(b.base.at, from.base.at))[0]\n\t\t\tif (!to) continue\n\t\t\tconst missing = (to.wants[money] ?? 0) - (to.working[money]?.length ?? 0)\n\t\t\tconst ids = working\n\t\t\t\t.map((id) => view.byId(id)!)\n\t\t\t\t.filter((unit) => !unit.own?.hidden && !snapshotOf(unit, gathering)?.carrying && !this.busy(unit))\n\t\t\t\t.slice(0, Math.min(spare, missing, MOVE_AT_ONCE - moved))\n\t\t\t\t.map((unit) => unit.id)\n\t\t\tif (!ids.length) continue\n\t\t\tconst deposit = nearestOf(to.deposits[money]!, from.base.at)!\n\t\t\tai.send({ type: 'order', entities: ids, order: { type: 'harvest', target: deposit.id } })\n\t\t\tai.decide(\n\t\t\t\t`moves ${ids.length === 1 ? '1 worker' : `${ids.length} workers`} from the base at ${where(from.base.at)} to the one at ${where(to.base.at)}: ${(from.wants[money] ?? 0) === 0 ? 'its mine is gone' : 'it has more than it serves'}`,\n\t\t\t\t{ kind: 'economy' }\n\t\t\t)\n\t\t\tmoved += ids.length\n\t\t\tif (moved >= MOVE_AT_ONCE) return\n\t\t}\n\t}\n\n\t/**\n\t * Where the worker does not gather the other resource: so many of what does (`lumberjack`, a ghoul) sent to the trees\n\t * by home, those at home first, as many as home wants on it (the seat's `lumberjacks`). They are trained as soldiers are\n\t */\n\tprivate lumberjacks(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { lumberjack, worker, material } = this\n\t\tconst home = view.home()\n\t\tif (!lumberjack || lumberjack === worker || material === undefined || !home) return\n\t\tconst homeBase = view.bases()[0]\n\t\tconst wanted = homeBase ? this.asked(material, homeBase, 0) : 0\n\t\tconst all = view.mine.ofType(lumberjack.id).where((unit) => !unit.own?.hidden && !this.busy(unit))\n\t\tconst chopping = all.filter((unit) => unit.own?.order === 'harvest').length\n\t\tif (chopping >= wanted) return\n\t\tconst tree = view.resources.ofResource(material).nearest(home)\n\t\tif (!tree) return\n\t\tconst free = all.filter((unit) => unit.own?.order !== 'harvest' && distSq(unit, home) < HALL_REACH * HALL_REACH * 4)\n\t\tfree.sort((a, b) => distSq(a, home) - distSq(b, home))\n\t\tconst sent = free.slice(0, wanted - chopping)\n\t\tif (sent.length) ai.send({ type: 'order', entities: sent.map((unit) => unit.id), order: { type: 'harvest', target: tree.id } })\n\t}\n\n\t/**\n\t * Where mines are gathered from at what stands on them (`topper`): one put up on each mine by a hall of its own that\n\t * has none, a mine at a time, through the build plan. With none at all and none on its way, everything else waits\n\t * (`waiting`)\n\t */\n\tprivate toppers(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { topper } = this\n\t\tthis.waiting = false\n\t\tif (!topper || view.mine.some((entity) => entity.own?.build === topper.id && entity.own.order === 'build')) return\n\t\tconst hall = view.typesOf('hall')[0]\n\t\tconst halls = hall ? view.mine.ofType(hall.id).finished() : view.mine.where(() => false)\n\t\tfor (const at of halls) if (ai.plans.build.build(topper, { near: { x: at.x, z: at.z }, by: 'economy' })) return\n\t\tthis.waiting = view.mine.ofType(topper.id).length === 0\n\t}\n\n\t/** How many workers the bases want together: what the halls train up to, with `builders` more */\n\twanted(): number {\n\t\tlet sum = 0\n\t\tfor (const each of this.bases()) for (const kind in each.wants) sum += each.wants[kind] ?? 0\n\t\treturn sum\n\t}\n\n\t/** Workers trained at every hall with nothing in its queue, while it has fewer (those queued counted) than its bases want */\n\tprivate train(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { worker } = this\n\t\tif (!worker) return\n\t\tconst halls = view.mine\n\t\t\t.buildings()\n\t\t\t.finished()\n\t\t\t.where((_, def) => (def.trains ?? []).includes(worker.id))\n\t\tlet have = this.workers().length + this.queued(worker.id)\n\t\tconst want = this.wanted() + (this.options.builders ?? 1)\n\t\t// those at a base that is short train first\n\t\tconst bases = this.bases()\n\t\tconst shortAt = (at: Vec2) => {\n\t\t\tconst base = bases.find((each) => each.base.buildings.some((building) => building.x === at.x && building.z === at.z))\n\t\t\tif (!base) return 0\n\t\t\tlet missing = 0\n\t\t\tfor (const kind in base.wants) missing += (base.wants[kind] ?? 0) - (base.working[kind]?.length ?? 0)\n\t\t\treturn missing\n\t\t}\n\t\tconst ready = halls.filter((each) => !queueOf(each).length)\n\t\tready.sort((a, b) => shortAt(b) - shortAt(a))\n\t\tfor (const at of ready) {\n\t\t\tif (have >= want) return\n\t\t\tif (!ai.plans.production.train(at, worker)) return\n\t\t\thave++\n\t\t\tthis.trained++\n\t\t}\n\t}\n\n\t/** Another hall by a free mine, as many as it is to have, once the condition holds: a standing want of the build plan */\n\tprivate expand(): void {\n\t\tconst { ai } = this\n\t\tconst hall = ai.view.typesOf('hall')[0]\n\t\tconst expansions = this.options.expansions ?? 0\n\t\tif (!hall || expansions <= 0) {\n\t\t\tai.plans.build.drop(EXPAND_WANT)\n\t\t\treturn\n\t\t}\n\t\tconst when = this.options.expandWhen ?? DEFAULT_EXPAND_WHEN\n\t\tai.plans.build.want({\n\t\t\tid: EXPAND_WANT,\n\t\t\ttype: hall.id,\n\t\t\tcount: 1 + expansions,\n\t\t\tpriority: 40,\n\t\t\tkeep: true,\n\t\t\tby: 'economy',\n\t\t\t// by the mine, not just within sight of it: the first ground seen on the way there would be as far as a hall\n\t\t\t// reaches. Where nobody has looked, the plan sends a worker first\n\t\t\twithin: HALL_REACH - 1,\n\t\t\tnear: () => this.freeMine(),\n\t\t\twhen: (brain) => evaluate(when, brain) && !!this.freeMine()\n\t\t})\n\t}\n\n\t/** The economy as the report shows it */\n\treport(): EconomyReport {\n\t\tconst { ai } = this\n\t\tconst { worker } = this\n\t\tconst running = this.running\n\t\tconst bases = running ? this.bases() : []\n\t\treturn {\n\t\t\tbases: bases.map((each) => {\n\t\t\t\tconst workers: EconomyReport['bases'][number]['workers'] = {}\n\t\t\t\tfor (const kind of new Set([...Object.keys(each.wants), ...Object.keys(each.working)]))\n\t\t\t\t\tworkers[kind] = [each.working[kind]?.length ?? 0, each.wants[kind] ?? 0, each.serves[kind] ?? 0]\n\t\t\t\treturn { at: pair(each.base.at), hall: each.base.centre.id, workers }\n\t\t\t}),\n\t\t\tfled: Object.entries(this.memory.fled).map(([unit, fled]) => ({ unit: Number(unit), from: pair(fled.from), since: fled.since })),\n\t\t\tworkers: [worker ? this.workers().length + this.queued(worker.id) : 0, running ? this.wanted() + (this.options.builders ?? 1) : 0],\n\t\t\t...(ai.plans.build.get(EXPAND_WANT) && { expansion: ai.plans.build.status(EXPAND_WANT) ?? 'new' })\n\t\t}\n\t}\n\n\t/** What it remembers, 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 Object.keys(this.memory.fled).length > 0 || this.memory.material !== undefined\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\treport.economy = { ...report.economy, ...this.report() }\n\t}\n\n\tsave(): EconomyMemory {\n\t\treturn structuredClone(this.memory)\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 EconomyMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\tfled: structuredClone(given.fled ?? {}),\n\t\t\t...(given.material && typeof given.material.more === 'number' && { material: { ...given.material } })\n\t\t}\n\t\treturn true\n\t}\n}\n\n/** When it expands, where nothing says: four minutes in, with a building that trains soldiers */\nconst DEFAULT_EXPAND_WHEN: AiCondition = { all: [{ time: { after: 240 } }, { units: { role: 'barracks' } }] }\n\n/** Of some entities, the one nearest a place */\nfunction nearestOf(entities: readonly EntityState[], to: Vec2): EntityState | undefined {\n\tlet best: EntityState | undefined\n\tlet bestDistance = Infinity\n\tfor (const each of entities) {\n\t\tconst d = distSq(each, to)\n\t\tif (d < bestDistance) {\n\t\t\tbestDistance = d\n\t\t\tbest = each\n\t\t}\n\t}\n\treturn best\n}\n\n/**\n * The economy module: the workers base by base each think (`ai.economy.think`): builders to sites, workers off a raid and\n * back, the idle where they are missing, the spare moved, the other resource's gatherers, what the money is gathered at,\n * workers trained, another hall wanted. With how it runs where the brain's definition and the seat's options say nothing\n * (`EconomyOptions`)\n *\n * @beta\n */\nexport const economy = (options: EconomyOptions = {}): AiModuleDef =>\n\tdefineModule('economy', (ai: Brain): AiModule => {\n\t\tai.area(Economy).configure(options)\n\t\treturn {\n\t\t\tid: 'economy',\n\t\t\tphase: 'plan',\n\t\t\tthink: () => ai.area(Economy).think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\teconomy?: EconomyMemory\n\t}\n}\n","import { type AbilityDef, anyEffect, at, baseStats, type UnitTypeDef } from '#engine/defs'\nimport { farthestReach } from '#engine/attacks'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { snapshotOf } from '#engine/components'\nimport type { PlayerId } from '#engine/entity'\nimport { shopStock } from '#engine/items'\nimport { inventorySlots } from '#engine/inventory'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { Registry } from '#engine/registry'\nimport type { EntityState, LearnableInfo, Snapshot } from '#engine/session/protocol'\nimport type { Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { orderKey } from './checks'\nimport { type AiCondition, evaluate } from './rules'\nimport { type Squad } from './squads'\nimport { defineTask, type TaskDef } from './task'\nimport { UnitSet } from './view'\nimport { heroOfState } from '#engine/hero'\nimport { an, pair, point, where } from './geometry'\nimport { ENGAGED, FIGHT_REACH } from './reach'\n\n/*\n * Micro (AI plan, C2): the fight itself, once a squad is in one. The squads (C1) say where the army goes and watch\n * that it gets there; what each unit does once the swords are out was one rule for everyone (hit the caster, then the\n * weakest) and nothing else: no one stepped back, no one ran, no one bought anything, a catapult shot whatever stood\n * nearest. This file is what a player's hands do during a fight, and it never changes what a squad was told to do:\n *\n * - **Focus fire** (`targets`): all of a squad on one rival at a time, the one worth most. Damage spread over ten\n * units kills none of them for a long while; the same damage on one kills it at once, and a dead unit deals no\n * damage. Who is worth most is a ranked list of rules (casters, then heroes, then whoever is weakest; a game's\n * own: workers, a type by name, a condition), or a function of the game's. Chosen again every few seconds, or when\n * the target falls, and queued with the squad's errand so the units go on with it after.\n * - **Kiting** (`kite`): a ranged unit closed on by a melee one it can outrun steps back as far as its own reach, then\n * shoots again. A footman has to catch a rifleman to hurt it; a rifleman has to stand still only to shoot. Only from\n * what it is faster than: stepping back from something as fast as itself trades its shots for a walk and nothing\n * else (measured: riflemen kiting footmen of the same speed lost more fights than they won). Within the squad's\n * spread and no more than once in a while, so that the squad neither scatters nor stutters.\n * - **Fleeing** (`unitsFlee`, `heroesFlee`, `returnAt`): a unit about to die leaves the fight for the nearest safe\n * building of its own, and comes back once healed (or, with nothing to heal it, once safe). It leaves its squad for\n * the micro module's own `fleeing` squad, so the squad's task goes on without it (the classic Units Flee, Heroes\n * Flee); `removeInjuries` sends the hurt home to heal between fights, `ignoreInjured` keeps them out until healed.\n * - **Spells** (`spells`): an ability that has to be aimed is used where it does most: on the hurt friend, on the knot\n * of enemies, on the nearest foe, as its effects say (the ability's own `ai` first, then the brain's `spells` map,\n * then what the kit works out from the effects). What is on autocast looks after itself.\n * - **Items** (`takeItems`, `buyItems`, `shopping`): a potion is drunk when it is needed, what lies about is picked up,\n * and a hero with nothing to do walks to a shop in reach for what its list says.\n * - **Mercenaries** (`hireUnits`, `hiring`): with money to spare and supply free, a hero (or a fighter) with nothing to\n * do walks to a place that hires in reach (a tavern, a mercenary camp: `UnitTypeDef.hires`) and hires there what its\n * list says, or the strongest for its price.\n * - **Siege** (`smartArtillery`): a siege unit shoots buildings when there are any in reach and nothing threatens it,\n * and is kept behind its squad's middle.\n * - **Heroes** (`heroes`): which hero to make next and which skill it learns next, as a list or a function.\n *\n * Every knob has a data form (`MicroOptions`, plain JSON on the brain's definition or the seat's options) and a\n * function form. What the module remembers (who each squad hits, who fled where, who kited when, who shops for what)\n * is plain data in the brain's memory (`BrainMemory.micro`), so a save keeps it.\n */\n\n/** Seconds a squad keeps hitting the one it was told to, before it is chosen again */\nconst FOCUS_EVERY = 4\n/** Seconds between two steps back of one unit: what keeps a kiting unit from stuttering */\nconst KITE_EVERY = 3\n/** How near a melee foe comes, past its own reach, before a ranged unit steps back */\nconst KITE_CLOSE = 3\n/** How much faster than the foe a unit is to step back from it: as fast is not enough, the foe is on it again as it stops */\nconst KITE_FASTER = 1.05\n/** How far from the middle of its squad a kiting unit may step, past the squad's spread */\nconst KITE_LEASH = 1\n/** The odds under which a unit does not bother kiting: its squad falls back, or fights on to the last */\nconst KITE_ODDS = 0.3\n/** Seconds between two orders of a siege unit */\nconst SIEGE_EVERY = 4\n/** How near a siege unit a foe is for the unit to be threatened: it shoots what threatens it, not buildings */\nconst SIEGE_THREATENED = 6\n/** How far behind the squad's middle a siege unit ahead of it is sent */\nconst SIEGE_BEHIND = 3\n/** Seconds a fled unit with nothing to heal it waits in safety before it is back */\nconst FLEE_SAFE = 8\n/**\n * Seconds of its own healing a fled unit is worth waiting for: one that would take longer to be back at `returnAt` (a\n * trickle of regeneration) is as one nothing heals, and comes back once safe, rather than sitting out the game\n */\nconst HEAL_WAIT = 60\n/** How far a unit with nowhere safe to go runs from the fight */\nconst FLEE_AWAY = 20\n/** How near a destination a fleeing unit is there */\nconst FLEE_ARRIVE = 4\n/** Seconds before a fleeing unit standing idle short of its destination is sent again */\nconst FLEE_RESEND = 3\n/** How far a shop may be for a hero to walk to it: not across the map */\nconst SHOP_REACH = 60\n/** How near a shop a hero is at it: the engine's shop range (6), a little in */\nconst AT_SHOP = 5\n/** How important an item is to the purse: under a hero (35), over what can wait */\nconst SHOPPING_PRIORITY = 20\n/** How important a mercenary is to the purse: under an item, over the soldiers trained (0) */\nconst HIRING_PRIORITY = 10\n/** Money to have left over before hiring of itself (the kit's choice): a mercenary is bought with what would lie idle */\nconst HIRING_SPARE = 150\n/** Mercenaries it keeps at the most, of the kit's choice */\nconst HIRING_MOST = 4\n/** How near an item lying about a unit picks it up */\nconst PICK_UP = 10\n/** The share of its health under which a unit drinks what heals, and of its mana under which it drinks what restores */\nconst DRINK_HEALTH = 0.45\nconst DRINK_MANA = 0.25\n/** The squad the micro module keeps the units that fled in */\nconst FLEEING = 'fleeing'\n/** Whose the fleeing squad is */\nconst OWNER = 'micro'\n/**\n * What a computer player sees as it weighs an ability, for the ability's `ai` to decide with (`AbilityDef.ai`)\n *\n * @beta\n */\nexport interface AbilityAiView {\n\tsnapshot: Snapshot\n\tregistry: Registry\n\tplayerId: PlayerId\n\t/** Enemy units it sees, near enough to the caster to matter */\n\tenemies: EntityState[]\n\t/** Its own and allied units that fight, near the caster */\n\tfriends: EntityState[]\n}\n\n/**\n * One rule of who is worth hitting first (`MicroOptions.targets`): what it picks out, how much it adds, when it counts.\n * Plain data\n *\n * @beta\n */\nexport interface TargetRule {\n\t/**\n\t * What it picks out: a role (`caster`, `hero`, `siege`, `worker`, `healer`), `building`, a tag (`ranged`, the game's\n\t * own), or a unit type by id\n\t */\n\tmatch: string\n\t/** What it adds to the worth of what it picks out: 1 when left out. Rules add up; a foe no rule names is worth 1 */\n\tweight?: number\n\t/** When it counts: a condition (`AiCondition`, as data or a function). Always when left out */\n\twhen?: AiCondition\n}\n\n/**\n * Who a squad hits, in code (`MicroOptions.targets`): of the foes in its fight, the one; nothing to leave the units to\n * themselves this time\n *\n * @beta\n */\nexport type TargetPicker = (ai: Brain, squad: Squad, foes: UnitSet) => EntityState | undefined\n\n/**\n * Where to use an ability, in code (`MicroOptions.spells`, by ability id): where (`point`) and on whom (`target`),\n * `null` for not now, `undefined` to leave it to what the kit works out from the effects. `foes` are the enemies within\n * the ability's reach of the caster, `friends` its own and its allies' fighters near it\n *\n * @beta\n */\nexport type SpellAim = (\n\tai: Brain,\n\tcaster: EntityState,\n\tfoes: readonly EntityState[],\n\tfriends: readonly EntityState[],\n\tlevel: number\n) => { point: Vec2; target?: number } | null | undefined\n\n/**\n * A hero the brain means to have (`MicroOptions.heroes`): which, what it learns in what order, what it buys\n *\n * @beta\n */\nexport interface HeroPlan {\n\t/** The hero's unit type */\n\ttype: string\n\t/**\n\t * The order its skills are learned in, each level a line (`['stomp', 'holyLight', 'stomp', …]`); past the end, or\n\t * left out, the ultimate as soon as it can be had and then whatever is furthest behind. Or a function: the skill to\n\t * learn next of those it may, by id\n\t */\n\tskills?: string[] | ((ai: Brain, hero: EntityState, learnable: readonly LearnableInfo[]) => string | undefined)\n\t/** What it shops for, in place of the brain's `shopping` */\n\titems?: ShoppingItem[]\n\t/** The chance it is made at all, 0 to 1 (1 when left out): rolled once, with the brain's numbers, and remembered */\n\tchance?: number\n}\n\n/**\n * A line of a hero's shopping list (`MicroOptions.shopping`, `HeroPlan.items`): an item to carry, how many, when\n *\n * @beta\n */\nexport interface ShoppingItem {\n\t/** The item, by id */\n\titem: string\n\t/** How many of it to carry: 1 when left out */\n\tcount?: number\n\t/** When it is wanted: a condition. Always when left out */\n\twhen?: AiCondition\n}\n\n/**\n * A line of what a brain hires (`MicroOptions.hiring`): a unit a place hires out, how many of it to have, when\n *\n * @beta\n */\nexport interface HiringItem {\n\t/** The unit type, by id: one a place that hires lists (`UnitTypeDef.hires`) */\n\tunit: string\n\t/** How many of it to have: 1 when left out */\n\tcount?: number\n\t/** When it is wanted: a condition. Always when left out */\n\twhen?: AiCondition\n}\n\n/**\n * How a brain fights (`BrainDef.micro`, the seat's `AiOptions.micro` over it, the `micro()` module's own under both):\n * whom it hits first, whether its ranged units kite, when its units flee, how it casts, what it buys, how its siege is\n * used, which heroes it makes. Every field has a data form a save keeps; the function forms are the brain's to give\n * again\n *\n * @beta\n */\nexport interface MicroOptions {\n\t/**\n\t * Who is worth hitting first, as ranked rules (`TargetRule`), or a function that picks (`TargetPicker`). The kit's\n\t * when left out: casters 2, heroes 1.5 (with `targetHeroes`), siege 1, healers 2, over the type's declared\n\t * `UnitTypeDef.ai.priority`; among those alike, the weakest, the nearest\n\t */\n\ttargets?: TargetRule[] | TargetPicker\n\t/** Whether heroes are worth hitting first (the classic Target Heroes): yes when left out */\n\ttargetHeroes?: boolean\n\t/** Seconds a squad keeps hitting the rival it was told to before another is chosen: 4 */\n\tfocusEvery?: number\n\t/**\n\t * Whether ranged units step back from the melee closing on them, when they are the faster: `'ranged'` (or `true`)\n\t * when left out, `false` never\n\t */\n\tkite?: boolean | 'ranged'\n\t/** The share of its health under which a unit leaves the fight for safety (the classic Units Flee): 0.25. `false` never */\n\tunitsFlee?: number | false\n\t/** The same for heroes (Heroes Flee): 0.35. `false` never */\n\theroesFlee?: number | false\n\t/** The share of its health at which a unit that fled is back: 0.8 */\n\treturnAt?: number\n\t/** Whether the hurt go home to heal between fights, not only out of one (Remove Injuries): no when left out */\n\tremoveInjuries?: boolean\n\t/** Whether a unit that fled stays out until healed, however long (Ignore Injured): no when left out, so one nothing heals (or that heals too slowly to wait a minute for) comes back once safe */\n\tignoreInjured?: boolean\n\t/**\n\t * Where to use abilities, by ability id (`SpellAim`): before the ability's own `ai`, and before what the kit works\n\t * out from its effects. `false` casts nothing: what is on autocast looks after itself\n\t */\n\tspells?: Record<string, SpellAim> | false\n\t/** Whether a potion is drunk when it is needed: yes when left out */\n\tpotions?: boolean\n\t/** Whether what lies about is picked up (Take Items): yes when left out */\n\ttakeItems?: boolean\n\t/** Whether heroes buy from a shop in reach (Buy Items): yes when left out, where there is a shop and a list */\n\tbuyItems?: boolean\n\t/**\n\t * What a hero shops for, in order (`ShoppingItem`), or a function that names the item a hero should buy next (none\n\t * for nothing). The cheapest item whose ability heals, one of it, when left out; `false` nothing\n\t */\n\tshopping?: ShoppingItem[] | ((ai: Brain, hero: EntityState) => string | undefined) | false\n\t/** Whether it hires units at a place that hires in reach (a tavern, a mercenary camp: `UnitTypeDef.hires`): yes when left out, where there is one */\n\thireUnits?: boolean\n\t/**\n\t * What it hires, in order (`HiringItem`), or a function that names the unit to hire next of those a place offers (none\n\t * for nothing). When left out: no hero, the strongest soldier for its price, with money to spare (150 past it) and\n\t * supply free, four at the most. `false` nothing\n\t */\n\thiring?: HiringItem[] | ((ai: Brain, offered: readonly UnitTypeDef[]) => string | undefined) | false\n\t/** Whether siege units shoot buildings when they may and stay behind the squad (Smart Artillery): yes when left out */\n\tsmartArtillery?: boolean\n\t/**\n\t * The heroes to make, in order (`HeroPlan`: which, its skills, its items, a chance), or a function that picks the\n\t * next of those that could be made. The first that can be made, and the ultimate first, when left out\n\t */\n\theroes?: HeroPlan[] | ((ai: Brain, candidates: readonly UnitTypeDef[]) => UnitTypeDef | string | undefined)\n}\n\n/**\n * What the micro module remembers between thinks, as a save keeps it\n *\n * @beta\n */\nexport interface MicroMemory {\n\tv: 1\n\t/** Whom each squad hits, by squad name: the foe and since when */\n\tfocus: Record<string, { target: number; since: number }>\n\t/** When each unit last stepped back, by unit id */\n\tkited: Record<string, number>\n\t/** Each unit that fled, by id: the squad it left, since when, where to, and why */\n\tfled: Record<string, { squad?: string; since: number; to: Vec2; why: 'hurt' | 'injured' }>\n\t/** What each siege unit was told to shoot, by unit id */\n\tsiege: Record<string, { target: number; since: number }>\n\t/** What each hero is on its way to buy, by hero id */\n\tshopping: Record<string, { shop: number; item: string; since: number }>\n\t/** Who is on their way to hire what, by the id of the unit sent: the place that hires, the unit type, since when */\n\thiring?: Record<string, { place: number; unit: string; since: number }>\n\t/** The chance of each hero plan as it was rolled, by its place in the list */\n\trolled: Record<string, boolean>\n}\n\n/**\n * The fights as the report shows them (`AiReport.micro`): each squad in one, its foes, its odds, whom it hits; the\n * units that fled; the heroes and what each learns next; who shops for what\n *\n * @beta\n */\nexport interface MicroReport {\n\tfights: {\n\t\tsquad: string\n\t\tfoes: number\n\t\todds: number\n\t\t/** Whom the squad hits: the foe, its type, since when */\n\t\ttarget?: { id: number; type: string; since: number }\n\t\t/** Its units that stepped back this think */\n\t\tkiting: number[]\n\t\t/** Its siege units told to shoot a building this think */\n\t\tsiege: number[]\n\t}[]\n\tfleeing: { unit: number; type: string; health: number; to: [number, number]; since: number; why: 'hurt' | 'injured' }[]\n\theroes: { id: number; type: string; level: number; next?: string }[]\n\tshopping: { hero: number; item: string; shop: number; since: number }[]\n\t/** Who is on their way to hire what: the unit sent, the place, the unit type, since when */\n\thiring: { by: number; place: number; unit: string; since: number }[]\n\t/** Abilities cast last think */\n\tcast: number\n\t/** Thinks whose fights it left alone, slips of its profile's `mistakes` */\n\tslipped?: number\n}\n\n/** The kit's rules of who is worth hitting first: casters, healers, heroes, siege; everyone else is worth 1 */\nconst DEFAULT_TARGETS: readonly TargetRule[] = [\n\t{ match: 'caster', weight: 2 },\n\t{ match: 'healer', weight: 2 },\n\t{ match: 'hero', weight: 1.5 },\n\t{ match: 'siege', weight: 1 }\n]\n\nconst percent = (share: number) => `${Math.round(share * 100)}%`\n\n/** A squad in a fight, as the module looks at it this think */\ninterface Fight {\n\tsquad: Squad\n\tunits: UnitSet\n\tmiddle: Vec2\n\tfoes: UnitSet\n\todds: number\n\ttarget?: EntityState\n\tkiting: number[]\n\tsiege: number[]\n}\n\n/** The parts of a think the module does, each once a think whoever asks first (the melee player's steps ask for some) */\ntype Part = 'fights' | 'spells' | 'items' | 'heroes'\n\n/**\n * A brain's micro (`ai.micro`): how its squads fight once in a fight, run by the `micro()` module each think after the\n * squads (`think`), and asked by whoever wants its judgement (`target`, `priority`, `nextHero`, `nextSkill`). Kept in\n * the brain's memory (`BrainMemory.micro`)\n *\n * @internal\n */\nexport class Micro implements AiArea {\n\t/** What finds it on a brain (`ai.area(Micro)`): made the first time a module asks for it */\n\tstatic readonly id = 'micro'\n\tstatic make(ai: Brain): Micro {\n\t\treturn new Micro(ai)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'micro'\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 how the computer player was fighting in a shape this brain does not read: it fights afresh'\n\n\t/** What the module was made with, under the brain's settings */\n\tprivate configured: MicroOptions = {}\n\t/** Whether a `micro()` module is in the brain: without one, nothing here runs by itself, and the squads fight as units do */\n\tenabled = false\n\tprivate memory: MicroMemory = { v: 1, focus: {}, kited: {}, fled: {}, siege: {}, shopping: {}, rolled: {} }\n\tprivate fights: Fight[] = []\n\tprivate cast = 0\n\t/** Thinks its fights were left alone, a slip of its profile's `mistakes` */\n\tprivate slipped = 0\n\tprivate thoughtAt: Partial<Record<Part, number>> = {}\n\n\tconstructor(\n\t\t/** The brain it fights for */\n\t\treadonly ai: Brain\n\t) {\n\t\tai.squads.define(FLEE)\n\t}\n\n\t/** Puts the `micro()` module's options under the brain's settings: what the module is made with */\n\tconfigure(options: MicroOptions): void {\n\t\tthis.configured = options\n\t\tthis.enabled = true\n\t}\n\n\t/** How it fights: the module's options, the brain's settings over them (`ai.settings.micro`: when units and heroes flee, the flags) */\n\tget options(): MicroOptions {\n\t\treturn this.ai.cache('micro.options', () => ({ ...this.configured, ...this.ai.settings.micro }))\n\t}\n\n\t/** Whether the module fights for a squad: one on a task that fights (`TaskDef.fighting`), not told to be left alone (`SquadOptions.micro`) */\n\tmanages(squad: Squad): boolean {\n\t\tconst state = squad.current\n\t\treturn (\n\t\t\tthis.enabled && squad.options.micro !== false && !!state && state.done === undefined && this.ai.squads.taskDef(state.kind)?.fighting !== false\n\t\t)\n\t}\n\n\t/**\n\t * The whole think: the fights (focus fire, kiting, siege, fleeing), those that fled coming back, the spells, the\n\t * items, the heroes' skills. Each part once a think: a part the melee player's steps asked for already is not done again\n\t */\n\tthink(): void {\n\t\t// a slip (its profile's `mistakes`, drawn with its own numbers): this think's fights left to the units themselves.\n\t\t// Drawn as the think begins, not again on a pass that goes on with the fights (`ai.budget`)\n\t\tconst mistakes = this.ai.profile.mistakes ?? 0\n\t\tif (!this.fighting && mistakes > 0 && this.ai.rng.next() < mistakes) {\n\t\t\tthis.slipped++\n\t\t\tthis.done('fights')\n\t\t}\n\t\tif (!this.fight()) return\n\t\tthis.spells()\n\t\tthis.items()\n\t\tthis.heroes()\n\t}\n\n\t/**\n\t * The fights: each squad in one looked at, its units told whom to hit, stepped back, sent to shoot buildings, sent to\n\t * safety; and the fled coming back. The squads are looked at as many a tick as the budget has room for (F2,\n\t * `ai.budget`): false where it stopped for the tick with squads to go, to go on at the next over the same picture\n\t */\n\tfight(): boolean {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tif (!this.fighting) {\n\t\t\tif (!this.begin('fights')) return true\n\t\t\tthis.prune()\n\t\t\tthis.fights = []\n\t\t\t// what is remembered of squads that are no more, or out of their fight\n\t\t\tconst focused = this.memory.focus\n\t\t\tfor (const name in focused) {\n\t\t\t\tconst squad = ai.squads.named(name)\n\t\t\t\tif (!squad || !this.manages(squad)) delete focused[name]\n\t\t\t}\n\t\t\tthis.fighting = { squads: view.hostile.alive().length ? [...ai.squads.all()].filter((squad) => this.manages(squad)) : [], at: 0 }\n\t\t}\n\t\tconst hostile = view.hostile.alive()\n\t\tconst { squads } = this.fighting\n\t\tfor (; this.fighting.at < squads.length; this.fighting.at++) {\n\t\t\tconst looked = this.fightOf(squads[this.fighting.at], hostile)\n\t\t\tif (!ai.budget.spent(looked || 1) && this.fighting.at + 1 < squads.length) {\n\t\t\t\tthis.fighting.at++\n\t\t\t\tai.budget.later()\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tthis.fighting = undefined\n\t\tthis.injured()\n\t\tthis.back()\n\t\treturn true\n\t}\n\n\t/** One squad's fight, if it is in one: its units told whom to hit, stepped back, sent at buildings, sent to safety. Gives how many units were looked at */\n\tprivate fightOf(squad: Squad, hostile: UnitSet): number {\n\t\tconst { view } = this.ai\n\t\tconst focused = this.memory.focus\n\t\tconst units = squad.units()\n\t\tconst middle = units.centre()\n\t\tif (!middle) return 0\n\t\t// what the squad fights: the hostile units near it, and the buildings that shoot (a tower); not what sleeps\n\t\tconst foes = hostile.near(middle, FIGHT_REACH).where((entity, def) => !entity.asleep && (def.kind === 'unit' || !!def.attacks?.length))\n\t\tif (!foes.length) {\n\t\t\tdelete focused[squad.name]\n\t\t\treturn units.length\n\t\t}\n\t\tconst fight: Fight = { squad, units, middle, foes, odds: view.strength.odds(units, foes), kiting: [], siege: [] }\n\t\tthis.fights.push(fight)\n\t\tthis.flee(fight)\n\t\t// those that fled are out of the squad now: what follows orders the rest\n\t\tfight.units = squad.units()\n\t\tif (!fight.units.length) return units.length\n\t\tthis.siegeOf(fight)\n\t\tthis.kite(fight)\n\t\tthis.focus(fight)\n\t\treturn units.length\n\t}\n\n\t/** The squads still to be looked at for a fight this think, where a pass stopped for the tick's budget, and the next of them */\n\tprivate fighting: { squads: Squad[]; at: number } | undefined\n\n\t// ---- focus fire\n\n\t/**\n\t * How much a foe is worth hitting: what its type declares (`UnitTypeDef.ai.priority`, 1 when it says nothing) times\n\t * one and the weights of the rules that pick it out (`targets`, the kit's when none are given)\n\t */\n\tpriority(foe: EntityState): number {\n\t\tconst { view } = this.ai\n\t\tconst def = view.def(foe)\n\t\tlet worth = 1\n\t\tconst rules = Array.isArray(this.options.targets) ? this.options.targets : DEFAULT_TARGETS\n\t\tfor (const rule of rules) {\n\t\t\tif (rule.match === 'hero' && this.options.targetHeroes === false && !Array.isArray(this.options.targets)) continue\n\t\t\tif (!this.matches(rule.match, foe, def)) continue\n\t\t\tif (rule.when !== undefined && !evaluate(rule.when, this.ai)) continue\n\t\t\tworth += rule.weight ?? 1\n\t\t}\n\t\treturn (def.ai?.priority ?? 1) * worth\n\t}\n\n\t/** Whether a rule's word picks a foe out: `building`, a role, a tag, a type */\n\tprivate matches(match: string, foe: EntityState, def: UnitTypeDef): boolean {\n\t\tif (match === 'building') return def.kind === 'building'\n\t\tconst { roles } = this.ai.view\n\t\treturn foe.type === match || roles.has(foe.type, match) || roles.hasTag(foe.type, match)\n\t}\n\n\t/**\n\t * Whom a squad in a fight hits: the foe worth most (`priority`), the weakest among those alike (what falls soonest\n\t * deals no more damage), the nearest among those alike too; or what the game's picker says (`targets` as a function)\n\t */\n\ttarget(squad: Squad, foes: UnitSet): EntityState | undefined {\n\t\tif (typeof this.options.targets === 'function') return this.options.targets(this.ai, squad, foes)\n\t\tconst prey = this.preyOf(squad, foes)\n\t\tif (prey) return prey\n\t\tconst middle = squad.centre()\n\t\tif (!middle || !foes.length) return undefined\n\t\tlet best: EntityState | undefined\n\t\tlet most = -Infinity\n\t\tfor (const foe of foes) {\n\t\t\tconst stats = this.ai.view.strength.statsOf(foe)\n\t\t\tconst health = Math.max(0, Math.min(1, foe.hp / Math.max(1, foe.maxHp ?? stats.health)))\n\t\t\t// the nearest among those alike: a little, so that the weakest is still the weakest\n\t\t\tconst near = 1 - 0.2 * Math.min(1, Math.sqrt(distSq(foe, middle)) / FIGHT_REACH)\n\t\t\tconst score = this.priority(foe) * (2 - health) * near\n\t\t\tif (score > most) {\n\t\t\t\tmost = score\n\t\t\t\tbest = foe\n\t\t\t}\n\t\t}\n\t\treturn best\n\t}\n\n\t/**\n\t * What the squad's task wants hit first, where it is among the foes: a harass's worker (`TaskState.memory.prey`). The\n\t * task names it and the micro module, fighting for the squad, sends the order: one of them, not both, or the units are\n\t * told the same twice\n\t */\n\tprivate preyOf(squad: Squad, foes: UnitSet): EntityState | undefined {\n\t\tconst prey = squad.current?.memory.prey\n\t\treturn typeof prey === 'number' ? foes.find((foe) => foe.id === prey) : undefined\n\t}\n\n\t/**\n\t * All of a squad on one rival: chosen again once it fell or every `focusEvery` seconds, the units within reach of it\n\t * told to attack it, and then, queued, to go on with the squad's errand. The healers are left to their spells, the\n\t * siege to its buildings, what stepped back this think to its step\n\t */\n\tprivate focus(fight: Fight): void {\n\t\tconst { ai } = this\n\t\tconst { squad, foes, units } = fight\n\t\tconst every = (this.options.focusEvery ?? FOCUS_EVERY) * ai.session.tickRate\n\t\tconst kept = this.memory.focus[squad.name]\n\t\tconst current = kept && foes.find((foe) => foe.id === kept.target)\n\t\t// the task's prey (a harass's worker) goes before the one kept\n\t\tconst prey = this.preyOf(squad, foes)\n\t\tif (current && ai.tick - kept.since < every && (!prey || prey.id === current.id)) {\n\t\t\tfight.target = current\n\t\t\treturn\n\t\t}\n\t\tconst target = this.target(squad, foes)\n\t\tif (!target) {\n\t\t\tdelete this.memory.focus[squad.name]\n\t\t\treturn\n\t\t}\n\t\tthis.memory.focus[squad.name] = { target: target.id, since: ai.tick }\n\t\tfight.target = target\n\t\t// chosen again as it was: what attacks already is left to it (told again, a unit at it stops and starts), and what\n\t\t// casts to its spell; the rest (idle, or walking on with the squad's errand) told\n\t\tconst again = kept?.target === target.id\n\t\t// the defend task picks one foe for the squad too: told whom, it sends only what stands idle after it\n\t\tif (squad.current?.kind === 'defend') squad.current.memory.foe = target.id\n\t\tconst { roles } = ai.view\n\t\tconst reach = FIGHT_REACH * FIGHT_REACH\n\t\t// what a unit is told, as a key: one at it already since another squad told it (its goal changed) is not told again\n\t\tconst told = orderKey({ type: 'attack', entities: [], point: point(target), target: target.id })\n\t\t// told it already: at it in the picture, or told since the picture was made (a pass of the fights over the same\n\t\t// picture, `ai.budget`), which the picture cannot show yet\n\t\tconst toldAlready = (unit: EntityState) => {\n\t\t\tconst sent = ai.sentTo(unit.id)\n\t\t\treturn !!sent && sent.key === told && (unit.own?.order === 'attack' || sent.tick >= ai.snapshot.tick)\n\t\t}\n\t\tconst hitters = units.filter(\n\t\t\t(unit) =>\n\t\t\t\tdistSq(unit, target) < reach &&\n\t\t\t\t!unit.own?.hidden &&\n\t\t\t\t!roles.has(unit.type, 'healer') &&\n\t\t\t\t!fight.kiting.includes(unit.id) &&\n\t\t\t\t!fight.siege.includes(unit.id) &&\n\t\t\t\t!(again && (unit.own?.order === 'attack' || unit.own?.order === 'cast')) &&\n\t\t\t\t!toldAlready(unit)\n\t\t)\n\t\tif (!hitters.length) return\n\t\tconst entities = hitters.map((unit) => unit.id)\n\t\tai.send({ type: 'attack', entities, point: point(target), target: target.id })\n\t\tconst on = ai.squads.whereOf(squad) ?? fight.middle\n\t\tai.send({ type: 'attack', entities, point: point(on), queue: true })\n\t}\n\n\t// ---- kiting\n\n\t/**\n\t * The ranged units of a squad closed on by melee they can outrun step back as far as their reach, within the squad's\n\t * spread, then go on with the fight: no more than once every few seconds each, and not when the squad is losing (it\n\t * falls back, or fights to the last)\n\t */\n\tprivate kite(fight: Fight): void {\n\t\tconst kite = this.options.kite ?? 'ranged'\n\t\tif (kite === false || fight.odds < KITE_ODDS) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { roles } = view\n\t\tconst every = KITE_EVERY * ai.session.tickRate\n\t\tconst melee = fight.foes.where((_, def) => def.kind === 'unit' && !!def.attacks?.length && !def.attacks.some((attack) => attack.projectileSpeed))\n\t\tif (!melee.length) return\n\t\tconst spread = fight.squad.spread() + KITE_LEASH\n\t\tconst { width, depth } = ai.session.terrain\n\t\tconst on = ai.squads.whereOf(fight.squad) ?? fight.middle\n\t\tfor (const unit of fight.units) {\n\t\t\tif (!roles.hasTag(unit.type, 'ranged') || unit.own?.hidden) continue\n\t\t\tconst last = this.memory.kited[unit.id]\n\t\t\tif (last !== undefined && ai.tick - last < every) continue\n\t\t\t// the melee foe nearest it, and whether it is upon it\n\t\t\tlet closest: EntityState | undefined\n\t\t\tlet closestAt = Infinity\n\t\t\tfor (const foe of melee) {\n\t\t\t\tconst d = distSq(unit, foe)\n\t\t\t\tif (d < closestAt) {\n\t\t\t\t\tclosestAt = d\n\t\t\t\t\tclosest = foe\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!closest) continue\n\t\t\tconst theirs = view.strength.statsOf(closest)\n\t\t\tconst close = farthestReach(view.def(closest), theirs) + KITE_CLOSE\n\t\t\tif (closestAt > close * close) continue\n\t\t\tconst mine = view.strength.statsOf(unit)\n\t\t\t// only from what it can outrun\n\t\t\tif (mine.moveSpeed < theirs.moveSpeed * KITE_FASTER) continue\n\t\t\tconst range = farthestReach(view.def(unit), mine)\n\t\t\tconst step = Math.max(2, range - 1)\n\t\t\tconst dx = unit.x - closest.x\n\t\t\tconst dz = unit.z - closest.z\n\t\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\t\tlet to = { x: unit.x + (dx / length) * step, z: unit.z + (dz / length) * step }\n\t\t\t// no further from the squad than its spread: a squad that kites stays a squad\n\t\t\tconst fromMiddle = Math.sqrt(distSq(to, fight.middle))\n\t\t\tif (fromMiddle > spread) {\n\t\t\t\tto = {\n\t\t\t\t\tx: fight.middle.x + ((to.x - fight.middle.x) / fromMiddle) * spread,\n\t\t\t\t\tz: fight.middle.z + ((to.z - fight.middle.z) / fromMiddle) * spread\n\t\t\t\t}\n\t\t\t}\n\t\t\tto = { x: Math.min(width - 1, Math.max(1, to.x)), z: Math.min(depth - 1, Math.max(1, to.z)) }\n\t\t\tif (distSq(to, unit) < 1.5 * 1.5) continue\n\t\t\tthis.memory.kited[unit.id] = ai.tick\n\t\t\tfight.kiting.push(unit.id)\n\t\t\tai.send({ type: 'order', entities: [unit.id], order: { type: 'move', point: to } })\n\t\t\tai.send({ type: 'attack', entities: [unit.id], point: point(on), queue: true })\n\t\t}\n\t}\n\n\t// ---- siege\n\n\t/**\n\t * The siege units of a squad shoot buildings when there are any in their reach and no foe is upon them, and one\n\t * that got ahead of the squad's middle is sent behind it: artillery is for walls, and dies to whatever reaches it\n\t */\n\tprivate siegeOf(fight: Fight): void {\n\t\tif (this.options.smartArtillery === false) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst siege = fight.units.withRole('siege')\n\t\tif (!siege.length) return\n\t\tconst every = SIEGE_EVERY * ai.session.tickRate\n\t\tconst threats = fight.foes.units()\n\t\tconst buildings = view.hostile.alive().buildings()\n\t\tconst on = ai.squads.whereOf(fight.squad) ?? fight.middle\n\t\tfor (const unit of siege) {\n\t\t\tif (unit.own?.hidden) continue\n\t\t\tconst kept = this.memory.siege[unit.id]\n\t\t\tconst threatened = threats.near(unit, SIEGE_THREATENED).length > 0\n\t\t\tif (threatened) {\n\t\t\t\tdelete this.memory.siege[unit.id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst range = farthestReach(view.def(unit), view.strength.statsOf(unit)) + 2\n\t\t\tconst near = buildings.near(unit, range).visible()\n\t\t\tconst current = kept && near.find((building) => building.id === kept.target)\n\t\t\tif (near.length && (!current || ai.tick - kept.since >= every)) {\n\t\t\t\t// a tower first: it shoots back; then the nearest\n\t\t\t\tconst target =\n\t\t\t\t\tnear.filter((building) => !!view.def(building).attacks?.length).sort((a, b) => distSq(a, unit) - distSq(b, unit))[0] ?? near.nearest(unit)!\n\t\t\t\tif (!current || current.id !== target.id) {\n\t\t\t\t\tthis.memory.siege[unit.id] = { target: target.id, since: ai.tick }\n\t\t\t\t\tai.send({ type: 'attack', entities: [unit.id], point: point(target), target: target.id })\n\t\t\t\t\tai.send({ type: 'attack', entities: [unit.id], point: point(on), queue: true })\n\t\t\t\t\tai.decide(`${unit.type} ${unit.id} turns to the ${target.type} at ${where(target)}`, { kind: 'micro' })\n\t\t\t\t} else this.memory.siege[unit.id].since = ai.tick\n\t\t\t\tfight.siege.push(unit.id)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (current) fight.siege.push(unit.id)\n\t\t\t// ahead of the middle, towards the foes: back behind it\n\t\t\tconst foe = threats.nearest(unit)\n\t\t\tif (!foe) continue\n\t\t\tconst ahead = Math.sqrt(distSq(fight.middle, foe)) - Math.sqrt(distSq(unit, foe))\n\t\t\tif (ahead <= 2 || (kept && ai.tick - kept.since < every)) continue\n\t\t\tconst dx = fight.middle.x - foe.x\n\t\t\tconst dz = fight.middle.z - foe.z\n\t\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\t\tconst to = { x: fight.middle.x + (dx / length) * SIEGE_BEHIND, z: fight.middle.z + (dz / length) * SIEGE_BEHIND }\n\t\t\tthis.memory.siege[unit.id] = { target: 0, since: ai.tick }\n\t\t\tfight.siege.push(unit.id)\n\t\t\tai.send({ type: 'order', entities: [unit.id], order: { type: 'move', point: to } })\n\t\t\tai.send({ type: 'attack', entities: [unit.id], point: point(on), queue: true })\n\t\t}\n\t}\n\n\t// ---- fleeing\n\n\t/** The share of its health under which a unit leaves a fight: heroes and units each their own; none for one that never does */\n\tprivate fleeAt(unit: EntityState): number | undefined {\n\t\tconst hero = this.ai.view.hasRole(unit, 'hero')\n\t\tconst at = hero ? (this.options.heroesFlee ?? 0.35) : (this.options.unitsFlee ?? 0.25)\n\t\treturn at === false || !(at > 0) ? undefined : at\n\t}\n\n\t/** How much of its health a unit has, 0 to 1 */\n\tprivate healthOf(unit: EntityState): number {\n\t\tconst stats = this.ai.view.strength.statsOf(unit)\n\t\treturn Math.max(0, Math.min(1, unit.hp / Math.max(1, unit.maxHp ?? stats.health)))\n\t}\n\n\t/** The units of a squad in a fight about to die leave it for safety */\n\tprivate flee(fight: Fight): void {\n\t\tfor (const unit of fight.units) {\n\t\t\tconst at = this.fleeAt(unit)\n\t\t\tif (at === undefined || unit.own?.hidden) continue\n\t\t\tif (this.healthOf(unit) >= at) continue\n\t\t\t// in the fight itself: a foe upon it\n\t\t\tif (!fight.foes.some((foe) => distSq(unit, foe) <= ENGAGED * ENGAGED)) continue\n\t\t\tthis.sendToSafety(unit, fight.squad, 'hurt')\n\t\t}\n\t}\n\n\t/** With `removeInjuries`, the hurt units with something to heal them go home between fights */\n\tprivate injured(): void {\n\t\tif (!this.options.removeInjuries) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst back = this.options.returnAt ?? 0.8\n\t\tconst hostile = view.hostile.alive()\n\t\tfor (const squad of ai.squads.all()) {\n\t\t\tif (!this.manages(squad) || this.fights.some((fight) => fight.squad === squad)) continue\n\t\t\tfor (const unit of squad.units()) {\n\t\t\t\tif (unit.own?.hidden || this.healthOf(unit) >= back) continue\n\t\t\t\tif (view.strength.statsOf(unit).healthRegen <= 0) continue\n\t\t\t\tif (hostile.near(unit, FIGHT_REACH).length) continue\n\t\t\t\tthis.sendToSafety(unit, squad, 'injured')\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Where a unit is safe: the nearest of its own finished buildings that no enemy strength reaches, else any of them,\n\t * else home, else away from the foes\n\t */\n\tprivate safety(unit: EntityState, foes: UnitSet): Vec2 {\n\t\tconst { view } = this.ai\n\t\tconst buildings = view.mine.buildings().finished()\n\t\tlet best: EntityState | undefined\n\t\tlet bestAt = Infinity\n\t\tlet safe = false\n\t\tfor (const building of buildings) {\n\t\t\tconst quiet = view.threat.at(building).enemy === 0\n\t\t\tif (safe && !quiet) continue\n\t\t\tconst d = distSq(unit, building)\n\t\t\tif ((quiet && !safe) || d < bestAt) {\n\t\t\t\tbest = building\n\t\t\t\tbestAt = d\n\t\t\t\tsafe = quiet\n\t\t\t}\n\t\t}\n\t\tif (best) return point(best)\n\t\tconst home = view.home()\n\t\tif (home) return point(home)\n\t\tconst foe = foes.nearest(unit)\n\t\tconst dx = foe ? unit.x - foe.x : 1\n\t\tconst dz = foe ? unit.z - foe.z : 0\n\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\tconst { width, depth } = this.ai.session.terrain\n\t\treturn {\n\t\t\tx: Math.min(width - 1, Math.max(1, unit.x + (dx / length) * FLEE_AWAY)),\n\t\t\tz: Math.min(depth - 1, Math.max(1, unit.z + (dz / length) * FLEE_AWAY))\n\t\t}\n\t}\n\n\t/** Takes a unit out of its squad into the `fleeing` squad and sends it to safety; the squad's task goes on without it */\n\tprivate sendToSafety(unit: EntityState, from: Squad, why: 'hurt' | 'injured'): void {\n\t\tconst { ai } = this\n\t\tconst to = this.safety(unit, ai.view.hostile.alive())\n\t\tconst fleeing = ai.squads.named(FLEEING) ?? ai.squads.make(FLEEING, [], { owner: OWNER, retreatAt: false, regroupWhen: false, micro: false })\n\t\tif (!fleeing.current) fleeing.task(FLEE.id)\n\t\tfleeing.add([unit.id], why === 'hurt' ? 'fled' : 'sent to heal')\n\t\tif (!fleeing.data.units.includes(unit.id)) return\n\t\tthis.memory.fled[unit.id] = { squad: from.name, since: ai.tick, to, why }\n\t\tconst state = fleeing.current!\n\t\tif (state.phase === 'starting') {\n\t\t\t// made empty, it began with no one to send: on its way now\n\t\t\tstate.phase = 'fleeing'\n\t\t\tstate.phaseSince = ai.tick\n\t\t}\n\t\t;(state.memory.to as Record<string, Vec2>) ??= {}\n\t\t;(state.memory.to as Record<string, Vec2>)[unit.id] = to\n\t\tai.send({ type: 'order', entities: [unit.id], order: { type: 'move', point: to } })\n\t\tai.decide(\n\t\t\twhy === 'hurt'\n\t\t\t\t? `${unit.type} ${unit.id} flees at ${percent(this.healthOf(unit))} to ${where(to)}`\n\t\t\t\t: `${unit.type} ${unit.id} goes to heal at ${where(to)}: ${percent(this.healthOf(unit))}`,\n\t\t\t{ kind: 'micro' }\n\t\t)\n\t}\n\n\t/**\n\t * Those that fled come back: at `returnAt` of their health, or, with nothing to heal them (or healing too slowly to\n\t * wait for: `HEAL_WAIT`) and `ignoreInjured` not set, once safe for a while, to the pool at home. Back to the squad they left when it is still there, sent to it; else to the pool\n\t */\n\tprivate back(): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst fleeing = ai.squads.named(FLEEING)\n\t\tif (!fleeing) {\n\t\t\tthis.memory.fled = {}\n\t\t\treturn\n\t\t}\n\t\tconst back = this.options.returnAt ?? 0.8\n\t\tconst hostile = view.hostile.alive()\n\t\tconst state = fleeing.current\n\t\tfor (const unit of fleeing.units()) {\n\t\t\tconst fled = this.memory.fled[unit.id]\n\t\t\tconst health = this.healthOf(unit)\n\t\t\tconst healed = health >= back\n\t\t\tconst stats = view.strength.statsOf(unit)\n\t\t\tconst slow = stats.healthRegen <= 0 || ((back - health) * stats.health) / stats.healthRegen > HEAL_WAIT\n\t\t\t// one nothing heals in good time is back once safe a while, but to the pool at home, not to the fight it fled\n\t\t\tlet safe = false\n\t\t\tif (!healed && !this.options.ignoreInjured && slow) {\n\t\t\t\tconst since = fled?.since ?? fleeing.current?.since ?? ai.tick\n\t\t\t\tsafe = ai.tick - since >= FLEE_SAFE * ai.session.tickRate && !hostile.near(unit, FIGHT_REACH).length\n\t\t\t}\n\t\t\tif (!healed && !safe) continue\n\t\t\tfleeing.remove([unit.id], 'back')\n\t\t\tif (state) delete (state.memory.to as Record<string, Vec2> | undefined)?.[unit.id]\n\t\t\tdelete this.memory.fled[unit.id]\n\t\t\tconst squad = healed && fled?.squad ? ai.squads.named(fled.squad) : undefined\n\t\t\tif (squad && squad.alive && !squad.idle) {\n\t\t\t\tsquad.add([unit.id], 'back from fleeing')\n\t\t\t\tconst join = squad.centre() ?? ai.squads.whereOf(squad)\n\t\t\t\tif (squad.data.units.includes(unit.id) && join) ai.send({ type: 'attack', entities: [unit.id], point: point(join) })\n\t\t\t\tai.decide(`${unit.type} ${unit.id} back with ${squad.name} at ${percent(health)}`, { kind: 'micro' })\n\t\t\t} else ai.decide(`${unit.type} ${unit.id} back at ${percent(health)}`, { kind: 'micro' })\n\t\t}\n\t\tif (!fleeing.data.units.length) fleeing.disband('no one fleeing')\n\t}\n\n\t// ---- spells\n\n\t/**\n\t * Has units use the abilities that have to be aimed, where there is a fight near them: the brain's say first\n\t * (`spells`), then the ability's own (`AbilityDef.ai`), then what the kit works out from the effects (`aim`). The\n\t * ones on autocast look after themselves\n\t */\n\tspells(): void {\n\t\tif (!this.begin('spells')) return\n\t\tthis.cast = 0\n\t\tif (this.options.spells === false) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { registry } = view\n\t\t// whatever fights it, creeps too: a spell is as good on a camp\n\t\tconst enemies = view.hostile.units().alive()\n\t\tif (!enemies.length) return\n\t\tconst friends = view.all\n\t\t\t.visible()\n\t\t\t.units()\n\t\t\t.where((entity, def) => !view.isHostile(entity) && !!def.attacks?.length)\n\t\tfor (const caster of view.mine) {\n\t\t\tif (!caster.own?.abilities?.length || caster.own.hidden || caster.own.order === 'cast') continue\n\t\t\tif (!enemies.near(caster, 12).length) continue\n\t\t\tfor (const state of caster.own.abilities) {\n\t\t\t\tconst ability = registry.ability(state.id)\n\t\t\t\tif (state.level < 1 || state.cooldown > 0 || state.charges === 0 || ability.target === 'passive' || state.autocast) continue\n\t\t\t\tif (at(ability.manaCost, state.level) > (caster.mana ?? 0)) continue\n\t\t\t\t// some reach as far as the caster's attacks do\n\t\t\t\tconst attacks = ability.attackRange ? view.strength.statsOf(caster).attackRange : 0\n\t\t\t\tconst foes = enemies.near(caster, at(ability.range, state.level) + attacks + 4).items\n\t\t\t\tconst near = friends.near(caster, 12).items\n\t\t\t\tconst aim = this.aim(caster, ability, state.level, foes, near)\n\t\t\t\tif (!aim) continue\n\t\t\t\tai.send({ type: 'cast', entities: [caster.id], ability: ability.id, point: point(aim.point), target: aim.target })\n\t\t\t\tthis.cast++\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Where to use an ability, or nothing when there is nothing worth it: the brain's `spells`, the ability's `ai`, then\n\t * from its effects (a heal on the friend hurt most, something harmful on the nearest, an area where it catches most)\n\t */\n\taim(\n\t\tcaster: EntityState,\n\t\tability: AbilityDef,\n\t\tlevel: number,\n\t\tenemies: readonly EntityState[],\n\t\tfriends: readonly EntityState[]\n\t): { point: Vec2; target?: number } | undefined {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { registry } = view\n\t\tconst own = this.options.spells && this.options.spells[ability.id]\n\t\tif (own) {\n\t\t\tconst decided = own(ai, caster, enemies, friends, level)\n\t\t\tif (decided !== undefined) return decided ?? undefined\n\t\t}\n\t\tif (ability.ai) {\n\t\t\tconst decided = ability.ai(\n\t\t\t\t{ snapshot: ai.snapshot, registry, playerId: ai.playerId, enemies: [...enemies], friends: [...friends] },\n\t\t\t\tcaster,\n\t\t\t\tlevel\n\t\t\t)\n\t\t\tif (decided !== undefined) return decided ?? undefined\n\t\t}\n\t\tconst harmful = (id?: string) => !!id && !!registry.buff(id).harmful\n\t\t// what a missile does counts as what the ability does\n\t\tconst effects = ability.effects.flatMap((effect) => [effect, ...(anyEffect(effect).effects ?? [])])\n\t\tconst hurts = effects.some((effect) => effect.type === 'damage' || (effect.type === 'buff' && harmful(effect.buff)))\n\t\t// only those it can get at: on the ground, in the air\n\t\tconst layers = ability.targets?.layers ?? ability.effects.find((effect) => effect.layers)?.layers\n\t\tif (layers) enemies = enemies.filter((enemy) => layers.includes(view.def(enemy).flying ? 'air' : 'ground'))\n\t\tconst heals = ability.effects.find((effect) => effect.type === 'heal')\n\t\tconst area = ability.effects.reduce((max, effect) => Math.max(max, at(effect.radius, level)), 0)\n\t\tconst maxHp = (entity: EntityState) => entity.maxHp ?? baseStats(view.def(entity), registry).health\n\t\tconst nearest = (candidates: readonly EntityState[]) => {\n\t\t\tlet best: EntityState | undefined\n\t\t\tlet bestAt = Infinity\n\t\t\tfor (const candidate of candidates) {\n\t\t\t\tconst d = distSq(caster, candidate)\n\t\t\t\tif (d < bestAt) {\n\t\t\t\t\tbestAt = d\n\t\t\t\t\tbest = candidate\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best\n\t\t}\n\n\t\tif (ability.target === 'unit') {\n\t\t\tif (heals) {\n\t\t\t\t// not wasted on a scratch\n\t\t\t\tconst need = at(heals.amount, level) * 0.6\n\t\t\t\tconst hurt = friends\n\t\t\t\t\t.filter((friend) => friend.id !== caster.id && maxHp(friend) - friend.hp >= need)\n\t\t\t\t\t.sort((a, b) => a.hp / maxHp(a) - b.hp / maxHp(b))[0]\n\t\t\t\treturn hurt && { point: hurt, target: hurt.id }\n\t\t\t}\n\t\t\tif (hurts) {\n\t\t\t\tconst target = nearest(enemies)\n\t\t\t\treturn target && { point: target, target: target.id }\n\t\t\t}\n\t\t\tconst buff = ability.effects.find((effect) => effect.type === 'buff')?.buff\n\t\t\tconst target = friends.find((friend) => !friend.buffs?.includes(buff ?? ''))\n\t\t\treturn target && { point: target, target: target.id }\n\t\t}\n\n\t\tif (ability.target === 'direction') {\n\t\t\tconst missile = ability.effects.find((effect) => effect.type === 'missile')\n\t\t\tconst reach = at(missile?.distance, level, 10)\n\t\t\tconst target = nearest(enemies)\n\t\t\treturn target && distSq(caster, target) <= reach * reach ? { point: { x: target.x, z: target.z } } : undefined\n\t\t}\n\n\t\tif (hurts) {\n\t\t\t// an area is worth it when it catches a few\n\t\t\tconst centres = ability.target === 'none' ? [caster] : enemies\n\t\t\tconst reach = area || 3\n\t\t\tconst need = ability.requiresLevel ? 4 : 2\n\t\t\tlet best: EntityState | undefined\n\t\t\tlet most = need - 1\n\t\t\tfor (const centre of centres) {\n\t\t\t\tconst caught = enemies.filter((enemy) => distSq(centre, enemy) <= reach * reach).length\n\t\t\t\tif (caught > most) {\n\t\t\t\t\tmost = caught\n\t\t\t\t\tbest = centre\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best && { point: { x: best.x, z: best.z } }\n\t\t}\n\t\t// something for the caster itself: when there is a fight\n\t\treturn enemies.some((enemy) => distSq(caster, enemy) < 64) ? { point: caster } : undefined\n\t}\n\n\t// ---- items\n\n\t/** Has units drink their potions when they need them, pick up what lies around, and heroes shop for what their list says */\n\titems(): void {\n\t\tif (!this.begin('items')) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { registry } = view\n\t\tconst potions = this.options.potions !== false\n\t\tconst takeItems = this.options.takeItems !== false\n\t\tconst hostile = view.hostile.alive()\n\t\tfor (const hero of view.mine) {\n\t\t\tconst inventory = hero.own && snapshotOf(hero, inventorySlots)?.slots\n\t\t\tif (!inventory || hero.own?.hidden) continue\n\t\t\tconst stats = view.strength.statsOf(hero)\n\t\t\tconst maxHp = hero.maxHp ?? stats.health\n\t\t\tconst maxMana = hero.maxMana ?? stats.mana\n\t\t\tif (potions) {\n\t\t\t\tlet drank = false\n\t\t\t\tfor (const slot of inventory) {\n\t\t\t\t\tconst ability = slot && registry.item(slot.item).ability\n\t\t\t\t\t// one waiting, or with none of its uses left (GP5), is not to be drunk now\n\t\t\t\t\tif (!slot || !ability || slot.cooldown > 0 || slot.uses === 0) continue\n\t\t\t\t\tconst effects = registry.ability(ability).effects\n\t\t\t\t\tconst heals = effects.some((effect) => effect.type === 'heal')\n\t\t\t\t\tconst restores = effects.some((effect) => effect.type === 'mana')\n\t\t\t\t\tif ((heals && hero.hp < maxHp * DRINK_HEALTH) || (restores && maxMana > 0 && (hero.mana ?? 0) < maxMana * DRINK_MANA)) {\n\t\t\t\t\t\tai.send({ type: 'order', entities: [hero.id], order: { type: 'cast', item: slot.id } })\n\t\t\t\t\t\tdrank = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (drank) continue\n\t\t\t}\n\t\t\tif (hero.own?.order) continue\n\t\t\tif (takeItems && inventory.includes(null)) {\n\t\t\t\tlet lying: (typeof view.items)[number] | undefined\n\t\t\t\tlet lyingAt = PICK_UP * PICK_UP\n\t\t\t\tfor (const item of view.items) {\n\t\t\t\t\tconst d = distSq(item, hero)\n\t\t\t\t\tif (d < lyingAt) {\n\t\t\t\t\t\tlyingAt = d\n\t\t\t\t\t\tlying = item\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (lying) {\n\t\t\t\t\tai.send({ type: 'order', entities: [hero.id], order: { type: 'pickUp', item: lying.id } })\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.shop(hostile)\n\t\tthis.hire(hostile)\n\t}\n\n\t/** What a hero shops for: its plan's list, the brain's, or the kit's (the cheapest item whose ability heals, when it carries none) */\n\tprivate wanted(hero: EntityState): string | undefined {\n\t\tconst { ai } = this\n\t\tconst { registry } = ai.view\n\t\tconst plan = this.planOf(hero.type)\n\t\tconst list = plan?.items ?? this.options.shopping\n\t\tif (list === false) return undefined\n\t\tif (typeof list === 'function') return list(ai, hero)\n\t\tconst slots = snapshotOf(hero, inventorySlots)?.slots ?? []\n\t\tconst carried = (item: string) => slots.filter((slot) => slot?.item === item).length\n\t\tif (Array.isArray(list)) {\n\t\t\tfor (const line of list) {\n\t\t\t\tif (!registry.items.has(line.item)) continue\n\t\t\t\tif (carried(line.item) >= (line.count ?? 1)) continue\n\t\t\t\tif (line.when !== undefined && !evaluate(line.when, ai)) continue\n\t\t\t\treturn line.item\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t\t// the kit's: something that heals, one of it, the cheapest\n\t\tconst money = ai.purse.money\n\t\tconst heals = (def: { ability?: string }) =>\n\t\t\t!!def.ability && registry.abilities.has(def.ability) && registry.ability(def.ability).effects.some((effect) => effect.type === 'heal')\n\t\tif (slots.some((slot) => slot && heals(registry.item(slot.item)))) return undefined\n\t\tconst cheapest = registry.items\n\t\t\t.all()\n\t\t\t.filter((def) => heals(def) && (def.cost[money] ?? 0) > 0)\n\t\t\t.sort((a, b) => (a.cost[money] ?? 0) - (b.cost[money] ?? 0))[0]\n\t\treturn cheapest?.id\n\t}\n\n\t/**\n\t * Heroes with nothing to do walk to a shop in reach for what they want and buy it there: the money held in the purse\n\t * on the way, paid as the `buy` is sent. Not in a fight, not on an errand\n\t */\n\tprivate shop(hostile: UnitSet): void {\n\t\tif (this.options.buyItems === false) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { registry } = view\n\t\t// the types that sell first: no type looked up of every tree known\n\t\tconst selling = ai.cache('micro.selling', () => new Set(registry.units.all().flatMap((def) => (def.sells?.length ? [def.id] : []))))\n\t\tconst shops = new UnitSet(\n\t\t\tview,\n\t\t\tview.all.known().filter((entity) => selling.has(entity.type) && !!snapshotOf(entity, shopStock) && !view.isHostile(entity))\n\t\t)\n\t\tif (!shops.length) {\n\t\t\tthis.memory.shopping = {}\n\t\t\treturn\n\t\t}\n\t\tconst going = this.memory.shopping\n\t\tfor (const hero of view.mine.heroes()) {\n\t\t\tconst own = hero.own\n\t\t\tconst slots = own && snapshotOf(hero, inventorySlots)?.slots\n\t\t\tif (!own || !slots || own.hidden) continue\n\t\t\tconst squad = ai.squads.squadOf(hero)\n\t\t\tconst busy = (squad && !squad.idle) || hostile.near(hero, FIGHT_REACH).length > 0\n\t\t\tlet errand: MicroMemory['shopping'][string] | undefined = going[hero.id]\n\t\t\tif (errand && (busy || !slots.includes(null))) {\n\t\t\t\tdelete going[hero.id]\n\t\t\t\terrand = undefined\n\t\t\t}\n\t\t\tif (busy) continue\n\t\t\tif (!errand) {\n\t\t\t\tif (own.order || !slots.includes(null)) continue\n\t\t\t\tconst item = this.wanted(hero)\n\t\t\t\tif (!item || !registry.items.has(item)) continue\n\t\t\t\tconst def = registry.item(item)\n\t\t\t\tif (!ai.purse.affords(def.cost, 0, SHOPPING_PRIORITY)) continue\n\t\t\t\tconst selling = shops.where(\n\t\t\t\t\t(entity) => !!snapshotOf(entity, shopStock)!.find((stock) => stock.item === item && (stock.count === undefined || stock.count > 0))\n\t\t\t\t)\n\t\t\t\tconst shop = selling.near(hero, SHOP_REACH).nearest(hero)\n\t\t\t\tif (!shop) continue\n\t\t\t\terrand = going[hero.id] = { shop: shop.id, item, since: ai.tick }\n\t\t\t\tai.send({ type: 'order', entities: [hero.id], order: { type: 'move', point: point(shop) } })\n\t\t\t\tai.decide(`${hero.type} ${hero.id} goes to the ${shop.type} at ${where(shop)} for ${an(def.name || item)}`, { kind: 'micro' })\n\t\t\t}\n\t\t\tconst shop = view.byId(errand.shop)\n\t\t\tconst def = registry.item(errand.item)\n\t\t\tif (!shop || !snapshotOf(shop, shopStock)?.some((stock) => stock.item === errand!.item && (stock.count === undefined || stock.count > 0))) {\n\t\t\t\tdelete going[hero.id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst reach = AT_SHOP + view.def(shop).radius\n\t\t\tif (distSq(hero, shop) <= reach * reach) {\n\t\t\t\tdelete going[hero.id]\n\t\t\t\tif (!ai.purse.spend(def.cost, SHOPPING_PRIORITY)) continue\n\t\t\t\tai.send({ type: 'buy', shop: shop.id, item: errand.item, hero: hero.id })\n\t\t\t\tai.decide(`${hero.type} ${hero.id} buys ${an(def.name || errand.item)} at the ${shop.type}`, { kind: 'micro' })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// on its way: the money kept for it, and a hero that stopped short sent on\n\t\t\tai.purse.reserve(`micro.shopping:${hero.id}`, def.cost, SHOPPING_PRIORITY)\n\t\t\tif (!own.order && ai.tick - errand.since >= FLEE_RESEND * ai.session.tickRate) {\n\t\t\t\terrand.since = ai.tick\n\t\t\t\tai.send({ type: 'order', entities: [hero.id], order: { type: 'move', point: point(shop) } })\n\t\t\t}\n\t\t}\n\t}\n\n\t/** What it would hire at a place now, of what the place offers: its list's next, the function's, or the kit's (the strongest soldier for its price) */\n\tprivate toHire(offered: readonly UnitTypeDef[]): UnitTypeDef | undefined {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { hiring } = this.options\n\t\tif (hiring === false || !offered.length) return undefined\n\t\tif (typeof hiring === 'function') {\n\t\t\tconst id = hiring(ai, offered)\n\t\t\treturn id === undefined ? undefined : offered.find((def) => def.id === id)\n\t\t}\n\t\tif (Array.isArray(hiring)) {\n\t\t\tfor (const line of hiring) {\n\t\t\t\tconst def = offered.find((each) => each.id === line.unit)\n\t\t\t\tif (!def) continue\n\t\t\t\tif (view.mine.ofType(def.id).length >= (line.count ?? 1)) continue\n\t\t\t\tif (line.when !== undefined && !evaluate(line.when, ai)) continue\n\t\t\t\treturn def\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t\t// the kit's: no hero (the altar's), the strongest for its price, a few at the most, with money that would lie idle\n\t\tconst money = ai.purse.money\n\t\tconst soldiers = offered.filter((def) => !def.hero && view.hasRole(def.id, 'soldier'))\n\t\tconst hired = view.mine.where((entity) => soldiers.some((def) => def.id === entity.type)).length\n\t\tif (hired >= HIRING_MOST) return undefined\n\t\tconst worth = (def: UnitTypeDef) => view.strength.of(def) / Math.max(1, def.cost?.[money] ?? 0)\n\t\tconst best = [...soldiers].sort((a, b) => worth(b) - worth(a))[0]\n\t\treturn best && ai.purse.affords(best.cost ?? {}, HIRING_SPARE, HIRING_PRIORITY) ? best : undefined\n\t}\n\n\t/**\n\t * Mercenaries: with supply free, a hero with nothing to do (or else an idle fighter of no squad's) walks to a place\n\t * that hires in reach for what `toHire` says, the money held in the purse on the way and paid as the `hire` is sent.\n\t * Not in a fight, not on an errand\n\t */\n\tprivate hire(hostile: UnitSet): void {\n\t\tif (this.options.hireUnits === false || this.options.hiring === false) return\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst { registry } = view\n\t\t// the types that hire first: no type looked up of every tree known\n\t\tconst hiring = ai.cache('micro.hiring', () => new Set(registry.units.all().flatMap((def) => (def.hires?.length ? [def.id] : []))))\n\t\tif (!hiring.size) return\n\t\tconst places = new UnitSet(\n\t\t\tview,\n\t\t\tview.all.known().filter((entity) => hiring.has(entity.type) && entity.hp > 0 && !view.isHostile(entity))\n\t\t)\n\t\tconst going = (this.memory.hiring ??= {})\n\t\tif (!places.length) {\n\t\t\tthis.memory.hiring = {}\n\t\t\treturn\n\t\t}\n\t\tconst offeredAt = (place: EntityState) => (view.def(place).hires ?? []).filter((id) => registry.units.has(id)).map((id) => registry.unit(id))\n\t\tconst { me } = view\n\t\tconst busy = (unit: EntityState) => {\n\t\t\tconst squad = ai.squads.squadOf(unit)\n\t\t\treturn (squad && !squad.idle) || hostile.near(unit, FIGHT_REACH).length > 0\n\t\t}\n\t\t// errands under way: the money kept, the hire paid at the place, those that stopped short sent on\n\t\tfor (const [id, errand] of Object.entries(going)) {\n\t\t\tconst unit = view.byId(Number(id))\n\t\t\tconst place = view.byId(errand.place)\n\t\t\tif (!unit || !place || unit.hp <= 0 || busy(unit) || !(view.def(place).hires ?? []).includes(errand.unit)) {\n\t\t\t\tdelete going[id]\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst def = registry.unit(errand.unit)\n\t\t\tconst reach = AT_SHOP + view.def(place).radius\n\t\t\tif (distSq(unit, place) <= reach * reach) {\n\t\t\t\tdelete going[id]\n\t\t\t\tconst supply = def.supply ?? 0\n\t\t\t\tif ((supply > 0 && me.supplyUsed + supply > me.supplyCap) || !ai.purse.spend(def.cost ?? {}, HIRING_PRIORITY)) continue\n\t\t\t\tme.supplyUsed += supply\n\t\t\t\tai.send({ type: 'hire', shop: place.id, unit: errand.unit })\n\t\t\t\tai.decide(`hires ${an(def.name || errand.unit)} at the ${place.type}`, { kind: 'micro' })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tai.purse.reserve(`micro.hiring:${id}`, def.cost ?? {}, HIRING_PRIORITY)\n\t\t\tif (!unit.own?.order && ai.tick - errand.since >= FLEE_RESEND * ai.session.tickRate) {\n\t\t\t\terrand.since = ai.tick\n\t\t\t\tai.send({ type: 'order', entities: [unit.id], order: { type: 'move', point: point(place) } })\n\t\t\t}\n\t\t}\n\t\t// one errand at a time\n\t\tif (Object.keys(going).length) return\n\t\tconst idle = (unit: EntityState) => !!unit.own && !unit.own.hidden && !unit.own.order && !busy(unit)\n\t\tconst runners = [\n\t\t\t...view.mine.heroes().where(idle),\n\t\t\t...view.mine.fighters().where((unit, def) => !def.hero && idle(unit) && !ai.squads.squadOf(unit))\n\t\t]\n\t\tfor (const runner of runners) {\n\t\t\tconst place = places.near(runner, SHOP_REACH).nearest(runner)\n\t\t\tif (!place) continue\n\t\t\tconst def = this.toHire(offeredAt(place))\n\t\t\tif (!def) return\n\t\t\tconst supply = def.supply ?? 0\n\t\t\tif (supply > 0 && me.supplyUsed + supply > me.supplyCap) return\n\t\t\tif (!ai.purse.affords(def.cost ?? {}, 0, HIRING_PRIORITY)) return\n\t\t\tgoing[runner.id] = { place: place.id, unit: def.id, since: ai.tick }\n\t\t\tai.send({ type: 'order', entities: [runner.id], order: { type: 'move', point: point(place) } })\n\t\t\tai.decide(`${runner.type} ${runner.id} goes to the ${place.type} at ${where(place)} to hire ${an(def.name || def.id)}`, { kind: 'micro' })\n\t\t\treturn\n\t\t}\n\t}\n\n\t// ---- heroes\n\n\t/** The plan for a hero type, where the brain's `heroes` is a list */\n\tprivate planOf(type: string): HeroPlan | undefined {\n\t\treturn Array.isArray(this.options.heroes) ? this.options.heroes.find((plan) => plan.type === type) : undefined\n\t}\n\n\t/**\n\t * Which hero to make next of those that could be made (at an altar, of the player's race, not had): the first of the\n\t * brain's `heroes` that could be and whose chance came up, or what its function says; else the first candidate\n\t */\n\tnextHero(candidates: readonly UnitTypeDef[], had: readonly string[]): UnitTypeDef | undefined {\n\t\tconst free = candidates.filter((def) => !had.includes(def.id))\n\t\tif (!free.length) return undefined\n\t\tconst { heroes } = this.options\n\t\tif (typeof heroes === 'function') {\n\t\t\tconst picked = heroes(this.ai, free)\n\t\t\tif (picked === undefined) return undefined\n\t\t\treturn typeof picked === 'string' ? free.find((def) => def.id === picked) : picked\n\t\t}\n\t\tif (Array.isArray(heroes)) {\n\t\t\tfor (let i = 0; i < heroes.length; i++) {\n\t\t\t\tconst plan = heroes[i]\n\t\t\t\tconst def = free.find((each) => each.id === plan.type)\n\t\t\t\tif (!def) continue\n\t\t\t\tconst chance = plan.chance ?? 1\n\t\t\t\tif (chance < 1) {\n\t\t\t\t\t// rolled once, with the brain's numbers, and remembered: a save keeps the roll\n\t\t\t\t\tthis.memory.rolled[i] ??= this.ai.rng.next() < chance\n\t\t\t\t\tif (!this.memory.rolled[i]) continue\n\t\t\t\t}\n\t\t\t\treturn def\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t\treturn free[0]\n\t}\n\n\t/**\n\t * Which skill a hero learns next of those it may: its plan's order (the next line not yet learned to that level),\n\t * else the ultimate as soon as it can be had, else whatever is furthest behind\n\t */\n\tnextSkill(hero: EntityState, learnable: readonly LearnableInfo[], now = true): string | undefined {\n\t\tif (!learnable.length) return undefined\n\t\tconst plan = this.planOf(hero.type)\n\t\tif (typeof plan?.skills === 'function') return plan.skills(this.ai, hero, learnable)\n\t\tif (Array.isArray(plan?.skills)) {\n\t\t\tconst counted: Record<string, number> = {}\n\t\t\tfor (const id of plan.skills) {\n\t\t\t\tcounted[id] = (counted[id] ?? 0) + 1\n\t\t\t\tconst skill = learnable.find((each) => each.id === id)\n\t\t\t\t// learned to this line already: on to the next line\n\t\t\t\tif (!skill || skill.level >= counted[id]) continue\n\t\t\t\treturn skill.available || !now ? id : undefined\n\t\t\t}\n\t\t}\n\t\tconst may = now ? learnable.filter((skill) => skill.available) : [...learnable]\n\t\treturn may.sort((a, b) => a.maxLevel - b.maxLevel || a.level - b.level)[0]?.id\n\t}\n\n\t/** Has heroes put the points they have into their skills, in the order their plan says */\n\theroes(): void {\n\t\tif (!this.begin('heroes')) return\n\t\tconst { ai } = this\n\t\tfor (const hero of ai.view.mine.heroes()) {\n\t\t\tconst info = heroOfState(hero)\n\t\t\tif (!info?.points || !info.learnable || hero.own?.hidden) continue\n\t\t\tconst next = this.nextSkill(hero, info.learnable)\n\t\t\tif (!next) continue\n\t\t\tai.send({ type: 'learn', entity: hero.id, ability: next })\n\t\t\tai.decide(`${hero.type} ${hero.id} learns ${next}`, { kind: 'micro' })\n\t\t}\n\t}\n\n\t// ---- bookkeeping\n\n\t/** Whether a part of the think is still to be done this think: it is, once, for whoever asks first */\n\tprivate begin(part: Part): boolean {\n\t\tif (this.thoughtAt[part] === this.ai.tick) return false\n\t\tthis.thoughtAt[part] = this.ai.tick\n\t\treturn true\n\t}\n\n\t/** Marks a part of the think done: one a brain's own turn did itself, or left to the units (a slip) */\n\tdone(part: Part): void {\n\t\tthis.thoughtAt[part] = this.ai.tick\n\t}\n\n\t/** Drops what is remembered of units that are gone */\n\tprivate prune(): void {\n\t\tconst { view } = this.ai\n\t\tconst gone = (id: string) => !view.mine.has(Number(id))\n\t\tfor (const id in this.memory.kited) if (gone(id)) delete this.memory.kited[id]\n\t\tfor (const id in this.memory.siege) if (gone(id)) delete this.memory.siege[id]\n\t\tfor (const id in this.memory.fled) if (gone(id)) delete this.memory.fled[id]\n\t\tfor (const id in this.memory.shopping) if (gone(id)) delete this.memory.shopping[id]\n\t}\n\n\t/** The fights and the rest, as the report shows them */\n\treport(): MicroReport {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst fleeing = ai.squads.named(FLEEING)\n\t\tconst fled = this.memory.fled\n\t\treturn {\n\t\t\tfights: this.fights.map((fight) => {\n\t\t\t\tconst kept = this.memory.focus[fight.squad.name]\n\t\t\t\treturn {\n\t\t\t\t\tsquad: fight.squad.name,\n\t\t\t\t\tfoes: fight.foes.length,\n\t\t\t\t\todds: Math.round(fight.odds * 100) / 100,\n\t\t\t\t\t...(fight.target && kept && { target: { id: fight.target.id, type: fight.target.type, since: kept.since } }),\n\t\t\t\t\tkiting: [...fight.kiting],\n\t\t\t\t\tsiege: [...fight.siege]\n\t\t\t\t}\n\t\t\t}),\n\t\t\tfleeing: (fleeing?.units().items ?? []).map((unit) => ({\n\t\t\t\tunit: unit.id,\n\t\t\t\ttype: unit.type,\n\t\t\t\thealth: Math.round(this.healthOf(unit) * 100) / 100,\n\t\t\t\tto: pair(fled[unit.id]?.to ?? unit),\n\t\t\t\tsince: fled[unit.id]?.since ?? 0,\n\t\t\t\twhy: fled[unit.id]?.why ?? 'hurt'\n\t\t\t})),\n\t\t\theroes: view.mine.heroes().map((hero) => {\n\t\t\t\tconst info = heroOfState(hero)\n\t\t\t\tconst next = info?.learnable ? this.nextSkill(hero, info.learnable, false) : undefined\n\t\t\t\treturn { id: hero.id, type: hero.type, level: info?.level ?? 1, ...(next && { next }) }\n\t\t\t}),\n\t\t\tshopping: Object.entries(this.memory.shopping).map(([hero, errand]) => ({ hero: Number(hero), ...errand })),\n\t\t\thiring: Object.entries(this.memory.hiring ?? {}).map(([by, errand]) => ({ by: Number(by), ...errand })),\n\t\t\tcast: this.cast,\n\t\t\t...(this.slipped && { slipped: this.slipped })\n\t\t}\n\t}\n\n\t/** What it remembers, 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.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\treport.micro = this.report()\n\t}\n\n\tsave(): MicroMemory {\n\t\treturn structuredClone(this.memory)\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 MicroMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\tfocus: { ...(given.focus ?? {}) },\n\t\t\tkited: { ...(given.kited ?? {}) },\n\t\t\tfled: structuredClone(given.fled ?? {}),\n\t\t\tsiege: { ...(given.siege ?? {}) },\n\t\t\tshopping: structuredClone(given.shopping ?? {}),\n\t\t\t...(given.hiring && { hiring: structuredClone(given.hiring) }),\n\t\t\trolled: { ...(given.rolled ?? {}) }\n\t\t}\n\t\treturn true\n\t}\n}\n\n/**\n * The task of the `fleeing` squad: each of its units on its way to its own safety (`state.memory.to`, by unit id), those\n * that stopped short sent again; never over by itself: the micro module takes the units out as they heal\n */\nconst FLEE: TaskDef = defineTask('flee', {\n\tfighting: false,\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'fleeing'\n\t\tstate.phaseSince = ai.tick\n\t\tconst to = (state.memory.to as Record<string, Vec2> | undefined) ?? {}\n\t\tfor (const id of squad.data.units) if (to[id]) squad.order({ type: 'move', point: to[id] }, [id])\n\t},\n\tthink(_ai, squad, state) {\n\t\tif (!squad.mayResend()) return\n\t\tconst to = (state.memory.to as Record<string, Vec2> | undefined) ?? {}\n\t\tfor (const unit of squad.idleUnits()) {\n\t\t\tconst there = to[unit.id]\n\t\t\tif (there && distSq(unit, there) > FLEE_ARRIVE * FLEE_ARRIVE) squad.order({ type: 'move', point: there }, [unit.id])\n\t\t}\n\t},\n\thandles: ['retreat', 'regroup', 'reinforce']\n})\n\n/**\n * The micro module: the fights of the brain's squads each think, after the squads sent and watched their tasks\n * (`ai.micro.think`): focus fire, kiting, siege, fleeing and coming back, spells, items, the heroes' skills. With how it\n * fights where the brain's definition and the seat's options say nothing (`MicroOptions`)\n *\n * @beta\n */\nexport const micro = (options: MicroOptions = {}): AiModuleDef =>\n\tdefineModule('micro', (ai: Brain): AiModule => {\n\t\tai.area(Micro).configure(options)\n\t\treturn {\n\t\t\tid: 'micro',\n\t\t\tphase: 'fight',\n\t\t\tthink: () => ai.area(Micro).think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tmicro?: MicroMemory\n\t}\n}\n","import { baseStats } from '#engine/defs'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { consider, curve, defineGoal, type GoalDef } from './goals'\nimport type { UnitSet } from './view'\nimport { heroOfState } from '#engine/hero'\nimport { pair, point, where } from './geometry'\n\n/*\n * Scouting (AI plan, C3): going to look. What a computer knows of its rivals is what it saw (A3: their buildings stay\n * remembered, their army is where it was last seen), so a computer that looked once, early, plays the rest of the game\n * against a picture of minute two: it misses the expansion, the tech switch to flyers, the army gathering at the\n * corner. A player looks again and again; this is the computer doing the same:\n *\n * - **A plan of looks.** First their bases it was told of (the starts) and has not seen, one after the other, as the\n * old melee player did. Then, every `lookEvery` seconds, each place worth a look again: their bases as remembered,\n * the mines they would expand to (mines nobody of its own holds, nearer one of their bases than any of its own), and\n * where their army was last seen. A place is due once it has been out of sight `lookEvery` seconds; nothing is due\n * while it is in sight.\n * - **One scout.** The looks due go to one unit at a time, as a squad of one (`scout`) on a `scout` task over the\n * places, nearest first: a flying unit where it has one idle (it sees over walls and is not stopped by them), else\n * the fastest of its fighters with nothing to do that is no hero, else a worker. The same unit goes on to the next\n * round while it lives.\n * - **What it saw** is the knowledge's: the scout's sight brings structures, workers, the army and the tech in as any\n * unit's does, so scouting only has to be there.\n *\n * The plan is a goal on the brain's picker (`scout`, weight 0.3: anything more important takes the unit), so it never\n * fights the army for units. `scout: false` leaves it out (a mission's computer that knows where everything is), a\n * function says where to look (`scout: (ai) => points`). What it remembers (the scout, the rounds) is plain data in\n * the brain's memory (`BrainMemory.scouting`).\n */\n\n/** How near one of their bases a mine is to be a likely expansion of theirs, and not its own way */\nconst EXPANSION_REACH = 60\n/** How near a known building of theirs a start is seen: a base found where it was said to be */\nconst BASE_SEEN = 14\n/** How many places one round takes a scout to at most: the rest wait for the next */\nconst ROUND = 4\n\n/**\n * How a brain scouts (`BrainDef.scouting`, the seat's `AiOptions.scouting` over it, the `scouting()` module's own under\n * both). Data, but for the function form of `scout`\n *\n * @beta\n */\nexport interface ScoutingOptions {\n\t/** Seconds a place stays out of sight before it is worth a look again: 90 when left out */\n\tlookEvery?: number\n\t/**\n\t * Where to look: `false` nowhere (the goal is left out), a function for places of the game's own each think (in place\n\t * of the kit's plan). The kit's plan when left out\n\t */\n\tscout?: false | ((ai: Brain) => Vec2[])\n\t/** Whether the mines they would expand to are looked at: yes when left out */\n\texpansions?: boolean\n\t/** Whether where their army was last seen is looked at again: yes when left out */\n\tarmy?: boolean\n\t/** Whether a flying unit with nothing to do goes before the fastest on foot: yes when left out */\n\tflyers?: boolean\n\t/** Seconds into the game before the first look: 15 when left out */\n\tfrom?: number\n}\n\n/**\n * What the scouting remembers between thinks, as a save keeps it\n *\n * @beta\n */\nexport interface ScoutingMemory {\n\tv: 1\n\t/** The unit that scouts, while it lives: the same one goes on to the next round */\n\tscout?: number\n\t/** Rounds sent */\n\trounds: number\n\t/** The places of the round the scout is on, while it is */\n\tround?: Vec2[]\n\t/**\n\t * Places a scout was lost on the way to, and when: not due again for `lookEvery` seconds, as if looked at (a lost\n\t * scout says as much: what guards it is there). Never the same unit sent to die at their towers over and over (AI1)\n\t */\n\tlost?: { at: Vec2; tick: number }[]\n}\n\n/**\n * A place in the plan of looks: where, what kind of place it is, when it was last in sight\n *\n * @beta\n */\nexport interface Look {\n\tat: Vec2\n\t/** Their start not seen yet, their base, a mine they would expand to, where their army was, or a place the game names */\n\tkind: 'start' | 'base' | 'expansion' | 'army' | 'game'\n\t/** Seconds since it was last in sight: `Infinity` for never */\n\tsince: number\n\t/** Whether it is worth a look now */\n\tdue: boolean\n}\n\n/**\n * The scouting as the report shows it (`AiReport.scouting`): the plan of looks with how old each is, the scout, where\n * it goes\n *\n * @beta\n */\nexport interface ScoutingReport {\n\tlooks: { at: [number, number]; kind: Look['kind']; seen?: number; due: boolean }[]\n\tscout?: number\n\tgoing?: [number, number][]\n\trounds: number\n}\n\n/**\n * The id of the scouting's goal\n *\n * @beta\n */\nexport const SCOUT = 'scout'\n\n/**\n * A brain's scouting (`ai.scouting`): its plan of looks (`looks`), the scout it sends (`scoutFor`), through the `scout`\n * goal the `scouting()` module puts on the picker. Kept in the brain's memory (`BrainMemory.scouting`)\n *\n * @internal\n */\nexport class Scouting implements AiArea {\n\t/** What finds it on a brain (`ai.area(Scouting)`): made the first time a module asks for it */\n\tstatic readonly id = 'scouting'\n\tstatic make(ai: Brain): Scouting {\n\t\treturn new Scouting(ai)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'scouting'\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 scouting in a shape this brain does not read: it starts afresh'\n\n\t/** Whether a `scouting()` module is in the brain: without one, nothing here runs, and the goal is not the brain's */\n\tenabled = false\n\tprivate memory: ScoutingMemory = { v: 1, rounds: 0 }\n\tprivate moduleOptions: ScoutingOptions = {}\n\t/** The goal it scouts through: added to the brain's picker by the module, unless told not to scout */\n\treadonly goal: GoalDef\n\n\tconstructor(\n\t\t/** The brain it scouts for */\n\t\treadonly ai: Brain\n\t) {\n\t\tthis.goal = this.makeGoal()\n\t}\n\n\t/** Puts the `scouting()` module's options under the brain's settings, and its goal on the picker */\n\tconfigure(options: ScoutingOptions): void {\n\t\tthis.moduleOptions = options\n\t\tif (!this.enabled && this.options.scout !== false) this.ai.goals.add(this.goal)\n\t\tthis.enabled = true\n\t}\n\n\t/** How it scouts: the module's options, the brain's settings over them (`ai.settings.scouting`) */\n\tget options(): ScoutingOptions {\n\t\treturn this.ai.cache('scouting.options', () => ({ ...this.moduleOptions, ...this.ai.settings.scouting }))\n\t}\n\n\t/** Seconds a place stays out of sight before it is due again */\n\tget lookEvery(): number {\n\t\treturn this.options.lookEvery ?? 90\n\t}\n\n\t/** The scout's unit, while it lives */\n\tget scout(): number | undefined {\n\t\treturn this.memory.scout\n\t}\n\n\t/**\n\t * Their starts it was told of (`AiOptions.enemyBases`) not seen yet: not looked at, and no building of theirs known\n\t * near (a creep's hut is no base)\n\t */\n\tunseenStarts(): Vec2[] {\n\t\tconst { ai } = this\n\t\tconst bases = ai.options.enemyBases ?? []\n\t\tconst knows = ai.def.knowledge !== false\n\t\tif (!knows) return bases.map(point)\n\t\tconst { map, enemy } = ai.knowledge\n\t\tconst rivals = enemy.structures({ gone: true })\n\t\tconst reach = BASE_SEEN * BASE_SEEN\n\t\treturn bases.filter((base) => map.lastLooked(base) === undefined && !rivals.some((building) => distSq(building.at, base) < reach)).map(point)\n\t}\n\n\t/**\n\t * The plan of looks, once a think: their starts not seen (due at once), then their bases as remembered, the mines they\n\t * would expand to, where their army was last seen, each due once out of sight `lookEvery` seconds. A game's own\n\t * places (`scout` as a function) in place of all of it\n\t */\n\tlooks(): Look[] {\n\t\tconst { ai } = this\n\t\treturn ai.cache('scouting.looks', () => {\n\t\t\tconst options = this.options\n\t\t\tconst every = this.lookEvery\n\t\t\tconst knows = ai.def.knowledge !== false\n\t\t\tconst lost = this.lostPlaces()\n\t\t\tconst reach = BASE_SEEN * BASE_SEEN\n\t\t\tconst since = (at: Vec2) => {\n\t\t\t\tconst looked = knows ? ai.knowledge.map.sinceLooked(at) : Infinity\n\t\t\t\tlet losing = Infinity\n\t\t\t\tfor (const each of lost) if (distSq(each.at, at) < reach) losing = Math.min(losing, (ai.tick - each.tick) / ai.session.tickRate)\n\t\t\t\treturn Math.min(looked, losing)\n\t\t\t}\n\t\t\tconst look = (at: Vec2, kind: Look['kind']): Look => {\n\t\t\t\tconst ago = since(at)\n\t\t\t\treturn { at: point(at), kind, since: ago, due: ago >= every }\n\t\t\t}\n\t\t\tif (typeof options.scout === 'function') return options.scout(ai).map((at) => look(at, 'game'))\n\t\t\tconst starts = this.unseenStarts()\n\t\t\tconst looks: Look[] = starts.map((at) => ({ at, kind: 'start', since: Infinity, due: true }))\n\t\t\tif (!knows) return looks\n\t\t\tconst { enemy } = ai.knowledge\n\t\t\tconst theirs = enemy.bases().filter((base) => !base.gone)\n\t\t\tfor (const base of theirs) looks.push(look(base.at, 'base'))\n\t\t\tconst told = ai.options.enemyBases ?? []\n\t\t\t// a start that was seen, with nothing remembered there now, is worth looking at again: they may have come back\n\t\t\tfor (const at of told)\n\t\t\t\tif (!starts.some((each) => each.x === at.x && each.z === at.z) && !theirs.some((base) => distSq(base.at, at) < BASE_SEEN * BASE_SEEN))\n\t\t\t\t\tlooks.push(look(at, 'base'))\n\t\t\tif (options.expansions ?? true) {\n\t\t\t\tconst mine = ai.view.bases()\n\t\t\t\tconst near = (at: Vec2, of: readonly Vec2[]) => of.reduce((best, each) => Math.min(best, distSq(each, at)), Infinity)\n\t\t\t\tconst centres = [...theirs.map((base) => base.at), ...told]\n\t\t\t\tconst candidates = ai.view\n\t\t\t\t\t.mines()\n\t\t\t\t\t.filter((each) => {\n\t\t\t\t\t\tif (theirs.some((base) => distSq(base.at, each) < BASE_SEEN * BASE_SEEN)) return false\n\t\t\t\t\t\tconst toThem = near(each, centres)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\ttoThem < EXPANSION_REACH * EXPANSION_REACH &&\n\t\t\t\t\t\t\ttoThem <\n\t\t\t\t\t\t\t\tnear(\n\t\t\t\t\t\t\t\t\teach,\n\t\t\t\t\t\t\t\t\tmine.map((base) => base.at)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\t\t\t\t.sort((a, b) => near(a, centres) - near(b, centres) || a.id - b.id)\n\t\t\t\tfor (const each of candidates.slice(0, 3)) looks.push(look(each, 'expansion'))\n\t\t\t}\n\t\t\tif (options.army ?? true) {\n\t\t\t\tconst army = enemy.armySeen()[0]\n\t\t\t\tif (army) looks.push(look(army.at, 'army'))\n\t\t\t}\n\t\t\treturn looks\n\t\t})\n\t}\n\n\t/**\n\t * The places scouts were lost on the way to, these `lookEvery` seconds: the round of a scout that died before it was\n\t * over taken in, once, as it is found gone\n\t */\n\tprivate lostPlaces(): readonly { at: Vec2; tick: number }[] {\n\t\tconst { ai } = this\n\t\tconst memory = this.memory\n\t\tif (memory.round && memory.scout !== undefined && !ai.view.mine.has(memory.scout)) {\n\t\t\tconst lost = (memory.lost ??= [])\n\t\t\tfor (const at of memory.round) lost.push({ at: point(at), tick: ai.tick })\n\t\t\tai.decide(`lost its scout on the way to ${memory.round.map(where).join(', ')}: not sent there again for ${this.lookEvery} s`, {\n\t\t\t\tkind: 'scout',\n\t\t\t\tgoal: SCOUT\n\t\t\t})\n\t\t\tdelete memory.round\n\t\t\tdelete memory.scout\n\t\t} else if (memory.round && !this.out()) delete memory.round\n\t\tconst every = this.lookEvery * ai.session.tickRate\n\t\tif (memory.lost?.some((each) => ai.tick - each.tick >= every)) memory.lost = memory.lost.filter((each) => ai.tick - each.tick < every)\n\t\treturn memory.lost ?? []\n\t}\n\n\t/** The looks due now, nearest a place first, each after the one before: the round a scout is sent on */\n\tround(from: Vec2): Vec2[] {\n\t\tconst due = this.looks().filter((each) => each.due)\n\t\t// their starts first, in the order told; the rest a walk from one to the nearest next\n\t\tconst starts = due.filter((each) => each.kind === 'start').map((each) => each.at)\n\t\tif (starts.length) return starts.slice(0, 1)\n\t\tconst rest = due.map((each) => each.at)\n\t\tconst round: Vec2[] = []\n\t\tlet at = from\n\t\twhile (rest.length && round.length < ROUND) {\n\t\t\tlet best = 0\n\t\t\tfor (let i = 1; i < rest.length; i++) if (distSq(rest[i], at) < distSq(rest[best], at)) best = i\n\t\t\tat = rest.splice(best, 1)[0]\n\t\t\tround.push(at)\n\t\t}\n\t\treturn round\n\t}\n\n\t/**\n\t * Who goes to look, of what it may have: the scout of the last round, while it is there; else a flying unit with\n\t * nothing to do (`flyers`); else the fastest of its fighters with nothing to do that is no hero; else, only to find\n\t * a start of theirs not seen yet, a worker. Looking again (their base, an expansion, their army) waits for a fighter:\n\t * a worker sent into a base it knows is lost to its towers, and what chases it home comes into its own (AI1)\n\t */\n\tscoutFor(available: UnitSet): EntityState | undefined {\n\t\tconst { ai } = this\n\t\tconst kept = available.find((unit) => unit.id === this.memory.scout)\n\t\tif (kept) return kept\n\t\tconst { registry } = ai\n\t\tconst speed = (unit: EntityState) => baseStats(ai.view.def(unit), registry).moveSpeed\n\t\tconst fastest = (units: Iterable<EntityState>) => [...units].sort((a, b) => speed(b) - speed(a) || a.id - b.id)[0]\n\t\tconst idle = available.fighters().where((unit) => !unit.own?.order && !heroOfState(unit))\n\t\tif (this.options.flyers ?? true) {\n\t\t\tconst flyer = fastest(idle.withRole('air'))\n\t\t\tif (flyer) return flyer\n\t\t}\n\t\tconst fighter = fastest(idle)\n\t\tif (fighter || !this.unseenStarts().length) return fighter\n\t\t// a worker inside a mine is not told to go anywhere until it is out: one outside, not building\n\t\treturn fastest(available.workers().where((unit) => !unit.own?.hidden && unit.own?.order !== 'build' && unit.own?.order !== 'construct'))\n\t}\n\n\t/** The goal: worth 0.3 while a look is due, one unit claimed, a squad of one sent on the round */\n\tprivate makeGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: SCOUT,\n\t\t\tweight: 0.3,\n\t\t\tconsiderations: [\n\t\t\t\t// while its scout is out on a round, the round goes on\n\t\t\t\tconsider('looks due', () => (this.out() ? 1 : this.looks().filter((each) => each.due).length), curve.step(1)),\n\t\t\t\tconsider('seconds into the game', (ai) => ai.time, curve.step(this.options.from ?? 15))\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst unit = this.scoutFor(available)\n\t\t\t\t\treturn unit ? [unit] : []\n\t\t\t\t}\n\t\t\t},\n\t\t\trun: (_ai, claimed) => this.send(claimed.units.first())\n\t\t})\n\t}\n\n\t/** The scout's squad while it is on a round */\n\tprivate out(): boolean {\n\t\tconst squad = this.ai.squads.named(SCOUT)\n\t\treturn !!squad && squad.current?.kind === 'scout' && squad.done === undefined\n\t}\n\n\t/** Sends the scout on the round of looks due, unless it is on one */\n\tprivate send(unit: EntityState | undefined): void {\n\t\tconst { ai } = this\n\t\tif (!unit || this.out()) return\n\t\tconst round = this.round(unit)\n\t\tif (!round.length) return\n\t\tthis.memory.scout = unit.id\n\t\tthis.memory.round = round.map(point)\n\t\tthis.memory.rounds++\n\t\tai.squads.make(SCOUT, [unit], { micro: false, owner: this.goal.id }).scout(round)\n\t\tai.decide(`sends ${unit.type} ${unit.id} to look at ${round.map(where).join(', ')}`, { kind: 'scout', goal: SCOUT })\n\t}\n\n\t/** The scouting as the report shows it */\n\treport(): ScoutingReport {\n\t\tconst { ai } = this\n\t\tif (!this.enabled) return { looks: [], rounds: 0 }\n\t\tconst squad = ai.squads.named(SCOUT)\n\t\tconst points = squad?.current?.kind === 'scout' && squad.done === undefined ? (squad.current.data.points as Vec2[]) : undefined\n\t\tconst next = (squad?.current?.memory.next as number | undefined) ?? 0\n\t\treturn {\n\t\t\tlooks: this.looks().map((each) => ({\n\t\t\t\tat: pair(each.at),\n\t\t\t\tkind: each.kind,\n\t\t\t\t...(Number.isFinite(each.since) && { seen: Math.round(each.since) }),\n\t\t\t\tdue: each.due\n\t\t\t})),\n\t\t\t...(this.memory.scout !== undefined && ai.view.mine.has(this.memory.scout) && { scout: this.memory.scout }),\n\t\t\t...(points && { going: points.slice(next).map(pair) }),\n\t\t\trounds: this.memory.rounds\n\t\t}\n\t}\n\n\t/** What it remembers, 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.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\treport.scouting = this.report()\n\t}\n\n\tsave(): ScoutingMemory {\n\t\tconst { round, lost, ...rest } = this.memory\n\t\treturn {\n\t\t\t...rest,\n\t\t\t...(round && { round: round.map(point) }),\n\t\t\t...(lost && { lost: lost.map((each) => ({ at: point(each.at), tick: each.tick })) })\n\t\t}\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 ScoutingMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\trounds: given.rounds ?? 0,\n\t\t\t...(given.scout !== undefined && { scout: given.scout }),\n\t\t\t...(Array.isArray(given.round) && { round: given.round.map(point) }),\n\t\t\t...(Array.isArray(given.lost) && { lost: given.lost.map((each) => ({ at: point(each.at), tick: each.tick })) })\n\t\t}\n\t\treturn true\n\t}\n\n\t/** Takes in the scout of a save from before the module (the melee player kept it) */\n\tadopt(scout: number | undefined): void {\n\t\tif (scout !== undefined && this.memory.scout === undefined) this.memory.scout = scout\n\t}\n}\n\n/**\n * The scouting module: puts the `scout` goal on the brain's picker, which sends one unit at a time to look at what is\n * due (`ai.scouting`). With how it scouts where the brain's definition and the seat's options say nothing\n * (`ScoutingOptions`)\n *\n * @beta\n */\nexport const scouting = (options: ScoutingOptions = {}): AiModuleDef =>\n\tdefineModule('scouting', (ai: Brain): AiModule => {\n\t\tai.area(Scouting).configure(options)\n\t\treturn { id: 'scouting', phase: 'act', think: () => undefined }\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tscouting?: ScoutingMemory\n\t}\n}\n","import type { UnitTypeDef } from '#engine/defs'\nimport { Team } from './team'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { type AiCondition, evaluate } from './rules'\nimport type { Squad } from './squads'\nimport { pair, point, where } from './geometry'\n\n/*\n * Attack groups and waves (AI plan, D2): the classic RTS attack data, made general. The melee player's waves were \"the\n * ready units, two more each time\": no say in what a wave is made of, when it goes, or where. A game, a map or a\n * mission says it here, as data:\n *\n * - **An attack group** (`AttackGroup`) is what a wave is made of: so many of each unit type or role (`{ footman: 4,\n * rifleman: 2 }`, `{ caster: 1 }`).\n * - **A wave** (`AttackWave`) names its group (or gives one in place), and says when it goes (`after` seconds from the\n * last wave, or from the start for the first; and `when`, a condition: a wave whose condition does not hold when its\n * turn comes is skipped), how much of the group is enough (`minForces`, a share), how long it gathers at the rally\n * before it goes (`gatherFor`), whether it goes again (`repeat`: for ever, or so many times), whether it waits for\n * its team to go together (`together`, C5), and where it goes (`target`: their nearest base, their weakest, an\n * expansion of theirs, their army as last seen, a place, or a function).\n * - **The waves module** (`waves()`) works on the wave whose turn it is: its group becomes **wants** of the production\n * plan (B3: the units are trained, and the buildings they need put up, as wants are), and nothing else of the army is\n * trained meanwhile (the composition left aside: a wave of four footmen and two riflemen trains exactly that); once\n * enough of it stands idle in the pool and its time has come, it is made a squad (`wave 1`, `wave 2`, …) that\n * **gathers** at the rally and then **attacks** (C1's tasks), and the next wave's turn begins.\n * - **Without waves** the melee player makes its own, as it always did (`waveSize` growing by two, the nearest base):\n * the module is there, and idle.\n *\n * The data forms are JSON (a map's file, `MapPlayer.data.ai.waves`; a seat's `AiOptions.waves` and `groups`); the waves\n * as a function (`(ai, index) => wave`) make them as the game goes. What the module remembers (whose turn it is, how many\n * times it went, the waves sent) is plain data in the brain's memory (`BrainMemory.waves`). `{ wave: … }` in a condition\n * (B2) is the index of the wave whose turn it is.\n */\n\n/**\n * What a wave is made of: so many of each unit type (by id) or role (`caster`, a game's own), by name, under a condition\n *\n * @beta\n */\nexport interface AttackGroup {\n\t/** Its name: what a wave names it by */\n\tid: string\n\t/** So many of each unit type or role: `{ footman: 4, rifleman: 2 }` */\n\tunits: Record<string, number>\n\t/** Only while this holds: a wave of a group whose condition fails is skipped as its own would be */\n\twhen?: AiCondition\n}\n\n/**\n * Where a wave goes: their base nearest home, their weakest (the fewest towers and army seen there), an expansion of\n * theirs, their army as last seen, a place, or a function of the brain\n *\n * @beta\n */\nexport type WaveTarget = 'nearestBase' | 'weakestBase' | 'expansion' | 'army' | Vec2 | ((ai: Brain) => Vec2 | undefined)\n\n/**\n * One wave (the classic attack wave): its group, when it goes, how much of it is enough, how long it gathers, whether it\n * goes again, together or not, and where to\n *\n * @beta\n */\nexport interface AttackWave {\n\t/** Its group: a group's name (`WavesOptions.groups`), or the units in place (`{ footman: 4 }`) */\n\tgroup: string | Record<string, number>\n\t/** Seconds after the wave before it (after the start, for the first) before it may go: 0 when left out */\n\tafter?: number\n\t/** The share of its group that is enough to go with, 0 to 1: all of it when left out */\n\tminForces?: number\n\t/** Seconds it gathers at the rally before it goes, whoever is late: 15 when left out */\n\tgatherFor?: number\n\t/** Whether it goes again once sent: `true` for ever, a number for so many times in all. Once when left out */\n\trepeat?: boolean | number\n\t/** Only when this holds as its turn comes: a wave whose condition fails is skipped */\n\twhen?: AiCondition\n\t/** Whether it waits for its team's attack together (`TeamOptions.together`, C5) */\n\ttogether?: boolean\n\t/** Where it goes: their base nearest home when left out */\n\ttarget?: WaveTarget\n\t/** Where it gathers: a place, or a name the map or the rules gave. A little out of home towards the target when left out */\n\trally?: Vec2 | string\n}\n\n/**\n * How a brain sends its waves (`BrainDef.waves`; the seat's `AiOptions.waves` and `groups`, the data of it, go over)\n *\n * @beta\n */\nexport interface WavesOptions {\n\t/** The groups waves are made of, by name */\n\tgroups?: AttackGroup[]\n\t/** The waves, in order, or a function giving the wave whose turn it is (by its index), none for no more */\n\twaves?: AttackWave[] | ((ai: Brain, index: number) => AttackWave | undefined)\n\t/** Whether a wave's group is trained (wants of the production plan): yes when left out. No for units that are given (a lanes game) */\n\ttrain?: boolean\n\t/** How important a wave's units are to the purse, as wants: 30 when left out (under a hall, a barracks, a hero) */\n\tpriority?: number\n}\n\n/**\n * What the waves module remembers between thinks, as a save keeps it\n *\n * @beta\n */\nexport interface WavesMemory {\n\tv: 1\n\t/** The index of the wave whose turn it is: the waves sent and skipped before it */\n\tindex: number\n\t/** Where in the list it is (for a list), and how many times the wave there went */\n\tentry: number\n\twent: number\n\t/** The tick the last wave went at (or was skipped at): what the next one's `after` counts from */\n\tlast: number\n\t/** The waves sent, the last ten: index, squad, size, target, tick */\n\tsent: { index: number; squad: string; size: number; at: Vec2; tick: number }[]\n\t/** How many were skipped, their condition failing */\n\tskipped: number\n}\n\n/**\n * The waves as the report shows them (`AiReport.waves`): the wave whose turn it is, its group as it stands, when it may go;\n * the waves sent\n *\n * @beta\n */\nexport interface WavesReport {\n\tindex: number\n\tcurrent?: { units: Record<string, [free: number, wanted: number]>; in: number; ready: boolean; status: string }\n\tsent: { index: number; squad: string; size: number; at: [number, number]; tick: number }[]\n\tskipped: number\n}\n\n/** How far out of home towards the target a wave gathers, where it is not told */\nconst RALLY_OUT = 12\n/** How many sent waves the memory keeps */\nconst SENT_KEPT = 10\n/** The prefix of the wants of a wave's units, on the build plan */\nconst WANT = 'waves.'\n/** Whose the waves' squads are: their units held by the module until the wave is over */\nconst OWNER = 'waves'\n\n/**\n * A brain's waves (`ai.waves`): the wave whose turn it is (`current`), what it is made of and how far along, the waves\n * sent. Run by the `waves()` module each think; idle without waves given\n *\n * @internal\n */\nexport class Waves implements AiArea {\n\t/** What finds it on a brain (`ai.area(Waves)`): made the first time a module asks for it */\n\tstatic readonly id = 'waves'\n\tstatic make(ai: Brain): Waves {\n\t\treturn new Waves(ai)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'waves'\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 waves in a shape this brain does not read: they start afresh'\n\n\t/** Whether a `waves()` module is in the brain */\n\tenabled = false\n\tprivate memory: WavesMemory = { v: 1, index: 0, entry: 0, went: 0, last: 0, sent: [], skipped: 0 }\n\tprivate moduleOptions: WavesOptions = {}\n\tprivate thoughtAt = -1\n\tprivate status = 'no waves'\n\n\tconstructor(\n\t\t/** The brain it sends waves for */\n\t\treadonly ai: Brain\n\t) {}\n\n\t/**\n\t * Puts the `waves()` module's options under the brain's settings; and while it has waves to send, the production\n\t * plan's composition is left aside (what is trained is the waves' groups, wanted outright)\n\t */\n\tconfigure(options: WavesOptions): void {\n\t\tthis.moduleOptions = options\n\t\tthis.enabled = true\n\t\tconst { production } = this.ai.plans\n\t\tconst before = production.settings.composition\n\t\tproduction.configure({\n\t\t\tcomposition: ((brain: Brain) => {\n\t\t\t\tif (brain.area(Waves).active) return {}\n\t\t\t\treturn typeof before === 'function' ? before(brain) : before\n\t\t\t}) as (ai: Brain) => Record<string, number>\n\t\t})\n\t}\n\n\t/** How it sends waves: the module's options, the brain's settings over them (`ai.settings.waves`), the groups of both */\n\tget options(): WavesOptions {\n\t\tconst settings = this.ai.settings.waves\n\t\tconst groups = settings?.groups && this.moduleOptions.groups ? [...this.moduleOptions.groups, ...settings.groups] : undefined\n\t\treturn { ...this.moduleOptions, ...settings, ...(groups && { groups }) }\n\t}\n\n\t/** Whether it was given waves: the module is in the brain, and waves were given it (all sent, or some to go) */\n\tget given(): boolean {\n\t\treturn this.enabled && this.options.waves !== undefined\n\t}\n\n\t/** Whether it has waves to send: given waves, and one whose turn it is. The melee player makes its own otherwise */\n\tget active(): boolean {\n\t\treturn this.given && this.current() !== undefined\n\t}\n\n\t/** The index of the wave whose turn it is: the waves sent and skipped before it (`{ wave }` in a condition) */\n\tget index(): number {\n\t\treturn this.memory.index\n\t}\n\n\t/** The wave whose turn it is: none when there are no (more) waves */\n\tcurrent(): AttackWave | undefined {\n\t\tconst { waves } = this.options\n\t\tif (!waves) return undefined\n\t\tif (typeof waves === 'function') return waves(this.ai, this.memory.index)\n\t\treturn waves[this.memory.entry]\n\t}\n\n\t/** A wave's group as units by type or role: the group named, or the units given in place. None for a name not given */\n\tgroupOf(wave: AttackWave): AttackGroup | undefined {\n\t\tif (typeof wave.group !== 'string') return { id: `wave ${this.memory.index + 1}`, units: wave.group }\n\t\treturn this.options.groups?.find((group) => group.id === wave.group)\n\t}\n\n\t/**\n\t * Whether a unit counts as one of a key of a group: of the type by id where a type has the id, else of the role. A\n\t * key that is both (the fixture's `soldier`) is the type: an archer, a soldier by role, is not one of `soldier: 4`\n\t */\n\tprivate matches(unit: EntityState, key: string): boolean {\n\t\tif (this.ai.registry.units.has(key)) return unit.type === key\n\t\treturn this.ai.view.hasRole(unit, key)\n\t}\n\n\t/** The type trained for a key of a group: the type of that id, or the first of the role it can make */\n\tprivate typeFor(key: string): UnitTypeDef | undefined {\n\t\tconst { registry, view } = this.ai\n\t\tif (registry.units.has(key)) return registry.unit(key)\n\t\treturn view.typesOf(key).find((def) => def.kind === 'unit')\n\t}\n\n\t/** The units free for a wave: in the pool (nothing holds them), idle or on their way to nothing, fighters */\n\tprivate free(): EntityState[] {\n\t\treturn this.ai.squads\n\t\t\t.pool()\n\t\t\t.fighters()\n\t\t\t.where((unit) => unit.own?.order !== 'harvest').items as EntityState[]\n\t}\n\n\t/** For each key of the group, the free units that count as it, at most as many as wanted, each unit once */\n\tprivate chosen(group: AttackGroup): Map<string, EntityState[]> {\n\t\tconst taken = new Set<number>()\n\t\tconst by = new Map<string, EntityState[]>()\n\t\tconst free = this.free()\n\t\tfor (const [key, count] of Object.entries(group.units)) {\n\t\t\tconst units: EntityState[] = []\n\t\t\tfor (const unit of free) {\n\t\t\t\tif (units.length >= count) break\n\t\t\t\tif (taken.has(unit.id) || !this.matches(unit, key)) continue\n\t\t\t\ttaken.add(unit.id)\n\t\t\t\tunits.push(unit)\n\t\t\t}\n\t\t\tby.set(key, units)\n\t\t}\n\t\treturn by\n\t}\n\n\t/** Where a wave goes, as its target says: their base nearest home when it says nothing. None where nothing is known */\n\ttargetOf(wave: AttackWave): Vec2 | undefined {\n\t\tconst { ai } = this\n\t\tconst target = wave.target ?? 'nearestBase'\n\t\tif (typeof target === 'function') return target(ai)\n\t\tif (typeof target === 'object') return point(target)\n\t\tconst home = ai.view.home()\n\t\tconst from = home ? point(home) : { x: 0, z: 0 }\n\t\tconst knows = ai.def.knowledge !== false\n\t\tconst bases = knows ? ai.knowledge.enemy.bases().filter((base) => !base.gone) : []\n\t\tconst told = ai.options.enemyBases ?? []\n\t\tconst nearest = (places: readonly Vec2[]) =>\n\t\t\tplaces.reduce<Vec2 | undefined>((best, each) => (!best || distSq(each, from) < distSq(best, from) ? each : best), undefined)\n\t\tswitch (target) {\n\t\t\tcase 'army': {\n\t\t\t\tconst army = knows ? ai.knowledge.enemy.armySeen()[0] : undefined\n\t\t\t\tif (army) return point(army.at)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'expansion': {\n\t\t\t\tconst expansion = nearest(bases.filter((base) => base.expansion).map((base) => base.at))\n\t\t\t\tif (expansion) return point(expansion)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'weakestBase': {\n\t\t\t\t// the fewest of their buildings that shoot remembered there, and the least of their strength seen near it\n\t\t\t\tconst threat = ai.view.threat\n\t\t\t\tlet best: { at: Vec2; score: number } | undefined\n\t\t\t\tfor (const base of bases) {\n\t\t\t\t\tconst score = threat.at(base.at, { remembered: true }).enemy\n\t\t\t\t\tif (!best || score < best.score) best = { at: base.at, score }\n\t\t\t\t}\n\t\t\t\tif (best) return point(best.at)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tconst known = nearest(bases.map((base) => base.at))\n\t\tif (known) return point(known)\n\t\treturn told.length ? point(told[this.memory.index % told.length]) : undefined\n\t}\n\n\t/** Where a wave gathers: the place given (by name or as a point), or a little out of home towards its target */\n\trallyOf(wave: AttackWave, target: Vec2 | undefined): Vec2 | undefined {\n\t\tconst { ai } = this\n\t\tif (typeof wave.rally === 'string') {\n\t\t\tconst named = ai.view.named(wave.rally)\n\t\t\treturn named ? point(named) : undefined\n\t\t}\n\t\tif (wave.rally) return point(wave.rally)\n\t\tconst home = ai.view.home()\n\t\tif (!home) return undefined\n\t\tif (!target) return point(home)\n\t\tconst dx = target.x - home.x\n\t\tconst dz = target.z - home.z\n\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\treturn { x: home.x + (dx / length) * RALLY_OUT, z: home.z + (dz / length) * RALLY_OUT }\n\t}\n\n\t/**\n\t * The think, once a think: the wave whose turn it is skipped where its condition fails; its group wanted of the\n\t * production plan; once enough of it is free and its time has come, sent (a squad that gathers, then attacks), the\n\t * next wave's turn begun. Without waves, nothing\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\t// the waves that are done (cleared, fallen back, or wiped) let go of: their units back to the pool for the next\n\t\tfor (const squad of ai.squads.of(OWNER).squads) if (squad.idle) ai.squads.disband(squad, `wave over: ${squad.done ?? 'idle'}`)\n\t\tconst wave = this.current()\n\t\tif (!wave) {\n\t\t\tthis.dropWants()\n\t\t\tthis.status = this.options.waves ? 'no more waves' : 'no waves'\n\t\t\treturn\n\t\t}\n\t\tconst group = this.groupOf(wave)\n\t\tif (!group) {\n\t\t\tthis.status = `no group \"${String(wave.group)}\"`\n\t\t\tif (!this.warned) {\n\t\t\t\tthis.warned = true\n\t\t\t\tai.log.warn('ai', `a wave names the group \"${String(wave.group)}\", which no group is: it is skipped`)\n\t\t\t}\n\t\t\tthis.next(true)\n\t\t\treturn\n\t\t}\n\t\tif ((wave.when && !evaluate(wave.when, ai)) || (group.when && !evaluate(group.when, ai))) {\n\t\t\tai.decide(`skips wave ${this.memory.index + 1}: its condition does not hold`, { kind: 'waves' })\n\t\t\tthis.next(true)\n\t\t\treturn\n\t\t}\n\t\tconst chosen = this.chosen(group)\n\t\tif (this.options.train ?? true) this.want(group, chosen)\n\t\tconst total = Object.values(group.units).reduce((sum, count) => sum + count, 0)\n\t\tconst have = [...chosen.values()].reduce((sum, units) => sum + units.length, 0)\n\t\tconst enough = Math.max(1, Math.ceil(total * Math.min(1, Math.max(0, wave.minForces ?? 1))))\n\t\tconst due = this.memory.last + Math.round((wave.after ?? 0) * ai.session.tickRate)\n\t\tif (ai.tick < due) {\n\t\t\tthis.status = `waits ${Math.ceil((due - ai.tick) / ai.session.tickRate)} s more (${have} of ${total})`\n\t\t\treturn\n\t\t}\n\t\tif (have < enough) {\n\t\t\tthis.status = `builds up: ${have} of ${total}, ${enough} enough`\n\t\t\treturn\n\t\t}\n\t\tconst target = this.targetOf(wave)\n\t\tif (!target) {\n\t\t\tthis.status = 'nowhere to go'\n\t\t\treturn\n\t\t}\n\t\t// with its team, at the time the team's plan says (C5): the plan standing joined (one whose time went by unjoined\n\t\t// is too late to join), or a plan proposed; the wave waits for its time\n\t\tlet plan = wave.together && ai.area(Team).enabled ? ai.area(Team).plan : undefined\n\t\tif (wave.together && ai.area(Team).enabled) {\n\t\t\tif (plan && !plan.joined.includes(ai.playerId) && ai.tick >= plan.at) plan = undefined\n\t\t\tif (!plan) plan = ai.area(Team).propose(target)\n\t\t\telse if (!plan.joined.includes(ai.playerId)) ai.area(Team).join()\n\t\t\tif (ai.tick < plan.at) {\n\t\t\t\tthis.status = `waits for its team: goes in ${Math.ceil((plan.at - ai.tick) / ai.session.tickRate)} s`\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tthis.send(wave, chosen, plan?.target ?? target)\n\t\tthis.next(false)\n\t}\n\n\tprivate warned = false\n\n\t/** The group's units wanted of the production plan: as many more of each type as the free ones fall short of */\n\tprivate want(group: AttackGroup, chosen: Map<string, EntityState[]>): void {\n\t\tconst { ai } = this\n\t\tconst keys = new Set<string>()\n\t\tfor (const [key, count] of Object.entries(group.units)) {\n\t\t\tconst type = this.typeFor(key)\n\t\t\tif (!type) continue\n\t\t\tconst id = `${WANT}${key}`\n\t\t\tkeys.add(id)\n\t\t\tconst free = chosen.get(key)?.length ?? 0\n\t\t\t// those it has of the type, less the free ones counted, and the group's: what is out or busy stays out of it. A\n\t\t\t// number, worked out each think: plain data, so that a save keeps the want and a loaded game trains alike\n\t\t\tai.plans.want({\n\t\t\t\tid,\n\t\t\t\ttype: type.id,\n\t\t\t\tcount: ai.view.mine.ofType(type.id).length - free + count,\n\t\t\t\tpriority: this.options.priority ?? 30,\n\t\t\t\tby: `wave ${this.memory.index + 1}`\n\t\t\t})\n\t\t}\n\t\tfor (const want of ai.plans.build.list()) if (want.id?.startsWith(WANT) && !keys.has(want.id)) ai.plans.drop(want.id)\n\t}\n\n\t/** The wants of a wave's units let go of */\n\tprivate dropWants(): void {\n\t\tconst { ai } = this\n\t\tfor (const want of ai.plans.build.list()) if (want.id?.startsWith(WANT)) ai.plans.drop(want.id)\n\t}\n\n\t/** A wave sent: its units a squad that gathers at the rally, then attacks; said, noted, written down */\n\tprivate send(wave: AttackWave, chosen: Map<string, EntityState[]>, target: Vec2): Squad {\n\t\tconst { ai } = this\n\t\tconst units = [...chosen.values()].flat()\n\t\tconst index = this.memory.index + 1\n\t\tconst name = `wave ${index}`\n\t\tconst rally = this.rallyOf(wave, target) ?? target\n\t\tconst squad = ai.squads.make(name, units, { owner: OWNER })\n\t\tsquad.gather(rally, { minForces: wave.minForces ?? 1, seconds: wave.gatherFor ?? 15, then: { kind: 'attack', data: { at: point(target) } } })\n\t\tai.knowledge.own.attackSent(target, units.length)\n\t\tai.area(Team).say('attacking')\n\t\tconst sent = { index: this.memory.index, squad: name, size: units.length, at: point(target), tick: ai.tick }\n\t\tthis.memory.sent.push(sent)\n\t\tif (this.memory.sent.length > SENT_KEPT) this.memory.sent.splice(0, this.memory.sent.length - SENT_KEPT)\n\t\tconst made = [...chosen.entries()].filter(([, each]) => each.length).map(([key, each]) => `${each.length} ${key}`)\n\t\tai.decide(`sends wave ${index}: ${made.join(', ')}, gathering at ${where(rally)} for ${wave.gatherFor ?? 15} s, then at ${where(target)}`, {\n\t\t\tkind: 'waves'\n\t\t})\n\t\tthis.status = `sent ${name}`\n\t\treturn squad\n\t}\n\n\t/** On to the next wave's turn: the same again where it repeats, else the next of the list */\n\tprivate next(skipped: boolean): void {\n\t\tconst { memory } = this\n\t\tconst wave = this.current()\n\t\tmemory.index++\n\t\tmemory.last = this.ai.tick\n\t\tif (skipped) memory.skipped++\n\t\tconst repeat = skipped ? false : wave?.repeat\n\t\tmemory.went++\n\t\tif (repeat === true || (typeof repeat === 'number' && memory.went < repeat)) return\n\t\tmemory.entry++\n\t\tmemory.went = 0\n\t}\n\n\t/** The waves as the report shows them */\n\treport(): WavesReport {\n\t\tconst { ai } = this\n\t\tconst wave = this.enabled ? this.current() : undefined\n\t\tconst group = wave && this.groupOf(wave)\n\t\tconst chosen = group ? this.chosen(group) : undefined\n\t\tconst due = wave ? this.memory.last + Math.round((wave.after ?? 0) * ai.session.tickRate) : 0\n\t\treturn {\n\t\t\tindex: this.memory.index,\n\t\t\t...(wave &&\n\t\t\t\tgroup &&\n\t\t\t\tchosen && {\n\t\t\t\t\tcurrent: {\n\t\t\t\t\t\tunits: Object.fromEntries(Object.entries(group.units).map(([key, count]) => [key, [chosen.get(key)?.length ?? 0, count]])) as Record<\n\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t[number, number]\n\t\t\t\t\t\t>,\n\t\t\t\t\t\tin: Math.max(0, Math.ceil((due - ai.tick) / ai.session.tickRate)),\n\t\t\t\t\t\tready: this.status.startsWith('sent'),\n\t\t\t\t\t\tstatus: this.status\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\tsent: this.memory.sent.map((each) => ({ index: each.index, squad: each.squad, size: each.size, at: pair(each.at), tick: each.tick })),\n\t\t\tskipped: this.memory.skipped\n\t\t}\n\t}\n\n\t/** What it remembers, 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.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\tif (this.enabled) report.waves = this.report()\n\t}\n\n\tsave(): WavesMemory {\n\t\treturn structuredClone(this.memory)\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 WavesMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\tindex: given.index ?? 0,\n\t\t\tentry: given.entry ?? 0,\n\t\t\twent: given.went ?? 0,\n\t\t\tlast: given.last ?? 0,\n\t\t\tsent: structuredClone(given.sent ?? []),\n\t\t\tskipped: given.skipped ?? 0\n\t\t}\n\t\treturn true\n\t}\n}\n\n/**\n * The waves module: the wave whose turn it is, each think (`ai.waves.think`): its group wanted, sent once enough of it is\n * free and its time has come, gathering at the rally, then attacking. Idle without waves given. With how it sends waves\n * where the brain's definition and the seat's options say nothing (`WavesOptions`)\n *\n * @beta\n */\nexport const waves = (options: WavesOptions = {}): AiModuleDef =>\n\tdefineModule('waves', (ai: Brain): AiModule => {\n\t\tai.area(Waves).configure(options)\n\t\treturn {\n\t\t\tid: 'waves',\n\t\t\tphase: 'act',\n\t\t\tafter: ['goals'],\n\t\t\tbefore: ['squads'],\n\t\t\tthink: () => ai.area(Waves).think()\n\t\t}\n\t})\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\twaves?: WavesMemory\n\t}\n}\n","import { type UnitTypeDef, upgradesOf } from '#engine/defs'\nimport { Economy } from '../economy'\nimport { queueOf, upgradeOf } from '#engine/systems/productionQueue'\nimport type { Vec2 } from '#engine/math'\nimport { availableToPlayer } from '#engine/shared'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\nimport type { Want } from '#engine/ai/plans/build'\nimport { flagOf } from '#engine/ai/profiles'\nimport type { AiRole } from '#engine/ai/roles'\nimport { type AiConditionData, evaluate } from '#engine/ai/rules'\nimport { HALL_REACH } from '../reach'\n\n/*\n * What the melee player builds (AI plan, D3; the part of its turn that was `runConstruction`): a ladder of wants on\n * the brain's build plan (B3), most important first, as data (`MELEE_LADDER`) rather than code. Each rung names a\n * role (what the kit found the game's types are for, `roles.ts`) and how many of it, how important it is to the purse\n * (`priority`: a hall before a barracks before a workshop), what to keep spare for it, and when it holds. Two rungs\n * are worked out rather than looked up: `counter`, the building the best answer to their army needs (a blacksmith for\n * riflemen against flyers), and `tier`, the next tier of the hall. Supply is the production plan's (kept ahead of what\n * it trains), another hall by a free mine the economy's (`economy.expand`, 40), towers at a base raided often the\n * defence's. The plan works out the steps to each want (a blacksmith needs a barracks), the spots, the builders and\n * the purse, and builds anew what is lost. The wants stand (`keep`): they are set again each think with what it has\n * now in mind, and a game gives a ladder of its own (`build({ ladder })`) or leaves a rung out\n */\n\n/**\n * One rung of the melee player's ladder of wants: what to have, by role, how many, how important, money to spare,\n * when. `counter` and `tier` are worked out each think (the file's comment); any other role is the first type of it\n * the player can make\n *\n * @beta\n */\nexport interface MeleeWant {\n\t/** The want's id on the build plan (`melee.barracks`): what the report shows, what `without` leaves out */\n\tid: string\n\t/**\n\t * A role of the kit's (`hall`, `barracks`, `altar`, `workshop`, `tower`), or one worked out: `counter` (the\n\t * building its best answer to their army needs), `tier` (the next tier of its hall), `expand` (another hall by a\n\t * free mine once the mine at home runs low, FJ1)\n\t */\n\trole: AiRole | 'counter' | 'tier' | 'expand'\n\t/** How many of it to have: 1 when left out */\n\tcount?: number\n\t/** How important it is to the purse: a want of more goes first and may spend what is held for one of less */\n\tpriority: number\n\t/** Money to keep spare before it is paid for (a luxury waits until there is this much over its price) */\n\tspare?: number\n\t/** Only while this holds (`AiConditionData`): `{ units: { role: 'barracks' } }` for the next tier */\n\twhen?: AiConditionData\n}\n\n/**\n * The melee player's ladder as it stands: a hall, a barracks, another hall once the mine at home runs low, an altar,\n * the building its best answer needs, the next tier of its hall once a barracks stands (FJ1: before the workshop, so\n * that what the tier opens is trained while it matters), a workshop, a second barracks with money to spare\n *\n * @beta\n */\nexport const MELEE_LADDER: readonly MeleeWant[] = [\n\t{ id: 'melee.hall', role: 'hall', count: 1, priority: 100 },\n\t{ id: 'melee.barracks', role: 'barracks', count: 1, priority: 80 },\n\t// another hall by a free mine when the mine at home is running out (`expandAt`): past the economy's own expansion\n\t{ id: 'melee.expand', role: 'expand', priority: 70 },\n\t{ id: 'melee.altar', role: 'altar', count: 1, priority: 60 },\n\t{ id: 'melee.counter', role: 'counter', priority: 50, spare: 100 },\n\t{ id: 'melee.tier', role: 'tier', priority: 45, spare: 100, when: { units: { role: 'barracks' } } },\n\t// another hall by a free mine is the economy's want (`economy.expand`, priority 40)\n\t{ id: 'melee.workshop', role: 'workshop', count: 1, priority: 30, spare: 150 },\n\t{ id: 'melee.barracks2', role: 'barracks', count: 2, priority: 10, spare: 400 }\n]\n\n/**\n * How the melee brain builds (`build()` of the melee brain): its ladder of wants, and how much better an answer to\n * their army must be for its building to be put up\n *\n * @beta\n */\nexport interface MeleeBuildOptions {\n\t/** The ladder of wants, most important first: `MELEE_LADDER` when left out */\n\tladder?: readonly MeleeWant[]\n\t/** How much better a type must answer their armies than what it can train now, for the building it needs to be put up: 1.2 when left out */\n\tcounterMargin?: number\n\t/**\n\t * The part of what it held left in the mine at home under which another hall by a free mine is wanted (the `expand`\n\t * rung): 0.35 when left out. 0 for never\n\t */\n\texpandAt?: number\n}\n\n/** What the module remembers: where home first stood (Allow Home Changes off) */\ninterface MeleeBuildMemory {\n\tv: 1\n\thomeAt?: Vec2\n}\n\n/** What fights: a worker that builds does not, one that only gathers (a ghoul) does */\nconst isSoldier = (def: UnitTypeDef) => def.kind === 'unit' && !!def.attacks?.length && !(def.harvester && def.builds?.length) && !def.hero\n\n/**\n * The melee brain's build module: the ladder of wants set on the build plan each think, the counter and the tier\n * worked out, the plan thought. After the heroes, before the production and the picker, as the old turn had it;\n * `steps.construction` honoured\n *\n * @beta\n */\nexport const build = (options: MeleeBuildOptions = {}): AiModuleDef =>\n\tdefineModule('melee.build', (ai: Brain) => {\n\t\tconst ladder = options.ladder ?? MELEE_LADDER\n\t\tconst margin = options.counterMargin ?? 1.2\n\t\tconst expandAt = options.expandAt ?? 0.35\n\t\tconst module = {\n\t\t\tid: 'melee.build',\n\t\t\tphase: 'plan' as const,\n\t\t\tafter: ['economy', 'melee.heroes'],\n\t\t\tbefore: ['melee.production'],\n\t\t\t/** Where its home first stood: where its hall is built again when lost, where it may not move home */\n\t\t\thomeAt: undefined as Vec2 | undefined,\n\t\t\tthink: () => {\n\t\t\t\tif (ai.area(Economy).waiting) return\n\t\t\t\twants(ai, ladder, margin, expandAt, module)\n\t\t\t\tai.plans.build.think()\n\t\t\t},\n\t\t\tsave: (): MeleeBuildMemory => ({ v: 1, ...(module.homeAt && { homeAt: { x: module.homeAt.x, z: module.homeAt.z } }) }),\n\t\t\trestore: (data: unknown) => {\n\t\t\t\tconst given = data as MeleeBuildMemory | undefined\n\t\t\t\tif (given?.homeAt) module.homeAt = { x: given.homeAt.x, z: given.homeAt.z }\n\t\t\t}\n\t\t}\n\t\treturn module\n\t})\n\n/** The ladder as wants on the plan, with what it has now in mind */\nfunction wants(ai: Brain, ladder: readonly MeleeWant[], margin: number, expandAt: number, module: { homeAt: Vec2 | undefined }): void {\n\tconst { view } = ai\n\tconst plan = ai.plans.build\n\tconst by = 'melee'\n\t// where home first stood: a hall lost there is built again there, where it may not move home (Allow Home Changes off)\n\tconst home = view.home()\n\tif (home && !module.homeAt) module.homeAt = { x: home.x, z: home.z }\n\tconst stays = flagOf(ai, 'allowHomeChanges') === false ? module.homeAt : undefined\n\tfor (const rung of ladder) {\n\t\tconst base: Omit<Want, 'type'> = { id: rung.id, priority: rung.priority, keep: true, by, ...(rung.spare !== undefined && { spare: rung.spare }) }\n\t\tswitch (rung.role) {\n\t\t\tcase 'counter': {\n\t\t\t\t// what answers the rivals' armies best, where it cannot be trained yet: the building it needs (a blacksmith for\n\t\t\t\t// riflemen against flyers), with a little to spare\n\t\t\t\tconst wanted = counterNeeds(ai, margin)\n\t\t\t\tif (wanted) plan.want({ ...base, type: wanted.id, count: rung.count ?? 1, by: 'counters', ...(rung.when && { when: rung.when }) })\n\t\t\t\telse plan.drop(rung.id)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'expand': {\n\t\t\t\t// another hall by a free mine once the mine at home runs low: one more than it has, where there is a mine to take\n\t\t\t\tconst hall = view.typesOf('hall')[0]\n\t\t\t\tif (!hall || !mineLow(ai, expandAt)) {\n\t\t\t\t\tplan.drop(rung.id)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tplan.want({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: hall.id,\n\t\t\t\t\tcount: (brain) => brain.view.mine.buildings().withRole('hall').length + (rung.count ?? 1),\n\t\t\t\t\tby: 'expand',\n\t\t\t\t\twithin: HALL_REACH - 1,\n\t\t\t\t\tnear: () => ai.area(Economy).freeMine(),\n\t\t\t\t\twhen: (brain) => !!brain.area(Economy).freeMine() && (!rung.when || evaluate(rung.when, brain))\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'tier': {\n\t\t\t\t// the next tier of a hall, once there is an army to speak of\n\t\t\t\tconst hall = view.typesOf('hall')[0]\n\t\t\t\tconst tier =\n\t\t\t\t\thall &&\n\t\t\t\t\tview.mine\n\t\t\t\t\t\t.ofType(hall.id)\n\t\t\t\t\t\t.finished()\n\t\t\t\t\t\t.find((each) => upgradesOf(view.def(each)).length && !queueOf(each).length && !upgradeOf(each)?.to)\n\t\t\t\t// the first of what it may turn into, where it may turn into several\n\t\t\t\tconst next = tier && upgradesOf(view.def(tier))[0]\n\t\t\t\tif (next)\n\t\t\t\t\tplan.want({\n\t\t\t\t\t\t...base,\n\t\t\t\t\t\ttype: next,\n\t\t\t\t\t\tcount: view.mine.ofType(next).length + (rung.count ?? 1),\n\t\t\t\t\t\tby: 'tier',\n\t\t\t\t\t\t...(rung.when && { when: rung.when })\n\t\t\t\t\t})\n\t\t\t\telse plan.drop(rung.id)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst type = view.typesOf(rung.role)[0]\n\t\t\t\tif (!type) {\n\t\t\t\t\tplan.drop(rung.id)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tplan.want({\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: type.id,\n\t\t\t\t\tcount: rung.count ?? 1,\n\t\t\t\t\t...(rung.when && { when: rung.when }),\n\t\t\t\t\t...(rung.role === 'hall' && stays && { near: stays })\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Whether the mine at home is running low: of the money's deposits by its home base in sight, what is left together\n * under `ratio` of what they held (the type's `resource.amount`). No while none is in sight\n */\nfunction mineLow(ai: Brain, ratio: number): boolean {\n\tif (ratio <= 0) return false\n\tconst { view } = ai\n\tconst home = view.bases()[0]\n\tif (!home) return false\n\tconst money = view.registry.currency ?? view.registry.resources[0]?.id\n\tif (!money) return false\n\tlet held = 0\n\tlet left = 0\n\tfor (const deposit of view.resourcesNear(home)) {\n\t\tif (!deposit.visible || deposit.resource === undefined) continue\n\t\tconst def = view.def(deposit)\n\t\tif (def.resource?.kind !== money) continue\n\t\theld += def.resource.amount\n\t\tleft += deposit.resource\n\t}\n\treturn held > 0 && left < held * ratio\n}\n\n/**\n * A building it would put up for a better answer to its rivals' armies: what the best of the soldiers its barracks\n * train needs, where it answers them better than any it can train now, and its workers can build it. None otherwise\n */\nfunction counterNeeds(ai: Brain, margin: number): UnitTypeDef | undefined {\n\tconst { registry, view } = ai\n\tconst { me } = view\n\tconst builds = new Set(view.typesOf('worker')[0]?.builds ?? [])\n\tlet best: { def: UnitTypeDef; score: number } | undefined\n\tlet ready = 0\n\tfor (const barracks of view.typesOf('barracks')) {\n\t\tif (!view.mine.ofType(barracks.id).length) continue\n\t\tfor (const id of barracks.trains ?? []) {\n\t\t\tconst def = registry.unit(id)\n\t\t\tif (!isSoldier(def) || !availableToPlayer(def, { race: me.race, availability: me.availability }, id)) continue\n\t\t\tconst score = counters(ai, def)\n\t\t\tif (view.has(def.requires)) ready = Math.max(ready, score)\n\t\t\telse if (score > (best?.score ?? 0)) best = { def, score }\n\t\t}\n\t}\n\tif (!best || best.score <= ready * margin) return undefined\n\t// the first thing it lacks that its workers build: by its id, or what provides it\n\tfor (const need of best.def.requires ?? []) {\n\t\tif (view.has([need])) continue\n\t\tconst maker = registry.units.all().find((def) => builds.has(def.id) && (def.id === need || def.provides?.includes(need)))\n\t\tif (maker) return maker\n\t}\n\treturn undefined\n}\n\n/**\n * How well a type it can train answers what it has seen of its rivals (`Strength.counterFor`: its strength against\n * them over its plain strength; one that hits the air against flyers, one whose damage gets through their armour).\n * 0 where it has seen nothing to answer\n */\nfunction counters(ai: Brain, def: UnitTypeDef): number {\n\tconst { registry } = ai\n\t// the most of each of its rivals' unit types seen at once, as its knowledge keeps them (not creeps, not buildings)\n\tconst seen: Record<string, number> = {}\n\tfor (const [type, { most }] of Object.entries(ai.knowledge.enemy.typesSeen())) {\n\t\tif (registry.units.has(type) && registry.unit(type).kind === 'unit') seen[type] = most\n\t}\n\tif (!Object.keys(seen).length) return 0\n\treturn ai.view.strength.counterFor(seen, [def])[0].score\n}\n","import { baseStats } from '#engine/defs'\nimport type { MeleeSurrenderOptions } from './surrender'\nimport { Defence } from '../defence'\nimport { Team } from '../team'\nimport { Waves } from '../waves'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModule, type AiModuleDef, defineModule, moduleKey } from '#engine/ai/module'\nimport { consider, curve, defineGoal, type Claimed, type GoalDef } from '#engine/ai/goals'\nimport type { EnemyBase } from '#engine/ai/knowledge'\nimport { flagOf } from '#engine/ai/profiles'\nimport type { Squad, SquadOptions } from '#engine/ai/squads'\nimport type { Base, UnitSet } from '#engine/ai/view'\nimport { heroOfState } from '#engine/hero'\nimport { where } from '../geometry'\n\n/*\n * The melee player's army (AI plan, D3): what its fighters do when nothing is raiding home, as goals on the brain's\n * picker (B1), each scoring itself from what it sees and claiming the units it needs, so that several run at once\n * on different units. Beside them on the picker are the kit's: `defend` (the defence's, C4), `help` (the team's,\n * C5) and `scout` (the scouting's, C3); the fall back home from a lost fight is the squads' (C1), and with waves given\n * as data (D2) the waves module sends those and `attack` stands aside. The goals here:\n *\n * - **attack** (0.8): the wave of its own. Its time comes `firstAttack` seconds in and every `attackEvery` after, or\n * sooner when their army as last seen is weak against what it has ready (No Mercy) or its team asks it to come\n * along; it goes once enough fighters stand idle (`waveSize`, two more each wave) **and it is worth going**: a\n * wave that would lose against their army as last seen (`goOdds`) waits and trains on, up to `waitAtMost`. The\n * wave is a squad (`wave`) sent at the nearest of their buildings it knows, held while it is out; idle fighters at\n * home make up what it lost (`reinforce`); once it razed what it went for, it goes on to the next while it is strong\n * enough (`pressOn`), rather than walking home to wait for the clock; not strong enough, it walks home rather than\n * stand idle where it razed it. A wave that falls back puts the next one off.\n * - **creep** (0.5): a camp of creeps near home taken by the hero and a few, between waves, for the hero's levels.\n * - **raid** (0.6): their workers hit where their army is not. Their workers as last seen are clustered by their\n * bases; a base with workers and no army seen near it lately gets a small, fast party (`size`) sent round their\n * army (`avoid`), which goes for the workers first and falls back early (`retreatAt`). The economy is what a\n * raid hurts: a mine with no workers brings in nothing.\n * - **harass** (0.5): before the first wave, the hero and a few at their main, for the same reason, while their army\n * is not seen there.\n * - **expand** (0.7): a few guards at a base past home that has no tower yet, so that a raid on it is met where it\n * lands and not from across the map; only fighters to spare past a wave go.\n *\n * The weights are what each is worth at its best against the others; a personality's `weights` scale them\n * (`harasser` raids and harasses more, `turtle` less). Every number is an option (`MeleeArmyOptions`, data: the seat's\n * `AiOptions.army` goes over the brain's), every goal can be left out (`false`). What the army remembers (the next\n * wave's time and size, how many went, the last raid) is plain data in the brain's memory, under `melee.army`\n */\n\n/**\n * How the melee player's army goes about its own waves and the goals beside them (`AiSettings.army` over the melee\n * brain's `army(options)`). Data: a save keeps the seat's\n *\n * @beta\n */\nexport interface MeleeArmyOptions {\n\t/** Seconds before its first wave: 150 when left out */\n\tfirstAttack?: number\n\t/** Seconds between two waves: 45 when left out */\n\tattackEvery?: number\n\t/** Units in its first wave, each after bringing two more: 6 when left out */\n\twaveSize?: number\n\t/**\n\t * The odds (`Strength.odds`) of what it has ready against their army as last seen (the last minute) under which a\n\t * wave whose time has come waits and trains on rather than go: 0.4 when left out; `false` never waits\n\t */\n\tgoOdds?: number | false\n\t/**\n\t * Seconds a wave waits past its time at the most, outmatched or short of its size: then it goes with what it has,\n\t * half the wave at the least, where that would hold against what is remembered to reach the target. Twice\n\t * `attackEvery` when left out. A wave that could never reach its size (the supply capped) still comes\n\t */\n\twaitAtMost?: number\n\t/** Whether a wave that razed what it went for goes on to the next of their buildings it knows, while it is strong enough: yes when left out */\n\tpressOn?: boolean\n\t/**\n\t * Where a wave of its own goes among their buildings it knows of: the `nearest`, or the `weakest` (the one the least\n\t * of their strength is remembered to reach: an expansion before a main with towers; the nearest among those alike).\n\t * `weakest` when left out\n\t */\n\ttarget?: 'nearest' | 'weakest'\n\t/**\n\t * Whether a wave of theirs that died at its gate is answered at once with what is ready (half a wave at the least),\n\t * their base being empty of it: yes when left out. `counterAfter` is how many of their fighters must have fallen\n\t * near its bases in the last twenty seconds (3 when left out)\n\t */\n\tcounter?: boolean\n\tcounterAfter?: number\n\t/** The odds against their army as last seen a wave needs to go on: 0.5 when left out */\n\tpressOdds?: number\n\t/** Whether idle fighters at home join a wave that is out, making up what it lost: yes when left out */\n\treinforce?: boolean\n\t/**\n\t * A strike while their army is away (FJ1): every sighting of their army within `awayFor` seconds (60) stands far\n\t * from what a wave would go for (their base, out raiding or creeping or at a base of mine), and what is ready (half\n\t * a wave at the least) would hold against what is remembered to reach it at these odds (`odds`, 0.6): the wave goes\n\t * before its time. `false` for none\n\t */\n\tstrike?: false | { awayFor?: number; odds?: number }\n\t/** Units more in each wave than the one before: 2 when left out */\n\twaveGrowth?: number\n\t/** The most units a wave of its own asks for: 24 when left out */\n\twaveMax?: number\n\t/**\n\t * Raids on their workers where their army is not (the `raid` goal): how many go (`size`, 3, the fastest), the odds\n\t * against what is remembered at the base they need (`odds`, 0.6), seconds between raids (`every`, 60), seconds\n\t * their army must not have been seen near the base (`armyAwayFor`, 45), how long ago their workers were seen at\n\t * the most (`workersSeenFor`, 120), the odds the raiders fall back at (`retreatAt`, 0.5). `false` for no raids\n\t */\n\traid?: false | { size?: number; odds?: number; every?: number; armyAwayFor?: number; workersSeenFor?: number; retreatAt?: number }\n\t/**\n\t * Harassing their main before the first wave (the `harass` goal): the party (`size`, 3: the hero and the fastest),\n\t * the odds it needs at their base (`odds`, 0.6), seconds between (`every`, 90), the odds it falls back at\n\t * (`retreatAt`, 0.5). `false` for none\n\t */\n\tharass?: false | { size?: number; odds?: number; every?: number; retreatAt?: number }\n\t/**\n\t * Guards at a base past home that has no tower yet (the `expand` goal): how many (`guards`, 2), and how many\n\t * fighters past a wave must stand idle for any to go (`spare`, 0). `false` for none\n\t */\n\texpand?: false | { guards?: number; spare?: number }\n\t/**\n\t * Creeping (the `creep` goal): seconds between camps (`every`, 40), seconds into the game before the first\n\t * (`from`, 30), how far from home a camp may be (`reach`, 70), the fewest in a party (`party`, 3). `false` for none\n\t */\n\tcreep?: false | { every?: number; from?: number; reach?: number; party?: number }\n\t/**\n\t * When it gives up (the `melee.surrender` module, `MeleeSurrenderOptions`): once it has no hall, no worker and no\n\t * army that could win the game back, for half a minute, when left out; a condition of the game's own (`when`), and\n\t * how long it holds first (`after`). `false` plays to the last\n\t */\n\tsurrender?: false | MeleeSurrenderOptions\n}\n\n/**\n * What the army module remembers between thinks, as a save keeps it (`BrainMemory.modules['melee.army']`)\n *\n * @beta\n */\nexport interface MeleeArmyMemory {\n\tv: 1\n\t/** Units the next wave of its own asks for */\n\twaveSize: number\n\t/** Seconds into the game the next wave's time comes */\n\tnextAttack: number\n\t/** Seconds into the game it may go creeping again */\n\tnextCreeping: number\n\t/** Waves sent */\n\tattacks: number\n\t/** The tick the wave it last said it falls back with turned at: said once a retreat */\n\tsaidRetreat?: number\n\t/** Seconds into the game the wave began waiting past its time, short of its size or outmatched (`goOdds`): none while it is not */\n\twaiting?: number\n\t/** The tick the last raid was sent at */\n\traided?: number\n\t/** The tick the last harassing party was sent at */\n\tharassed?: number\n}\n\n/**\n * The army module, with the army it runs (`MeleeArmy`): what the tests and the debug tools reach (`meleeArmyOf`)\n *\n * @beta\n */\nexport interface MeleeArmyModule extends AiModule {\n\tarmy: MeleeArmy\n}\n\n/**\n * What finds the melee army's module with its shape (`ai.module(MELEE_ARMY)`)\n *\n * @beta\n */\nexport const MELEE_ARMY = moduleKey<MeleeArmyModule>('melee.army')\n\n/**\n * The melee brain's army (`MeleeArmy`) of a brain: its waves, numbers and memory, for the tests and the debug tools.\n * Throws for a brain without the `melee.army` module\n *\n * @beta\n */\nexport function meleeArmyOf(ai: Brain): MeleeArmy {\n\tconst module = ai.module(MELEE_ARMY)\n\tif (!module?.army) throw new Error(`The brain \"${ai.def.id}\" has no melee.army module`)\n\treturn module.army\n}\n\n/** How near a base what is at it is: their workers at one of their bases, my fighters at one of mine */\nconst AT_BASE = 30\n/** How near a base their army seen counts as there */\nconst ARMY_NEAR = 36\n/** How near a base a guard stands to guard it */\nconst GUARDING = 16\n/** The fewest raiders or harassers a party is sent with */\nconst PARTY_LEAST = 2\n/** Why a wave that razed what it went for and does not go on walks home (its `retreat`'s `why`) */\nconst RAZED = 'razed'\n\n/**\n * The melee player's army: its waves of its own and the goals beside them (the file's comment), its numbers from its\n * options (`firstAttack`, `attackEvery`, `waveSize`) and the defence's radius, its memory. Made for a brain by\n * the `army()` module; reached as `ai.module(MELEE_ARMY)?.army` (`meleeArmyOf(ai)`)\n *\n * @beta\n */\nexport class MeleeArmy {\n\treadonly memory: MeleeArmyMemory\n\treadonly firstAttack: number\n\treadonly attackEvery: number\n\treadonly defendRadius: number\n\n\tconstructor(\n\t\t/** The brain it is the army of */\n\t\treadonly ai: Brain,\n\t\t/** How it goes: the module's options, the brain's settings over them (`ai.settings.army`) */\n\t\treadonly options: MeleeArmyOptions\n\t) {\n\t\t// its numbers are its settings' (D1, B2): the difficulty, the personality, the seat's own\n\t\tthis.firstAttack = options.firstAttack ?? 150\n\t\tthis.attackEvery = options.attackEvery ?? 45\n\t\tthis.defendRadius = ai.area(Defence).radius\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\twaveSize: options.waveSize ?? 6,\n\t\t\tnextAttack: this.firstAttack,\n\t\t\tnextCreeping: (options.creep && options.creep.from) || 30,\n\t\t\tattacks: 0\n\t\t}\n\t}\n\n\tprivate get time(): number {\n\t\treturn this.ai.time\n\t}\n\n\t/** Its fighters: what is gathering (a ghoul at the trees) is at work, not in the army */\n\tprivate armyOf(units: UnitSet): UnitSet {\n\t\treturn units.fighters().where((entity) => entity.own?.order !== 'harvest')\n\t}\n\n\t/** The fighters no goal holds and with nothing to do: what a wave or a party is made of. Once a think */\n\tready(): UnitSet {\n\t\treturn this.ai.cache('melee.ready', () => this.readyOf(this.ai.goals.pool()))\n\t}\n\n\tprivate readyOf(units: UnitSet): UnitSet {\n\t\treturn this.armyOf(units).where((unit) => !unit.own?.order)\n\t}\n\n\t/** Their army as last seen within so many seconds, summed by type: a force to weigh odds against */\n\tprivate theirs(seconds: number): Record<string, number> {\n\t\treturn this.ai.cache(`melee.theirs.${seconds}`, () => {\n\t\t\tconst theirs: Record<string, number> = {}\n\t\t\tfor (const army of this.ai.knowledge.enemy.armySeen(seconds))\n\t\t\t\tfor (const [type, count] of Object.entries(army.types)) theirs[type] = (theirs[type] ?? 0) + count\n\t\t\treturn theirs\n\t\t})\n\t}\n\n\t/** The odds of a force of mine against their army as last seen within so many seconds: 1 where none was seen */\n\tprivate oddsAgainstTheirs(mine: UnitSet, seconds: number): number {\n\t\tif (!mine.length) return 0\n\t\tconst theirs = this.theirs(seconds)\n\t\tif (!Object.keys(theirs).length) return 1\n\t\treturn this.ai.view.strength.odds(mine, theirs)\n\t}\n\n\t/** The odds of a force of mine against what is remembered to reach a place (towers, their army seen near it), by the square law */\n\tprivate oddsAt(mine: Iterable<EntityState>, at: Vec2): number {\n\t\tconst { view } = this.ai\n\t\tconst strength = view.strength.sum([...mine])\n\t\tif (strength <= 0) return 0\n\t\tconst theirs = view.threat.at(at, { remembered: true }).enemy\n\t\tif (theirs <= 0) return 1\n\t\treturn (strength * strength) / (strength * strength + theirs * theirs)\n\t}\n\n\t/** Whether its team asks it to join an attack together it has not answered, while its waves wait for the team's (`together`) */\n\tprivate invited(): boolean {\n\t\tconst team = this.ai.area(Team)\n\t\tconst plan = team.together ? team.plan : undefined\n\t\treturn !!plan && plan.by !== this.ai.playerId && this.ai.tick < plan.at && !plan.declined.includes(this.ai.playerId)\n\t}\n\n\t/**\n\t * Whether it has no mercy (No Mercy, a flag of its profile): the enemy's army as last seen (the last minute) weak\n\t * against what it has ready, at the odds the flag says (0.75 for `true`), and it goes before its time\n\t */\n\tprivate merciless(): boolean {\n\t\tconst flag = flagOf(this.ai, 'noMercy')\n\t\tif (!flag) return false\n\t\tconst odds = typeof flag === 'number' ? flag : 0.75\n\t\tconst ready = this.ready()\n\t\tif (!ready.length) return false\n\t\treturn this.oddsAgainstTheirs(ready, 60) >= odds\n\t}\n\n\t/**\n\t * Whether the wave is worth sending now: what is ready would not lose outright against their army as last seen\n\t * (`goOdds`), or it has waited long enough (`waitAtMost`). Nothing seen of their army: worth it\n\t */\n\tprivate worthGoing(): boolean {\n\t\tconst goOdds = this.options.goOdds ?? 0.4\n\t\tif (goOdds === false) return true\n\t\tif (this.oddsAgainstTheirs(this.ready(), 60) >= goOdds) return true\n\t\treturn this.waitedEnough()\n\t}\n\n\t/**\n\t * Whether a wave of theirs just died at its gate (so many of their fighters fallen near its bases in the last twenty\n\t * seconds): their base is empty of it, and what is ready goes at once\n\t */\n\tprivate counterAttack(): boolean {\n\t\tif (this.options.counter === false) return false\n\t\treturn this.ai.cache('melee.counter', () => {\n\t\t\tconst { view, knowledge, registry } = this.ai\n\t\t\tconst bases = view.bases()\n\t\t\tlet fallen = 0\n\t\t\tfor (const death of knowledge.events.deaths(20)) {\n\t\t\t\tif (view.player(death.owner)?.relation !== 'enemy' || !registry.units.has(death.type)) continue\n\t\t\t\tconst def = registry.unit(death.type)\n\t\t\t\tif (def.kind !== 'unit' || !def.attacks?.length || def.harvester) continue\n\t\t\t\tif (bases.some((base) => distSq(base.at, death.at) < AT_BASE * AT_BASE)) fallen++\n\t\t\t}\n\t\t\treturn fallen >= (this.options.counterAfter ?? 3)\n\t\t})\n\t}\n\n\t/**\n\t * Whether their army is away from what a wave would go for (`strike`): at least one sighting of it within `awayFor`\n\t * seconds (nothing seen says nothing of where it is), every one far from the target and from every base of mine and\n\t * every building of my allies' (an army at my gate is the defence's, at an ally's the team's: not a reason to trade\n\t * bases), and what is ready (half a wave at the least) would hold against what is remembered to reach the target\n\t * (its towers). Once a think\n\t */\n\tprivate armyAway(): boolean {\n\t\tconst strike = this.options.strike\n\t\tif (strike === false) return false\n\t\treturn this.ai.cache('melee.strike', () => {\n\t\t\tconst { view, knowledge } = this.ai\n\t\t\tif (this.ai.area(Waves).active || this.out('wave')) return false\n\t\t\tconst ready = this.ready()\n\t\t\tif (ready.length < Math.max(PARTY_LEAST, Math.ceil(this.memory.waveSize / 2))) return false\n\t\t\tconst sightings = knowledge.enemy.armySeen(strike?.awayFor ?? 60).filter((army) => view.player(army.owner)?.relation === 'enemy')\n\t\t\tif (!sightings.length) return false\n\t\t\tconst target = this.targetFor(ready.centre())\n\t\t\tif (!target) return false\n\t\t\tconst far = ARMY_NEAR * 2\n\t\t\tif (sightings.some((army) => distSq(army.at, target) < far * far)) return false\n\t\t\t// an army at my gate is the defence's, at an ally's the team's: not a reason to trade bases\n\t\t\tconst home = this.defendRadius + ARMY_NEAR\n\t\t\tconst ours = [...view.bases().map((base) => base.at), ...view.allies.buildings()]\n\t\t\tif (sightings.some((army) => ours.some((at) => distSq(army.at, at) < home * home))) return false\n\t\t\treturn this.oddsAt(ready, target) >= (strike?.odds ?? 0.6)\n\t\t})\n\t}\n\n\t/** Whether the wave has waited past its time as long as it will (`waitAtMost`): it goes with what it has then */\n\tprivate waitedEnough(): boolean {\n\t\tconst { waiting } = this.memory\n\t\treturn waiting !== undefined && this.time - waiting >= (this.options.waitAtMost ?? this.attackEvery * 2)\n\t}\n\n\t/**\n\t * Whether the wave is ready: as many as it asks for stand idle; or half of them, once it has waited long enough and\n\t * they would hold against what is remembered to reach the target (half a wave is not fed to the towers)\n\t */\n\tprivate waveReady(): boolean {\n\t\tconst ready = this.ready()\n\t\tconst { waveSize } = this.memory\n\t\tif (ready.length >= waveSize) return true\n\t\tif (!(this.waitedEnough() || this.counterAttack() || this.armyAway()) || ready.length < Math.max(PARTY_LEAST, Math.ceil(waveSize / 2)))\n\t\t\treturn false\n\t\tconst goOdds = this.options.goOdds ?? 0.4\n\t\tif (goOdds === false) return true\n\t\tconst target = this.targetFor(ready.centre())\n\t\treturn !!target && this.oddsAt(ready, target) >= goOdds\n\t}\n\n\t/**\n\t * Where a wave goes: of the rival's buildings it knows of (in sight or remembered, not a creep's), the nearest, or\n\t * (`target: 'weakest'`) the one the least of their strength is remembered to reach (an expansion before a main with\n\t * towers), the nearest among those alike; else a base it was told of\n\t */\n\tprivate targetFor(from: Vec2 | undefined): Vec2 | undefined {\n\t\tconst { view } = this.ai\n\t\tconst known = view.enemies.known().buildings()\n\t\tconst bases = this.ai.options.enemyBases ?? []\n\t\tif (!known.length || !from) return bases.length ? bases[this.memory.attacks % bases.length] : undefined\n\t\tif ((this.options.target ?? 'weakest') === 'nearest') {\n\t\t\tconst near = known.nearest(from)!\n\t\t\treturn { x: near.x, z: near.z }\n\t\t}\n\t\tlet best: { at: Vec2; threat: number; distance: number } | undefined\n\t\tfor (const building of known) {\n\t\t\tconst threat = view.threat.at(building, { remembered: true }).enemy\n\t\t\tconst distance = distSq(from, building)\n\t\t\t// alike within a tenth: the nearer; else the least threatened\n\t\t\tconst alike = best && Math.abs(threat - best.threat) <= Math.max(threat, best.threat) * 0.1\n\t\t\tif (!best || (alike ? distance < best.distance : threat < best.threat)) best = { at: { x: building.x, z: building.z }, threat, distance }\n\t\t}\n\t\treturn best!.at\n\t}\n\n\t/**\n\t * A way of its own for a wave (Random Paths, a flag of its profile): by the brain's numbers, straight, or by a place a\n\t * third of the way's length to one side or the other of its middle. None for straight, or without the flag\n\t */\n\tprivate wayOf(squad: Squad, target: Vec2): Vec2 | undefined {\n\t\tif (!flagOf(this.ai, 'randomPaths')) return undefined\n\t\tconst from = squad.centre()\n\t\tif (!from) return undefined\n\t\tconst side = this.ai.rng.int(-1, 1)\n\t\tif (side === 0) return undefined\n\t\tconst dx = target.x - from.x\n\t\tconst dz = target.z - from.z\n\t\tconst { width, depth } = this.ai.session.terrain\n\t\tconst x = (from.x + target.x) / 2 - (dz / 3) * side\n\t\tconst z = (from.z + target.z) / 2 + (dx / 3) * side\n\t\treturn { x: Math.min(width - 2, Math.max(2, x)), z: Math.min(depth - 2, Math.max(2, z)) }\n\t}\n\n\t/**\n\t * How the squads it sends out behave: they fall back from a fight away from home at the odds a wave used to (the\n\t * profile's `retreatOdds`, or Groups Flee), fight on to the last near home, and a wave is made up from home\n\t * (`reinforce`); the seat's say goes over it\n\t */\n\tprivate get outward(): SquadOptions {\n\t\treturn {\n\t\t\tretreatAt: 0.3,\n\t\t\thome: this.defendRadius + 6,\n\t\t\treinforce: this.options.reinforce ?? true,\n\t\t\t...this.ai.squads.defaults\n\t\t}\n\t}\n\n\t/** A party's options: as a wave's, but it falls back sooner and nobody comes after it */\n\tprivate party(retreatAt: number): SquadOptions {\n\t\treturn { ...this.outward, retreatAt, reinforce: false }\n\t}\n\n\t/** Sends a wave: its squad to attack the target, the next wave set, said where it says things */\n\tprivate launch(squad: Squad, target: Vec2, together: boolean): void {\n\t\tconst { ai, memory } = this\n\t\tconst known = ai.view.enemies.known().buildings()\n\t\tconst size = squad.length\n\t\tconst early = this.time < memory.nextAttack\n\t\tconst counter = early && this.counterAttack()\n\t\tconst struck = early && !counter && this.armyAway()\n\t\tconst via = this.wayOf(squad, target)\n\t\tsquad.attack(target, via ? { via } : {})\n\t\tai.knowledge.own.attackSent(target, size)\n\t\tmemory.attacks++\n\t\tmemory.waveSize = Math.min(memory.waveSize + (this.options.waveGrowth ?? 2), this.options.waveMax ?? 24)\n\t\tmemory.waiting = undefined\n\t\t// a slip (its profile's `mistakes`): the next wave sooner than it should, by up to its share of the wait\n\t\tconst mistakes = ai.profile.mistakes ?? 0\n\t\tmemory.nextAttack = this.time + this.attackEvery * (mistakes > 0 ? 1 - mistakes * ai.rng.next() : 1)\n\t\tai.area(Team).say('attacking')\n\t\tai.decide(\n\t\t\t`sends wave ${memory.attacks} of ${size} at ${where(target)}${together ? ', together with its team' : known.length ? ', a building of theirs it knows' : ', a base it was told of'}${counter ? ', answering their wave that fell at its gate' : struck ? ', their army away' : ''}; the next is ${memory.waveSize} strong at ${Math.round(memory.nextAttack)} s`,\n\t\t\t{ kind: 'army', goal: 'attack' }\n\t\t)\n\t}\n\n\t/**\n\t * The squad a goal of its sent out (`wave`, `creep`, `raid`, `harass`, `expand`), while it is on its errand: on its\n\t * way, fighting, falling back, or (a wave) done with its target, to go on or to be sent home. None once its task is\n\t * over, or before it was sent\n\t */\n\tprivate out(name: string): Squad | undefined {\n\t\tconst squad = this.ai.squads.named(name)\n\t\tif (!squad) return undefined\n\t\tif (!squad.idle) return squad\n\t\treturn name === 'wave' && squad.done === 'cleared' ? squad : undefined\n\t}\n\n\t/**\n\t * Whether a wave that razed what it went for goes on: it may, it is still a few, it is strong enough against their\n\t * army as last seen and against what is remembered to reach the next target (its towers), and it knows of more of theirs\n\t */\n\tprivate mayPressOn(squad: Squad): boolean {\n\t\tif (!(this.options.pressOn ?? true) || squad.length < PARTY_LEAST) return false\n\t\tconst odds = this.options.pressOdds ?? 0.5\n\t\tif (this.oddsAgainstTheirs(squad.units(), 60) < odds) return false\n\t\tif (!this.ai.view.enemies.known().buildings().length) return false\n\t\tconst target = this.targetFor(squad.centre())\n\t\treturn !!target && this.oddsAt(squad.units(), target) >= odds\n\t}\n\n\t/** The camp its ready units and hero can take near home, when it is time to go creeping */\n\tprivate campToTake(ready: Iterable<EntityState>) {\n\t\tconst creep = this.options.creep\n\t\tif (creep === false) return undefined\n\t\tif (this.time < this.memory.nextCreeping || this.memory.nextAttack - this.time < 40) return undefined\n\t\tconst party = [...ready]\n\t\tconst hero = party.find((unit) => heroOfState(unit))\n\t\tconst home = this.ai.view.home()\n\t\tif (!hero || !home || party.length < (creep?.party ?? 3)) return undefined\n\t\t// what the group can take on grows with its size and with the hero\n\t\tconst strength = party.length * 1.2 + (heroOfState(hero)?.level ?? 1)\n\t\tconst reach = creep?.reach ?? 70\n\t\tconst camps = this.ai.view.camps().filter((camp) => !camp.cleared && camp.level <= strength && distSq(camp, home) < reach * reach)\n\t\tlet best: (typeof camps)[number] | undefined\n\t\tlet bestDistance = Infinity\n\t\tfor (const camp of camps) {\n\t\t\tconst d = distSq(home, camp)\n\t\t\tif (d < bestDistance) {\n\t\t\t\tbestDistance = d\n\t\t\t\tbest = camp\n\t\t\t}\n\t\t}\n\t\treturn best\n\t}\n\n\t// ---- the raid\n\n\t/** Where a raid would go: the base of theirs with the most workers seen lately and no army seen near it, with how many */\n\tprivate raidTarget(): { at: Vec2; workers: number } | undefined {\n\t\treturn this.ai.cache('melee.raid', () => {\n\t\t\tconst raid = this.options.raid\n\t\t\t// with waves given (D2), the fighters are the waves': no party of its own is sent\n\t\t\tif (raid === false || this.ai.area(Waves).active) return undefined\n\t\t\tconst { enemy } = this.ai.knowledge\n\t\t\tconst workers = enemy.workersSeen(raid?.workersSeenFor ?? 120).filter((worker) => worker.died === undefined)\n\t\t\tif (!workers.length) return undefined\n\t\t\tconst armies = enemy.armySeen(raid?.armyAwayFor ?? 45)\n\t\t\tconst home = this.ai.view.home()\n\t\t\tlet best: { at: Vec2; workers: number; distance: number } | undefined\n\t\t\tfor (const base of enemy.bases()) {\n\t\t\t\tif (base.gone || armies.some((army) => distSq(army.at, base.at) < ARMY_NEAR * ARMY_NEAR)) continue\n\t\t\t\tconst count = workers.filter((worker) => distSq(worker.at, base.at) < AT_BASE * AT_BASE).length\n\t\t\t\tif (!count) continue\n\t\t\t\tconst distance = home ? distSq(home, base.at) : 0\n\t\t\t\tif (!best || count > best.workers || (count === best.workers && distance < best.distance))\n\t\t\t\t\tbest = { at: { x: base.at.x, z: base.at.z }, workers: count, distance }\n\t\t\t}\n\t\t\treturn best && { at: best.at, workers: best.workers }\n\t\t})\n\t}\n\n\t/** The fastest fighters of some, no heroes among them, up to so many: a party; none where fewer than two */\n\tprivate fastest(units: UnitSet, count: number): EntityState[] {\n\t\tconst { registry, view } = this.ai\n\t\tconst speed = (unit: EntityState) => baseStats(view.def(unit), registry).moveSpeed\n\t\tconst chosen = units\n\t\t\t.filter((unit) => !heroOfState(unit))\n\t\t\t.sort((a, b) => speed(b) - speed(a) || a.id - b.id)\n\t\t\t.slice(0, count)\n\t\treturn chosen.length >= Math.min(count, PARTY_LEAST) ? chosen : []\n\t}\n\n\t/** The raiders of what may go: the fastest few, where a raid is on and they would not die at the base */\n\tprivate raiders(available: UnitSet): EntityState[] {\n\t\tconst raid = this.options.raid\n\t\tif (raid === false) return []\n\t\tconst target = this.raidTarget()\n\t\tif (!target) return []\n\t\tconst chosen = this.fastest(this.readyOf(available), raid?.size ?? 3)\n\t\treturn chosen.length && this.oddsAt(chosen, target.at) >= (raid?.odds ?? 0.6) ? chosen : []\n\t}\n\n\t// ---- harassing\n\n\t/** Their main as known: the first base of theirs with a hall, nearest home */\n\tprivate theirMain(): EnemyBase | undefined {\n\t\treturn this.ai.cache('melee.theirMain', () => {\n\t\t\tif (this.ai.area(Waves).active) return undefined\n\t\t\tconst home = this.ai.view.home()\n\t\t\tconst mains = this.ai.knowledge.enemy.bases().filter((base) => base.hall && !base.gone && !base.expansion)\n\t\t\tlet best: EnemyBase | undefined\n\t\t\tlet bestDistance = Infinity\n\t\t\tfor (const base of mains) {\n\t\t\t\tconst d = home ? distSq(home, base.at) : 0\n\t\t\t\tif (d < bestDistance) {\n\t\t\t\t\tbestDistance = d\n\t\t\t\t\tbest = base\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best\n\t\t})\n\t}\n\n\t/** The party that harasses: the hero and the fastest few, where their army was not seen at their main lately and the party would hold */\n\tprivate harassers(available: UnitSet): EntityState[] {\n\t\tconst harass = this.options.harass\n\t\tif (harass === false) return []\n\t\tconst main = this.theirMain()\n\t\tif (!main) return []\n\t\tif (this.ai.knowledge.enemy.armySeen(60).some((army) => distSq(army.at, main.at) < ARMY_NEAR * ARMY_NEAR)) return []\n\t\tconst ready = this.readyOf(available)\n\t\tconst heroes = ready.filter((unit) => !!heroOfState(unit))\n\t\tconst size = harass?.size ?? 3\n\t\tconst chosen = [...heroes.slice(0, 1), ...this.fastest(ready, Math.max(0, size - Math.min(1, heroes.length)))]\n\t\tif (!chosen.length || (!heroes.length && chosen.length < Math.min(size, PARTY_LEAST))) return []\n\t\treturn this.oddsAt(chosen, main.at) >= (harass?.odds ?? 0.6) ? chosen : []\n\t}\n\n\t// ---- the expansion's guards\n\n\t/** Whether a base of mine still wants guards: past home, with no finished tower among its buildings */\n\tprivate wantsGuards(base: Base): boolean {\n\t\treturn !base.buildings.withRole('tower').finished().length\n\t}\n\n\t/** The bases past home that want guards and have none: no fighters of mine standing by them. Once a think */\n\tprivate unguarded(): Base[] {\n\t\treturn this.ai.cache('melee.unguarded', () => {\n\t\t\tif (this.ai.area(Waves).active) return []\n\t\t\tconst { view } = this.ai\n\t\t\tconst fighters = this.armyOf(view.mine)\n\t\t\treturn view\n\t\t\t\t.bases()\n\t\t\t\t.slice(1)\n\t\t\t\t.filter((base) => this.wantsGuards(base) && !fighters.near(base.at, GUARDING).length)\n\t\t})\n\t}\n\n\t/** The base the expand squad guards, where it still wants guards */\n\tprivate guarded(): Base | undefined {\n\t\tconst squad = this.ai.squads.named('expand')\n\t\tconst at = squad?.current?.kind === 'defend' ? (squad.current.data.at as Vec2 | undefined) : undefined\n\t\tif (!at) return undefined\n\t\tconst base = this.ai.view.bases().find((each) => distSq(each.at, at) < GUARDING * GUARDING)\n\t\treturn base && this.wantsGuards(base) ? base : undefined\n\t}\n\n\t/** The guards for the first base wanting them: the fighters nearest it, so many, from what stands idle past a wave */\n\tprivate guards(available: UnitSet): EntityState[] {\n\t\tconst expand = this.options.expand\n\t\tif (expand === false) return []\n\t\tconst base = this.unguarded()[0]\n\t\tif (!base) return []\n\t\tconst ready = this.readyOf(available)\n\t\tconst guards = expand?.guards ?? 2\n\t\tif (ready.length < guards + this.memory.waveSize + (expand?.spare ?? 0)) return []\n\t\treturn ready.items\n\t\t\t.slice()\n\t\t\t.sort((a, b) => distSq(a, base.at) - distSq(b, base.at) || a.id - b.id)\n\t\t\t.slice(0, guards)\n\t}\n\n\t// ---- the goals\n\n\t/** The goals, for the picker: attack, creep, raid, harass, expand (each unless left out) */\n\tgoals(): GoalDef[] {\n\t\tconst { options } = this\n\t\tconst goals: GoalDef[] = [this.attackGoal()]\n\t\tif (options.creep !== false) goals.push(this.creepGoal())\n\t\tif (options.raid !== false) goals.push(this.raidGoal())\n\t\tif (options.harass !== false) goals.push(this.harassGoal())\n\t\tif (options.expand !== false) goals.push(this.expandGoal())\n\t\treturn goals\n\t}\n\n\tprivate attackGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'attack',\n\t\t\tweight: 0.8,\n\t\t\tconsiderations: [\n\t\t\t\t// seconds past the time set for the next wave; and once the wave is out, as long as it is. Asked to join an\n\t\t\t\t// attack together by its team, or merciless, its time has come too\n\t\t\t\tconsider(\n\t\t\t\t\t'its time has come',\n\t\t\t\t\t// with waves given (D2), the waves module sends them: this goal stands aside\n\t\t\t\t\t() =>\n\t\t\t\t\t\tthis.ai.area(Waves).active\n\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t: this.out('wave')\n\t\t\t\t\t\t\t\t? 1\n\t\t\t\t\t\t\t\t: this.invited() || this.merciless() || this.counterAttack() || this.armyAway()\n\t\t\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t\t\t: this.time - this.memory.nextAttack,\n\t\t\t\t\tcurve.step(0)\n\t\t\t\t),\n\t\t\t\t// as many as it asks for; or half of them, once it has waited long enough (the supply may cap the army)\n\t\t\t\tconsider('the wave is ready', () => (this.out('wave') || this.waveReady() ? 1 : this.ready().length / this.memory.waveSize), curve.step(1)),\n\t\t\t\t// outmatched by their army as last seen, it waits and trains on, for a while\n\t\t\t\tconsider('worth going', () => (this.out('wave') ? 1 : this.worthGoing() ? 1 : 0), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.readyOf(available) },\n\t\t\trun: (_ai, claimed) => this.attack(claimed)\n\t\t})\n\t}\n\n\t/** The attack goal's turn: the wave out watched (its fall back, its wait for the team, its next target), or sent */\n\tprivate attack(claimed: Claimed): void {\n\t\tconst { ai, memory } = this\n\t\tconst team = ai.area(Team)\n\t\tconst out = ai.squads.named('wave')\n\t\tif (!claimed.first && out) {\n\t\t\t// a wave that falls back from a lost fight puts the next one off, as from when it turned; one walking home from\n\t\t\t// what it razed does not\n\t\t\tif (out.current?.kind === 'retreat' && out.current.data.why === RAZED) return\n\t\t\tif (out.current?.kind === 'retreat') {\n\t\t\t\tmemory.nextAttack = Math.max(memory.nextAttack, out.current.since / ai.session.tickRate + this.attackEvery)\n\t\t\t\tif (memory.saidRetreat !== out.current.since) {\n\t\t\t\t\tmemory.saidRetreat = out.current.since\n\t\t\t\t\tteam.say('retreating')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// a wave waiting for the team's attack together goes at its time, or on its own once the plan is gone\n\t\t\tif (out.current?.kind === 'defend' && out.current.data.waiting) {\n\t\t\t\tconst plan = team.plan\n\t\t\t\tif (plan && plan.joined.includes(ai.playerId) && ai.tick < plan.at) return\n\t\t\t\tconst target = plan?.target ?? this.targetFor(out.centre())\n\t\t\t\tif (target) this.launch(out, target, !!plan)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// a wave that razed what it went for goes on to the next of theirs it knows, while it is strong enough; else it\n\t\t\t// walks home, rather than stand idle where it razed it\n\t\t\tif (out.idle && out.done === 'cleared') {\n\t\t\t\tconst target = this.mayPressOn(out) && this.targetFor(out.centre())\n\t\t\t\tif (target) {\n\t\t\t\t\tout.attack(target)\n\t\t\t\t\tai.knowledge.own.attackSent(target, out.length)\n\t\t\t\t\tai.decide(`wave ${memory.attacks} of ${out.length} goes on to ${where(target)}: what it went for is razed`, {\n\t\t\t\t\t\tkind: 'army',\n\t\t\t\t\t\tgoal: 'attack'\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tout.retreat(undefined, RAZED)\n\t\t\t\t\tai.decide(`wave ${memory.attacks} of ${out.length} goes home: what it went for is razed`, { kind: 'army', goal: 'attack' })\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (!claimed.first) return\n\t\tconst wave = claimed.units\n\t\tconst target = this.targetFor(wave.centre())\n\t\tif (!target) return\n\t\tconst squad = claimed.squad('wave', wave, this.outward)\n\t\tif (team.together) {\n\t\t\t// the team's plan: proposed where there is none, joined where there is; the wave holds home till its time\n\t\t\tconst plan = team.plan && ai.tick < team.plan.at ? team.plan : undefined\n\t\t\tif (plan) team.join()\n\t\t\telse team.propose(target)\n\t\t\tsquad.defend(wave.centre() ?? target, 12)\n\t\t\tsquad.current!.data.waiting = true\n\t\t\tconst at = (team.plan?.at ?? ai.tick) / ai.session.tickRate\n\t\t\tai.decide(`wave ${memory.attacks + 1} of ${wave.length} waits to attack together at ${Math.round(at)} s`, { kind: 'army', goal: 'attack' })\n\t\t\treturn\n\t\t}\n\t\tthis.launch(squad, target, false)\n\t}\n\n\tprivate creepGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'creep',\n\t\t\tweight: 0.5,\n\t\t\tconsiderations: [consider('a camp to take', () => (this.out('creep') ? 1 : this.campToTake(this.ready()) ? 1 : 0), curve.step(1))],\n\t\t\tclaims: { units: (_ai, available) => this.readyOf(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst camp = this.campToTake(claimed.units)\n\t\t\t\tif (!camp) return\n\t\t\t\tthis.memory.nextCreeping = this.time + ((this.options.creep && this.options.creep.every) || 40)\n\t\t\t\tclaimed.squad('creep', claimed.units, this.outward).creep(camp)\n\t\t\t\tai.decide(`goes creeping at ${where(camp)} with ${claimed.units.length}`, { kind: 'army', goal: 'creep' })\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate raidGoal(): GoalDef {\n\t\tconst raid = this.options.raid || {}\n\t\tconst every = raid.every ?? 60\n\t\treturn defineGoal({\n\t\t\tid: 'raid',\n\t\t\tweight: 0.6,\n\t\t\tcommitment: 20,\n\t\t\tcooldown: every,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('their workers seen where their army is not', () => (this.out('raid') ? 1 : (this.raidTarget()?.workers ?? 0)), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'seconds since the last raid',\n\t\t\t\t\t() => (this.out('raid') || this.memory.raided === undefined ? every : (this.ai.tick - this.memory.raided) / this.ai.session.tickRate),\n\t\t\t\t\tcurve.step(every)\n\t\t\t\t),\n\t\t\t\tconsider('raiders to spare', () => (this.out('raid') ? 1 : this.raiders(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.raiders(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst target = this.raidTarget()\n\t\t\t\tif (!target) return\n\t\t\t\tthis.memory.raided = ai.tick\n\t\t\t\tclaimed.squad('raid', claimed.units, this.party(raid.retreatAt ?? 0.5)).harass(target.at)\n\t\t\t\tai.decide(`raids their workers at ${where(target.at)} with ${claimed.units.length}: ${target.workers} seen there, their army elsewhere`, {\n\t\t\t\t\tkind: 'army',\n\t\t\t\t\tgoal: 'raid'\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate harassGoal(): GoalDef {\n\t\tconst harass = this.options.harass || {}\n\t\tconst every = harass.every ?? 90\n\t\treturn defineGoal({\n\t\t\tid: 'harass',\n\t\t\tweight: 0.5,\n\t\t\tcommitment: 30,\n\t\t\tcooldown: every,\n\t\t\tconsiderations: [\n\t\t\t\tconsider(\n\t\t\t\t\t'before the first wave',\n\t\t\t\t\t() => (this.out('harass') ? 1 : this.memory.attacks === 0 && this.time < this.memory.nextAttack ? 1 : 0),\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t),\n\t\t\t\tconsider('their main known', () => (this.out('harass') ? 1 : this.theirMain() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'seconds since the last',\n\t\t\t\t\t() => (this.out('harass') || this.memory.harassed === undefined ? every : (this.ai.tick - this.memory.harassed) / this.ai.session.tickRate),\n\t\t\t\t\tcurve.step(every)\n\t\t\t\t),\n\t\t\t\tconsider('a party to send', () => (this.out('harass') ? 1 : this.harassers(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.harassers(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst main = this.theirMain()\n\t\t\t\tif (!main) return\n\t\t\t\tthis.memory.harassed = ai.tick\n\t\t\t\tclaimed.squad('harass', claimed.units, this.party(harass.retreatAt ?? 0.5)).harass(main.at)\n\t\t\t\tai.decide(`harasses their main at ${where(main.at)} with ${claimed.units.length} before its first wave`, { kind: 'army', goal: 'harass' })\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate expandGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'expand',\n\t\t\tweight: 0.7,\n\t\t\tcommitment: 30,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('a new base to hold', () => (this.guarded() ? 1 : this.unguarded().length), curve.step(1)),\n\t\t\t\tconsider('guards to spare', () => (this.guarded() ? 1 : this.guards(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.guards(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst base = this.unguarded()[0]\n\t\t\t\tif (!base) return\n\t\t\t\tclaimed.squad('expand', claimed.units, { ...this.outward, reinforce: false }).defend(base.at, GUARDING)\n\t\t\t\tai.decide(`leaves ${claimed.units.length} to guard its base at ${where(base.at)}: no tower there yet`, { kind: 'army', goal: 'expand' })\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---- the think, the memory, the report\n\n\t/** Once a think, before the picker: whether the wave began waiting past its time, short of its size or outmatched */\n\tthink(): void {\n\t\tconst { memory } = this\n\t\tif (this.ai.area(Waves).active || this.out('wave')) return\n\t\tif (this.time < memory.nextAttack) {\n\t\t\tmemory.waiting = undefined\n\t\t\treturn\n\t\t}\n\t\tif (memory.waiting !== undefined) return\n\t\tconst ready = this.ready().length\n\t\tconst short = ready < memory.waveSize\n\t\tif (!short && this.worthGoing()) return\n\t\tmemory.waiting = this.time\n\t\tthis.ai.decide(\n\t\t\t`wave ${memory.attacks + 1} waits: ${short ? `${ready} of ${memory.waveSize} ready` : `outmatched by their army as last seen (odds ${this.oddsAgainstTheirs(this.ready(), 60).toFixed(2)})`}`,\n\t\t\t{ kind: 'army', goal: 'attack' }\n\t\t)\n\t}\n\n\t/** What it remembers, for a save: a copy */\n\tsave(): MeleeArmyMemory {\n\t\treturn { ...this.memory }\n\t}\n\n\t/** Takes back what `save` gave */\n\trestore(data: unknown): void {\n\t\tconst given = (data ?? {}) as Partial<MeleeArmyMemory>\n\t\tconst { memory } = this\n\t\t// into the same object: what reads the memory (the goals) holds on to it\n\t\tmemory.waveSize = given.waveSize ?? memory.waveSize\n\t\tmemory.nextAttack = given.nextAttack ?? memory.nextAttack\n\t\tmemory.nextCreeping = given.nextCreeping ?? memory.nextCreeping\n\t\tmemory.attacks = given.attacks ?? memory.attacks\n\t\tfor (const key of ['saidRetreat', 'waiting', 'raided', 'harassed'] as const) {\n\t\t\tif (given[key] !== undefined) memory[key] = given[key]\n\t\t\telse delete memory[key]\n\t\t}\n\t}\n\n\t/** What it is thinking, for the debug tools: how hard it plays, its next wave, its roles */\n\tinspect(): Record<string, unknown> {\n\t\tconst { ai, memory } = this\n\t\tconst { view } = ai\n\t\tconst first = (role: string) => view.typesOf(role)[0]?.id\n\t\treturn {\n\t\t\tdifficulty: ai.profile.difficulty ?? 'normal',\n\t\t\tpersonality: ai.profile.personality ?? 'balanced',\n\t\t\tnextAttack: Math.max(0, Math.round(memory.nextAttack - this.time)),\n\t\t\twaveSize: memory.waveSize,\n\t\t\tattacks: memory.attacks,\n\t\t\t...(memory.waiting !== undefined && { waiting: Math.round(this.time - memory.waiting) }),\n\t\t\troles: {\n\t\t\t\tworker: first('worker'),\n\t\t\t\thall: first('hall'),\n\t\t\t\tfarm: [...view.typesOf('supply')].sort((a, b) => (a.cost?.[ai.purse.money] ?? 0) - (b.cost?.[ai.purse.money] ?? 0))[0]?.id,\n\t\t\t\tbarracks: view.typesOf('barracks').map((def) => def.id),\n\t\t\t\taltars: view.typesOf('altar').map((def) => def.id)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * The melee brain's army module: the goals of the army put on the picker (attack, creep, raid, harass, expand), the\n * wave's wait counted. Before the picker (`goals`), after the building and the production, as the old turn had it. With how the army goes where the seat says nothing (`MeleeArmyOptions`)\n *\n * @beta\n */\nexport const army = (options: MeleeArmyOptions = {}): AiModuleDef =>\n\tdefineModule('melee.army', (ai: Brain): MeleeArmyModule => {\n\t\tconst army = new MeleeArmy(ai, { ...options, ...ai.settings.army })\n\t\tai.goals.add(...army.goals())\n\t\treturn {\n\t\t\tid: 'melee.army',\n\t\t\tversion: 1,\n\t\t\tphase: 'decide',\n\t\t\tarmy,\n\t\t\tthink: () => army.think(),\n\t\t\tsave: () => army.save(),\n\t\t\trestore: (data) => army.restore(data),\n\t\t\tinspect: () => army.inspect()\n\t\t}\n\t})\n","import { availableToPlayer } from '#engine/shared'\nimport { Economy } from '../economy'\nimport { Micro } from '../micro'\nimport { queueOf } from '#engine/systems/productionQueue'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\nimport { an } from '../geometry'\n\n/*\n * The melee player's heroes (AI plan, D3; the part of its turn that was `runHeroes`): a fallen hero revived at an idle\n * altar, and the next hero trained while it wants more (one until the game is under way, then as many as its profile\n * says), which one the micro says (`ai.micro.nextHero`: the plan's order, a chance of none). What a hero costs is\n * held in the purse while it is short (`priority`), so that the soldiers wait for it and the hall and the barracks do\n * not. Nothing while the game's build order is followed, nor while the economy waits for what the money is gathered\n * at. What each hero learns is the micro's\n */\n\n/**\n * How the melee brain makes its heroes (`heroes()` of the melee brain): how many once the game is under way (the\n * profile's `heroes`), from when, and how important their price is to the purse\n *\n * @beta\n */\nexport interface MeleeHeroesOptions {\n\t/** Heroes it has once the game is under way (`secondFrom`): one before. 2 when left out */\n\tmost?: number\n\t/** Seconds into the game from which it wants every hero it may have: one before. 240 when left out */\n\tsecondFrom?: number\n\t/**\n\t * How important a hero's price is to the purse while it is short (`Purse.reserve`): the hall, supply, the barracks,\n\t * the altar, the answer to their army and another hall go before it (their wants are more important); a workshop,\n\t * the next tier, a second barracks and the soldiers wait for it. 35 when left out\n\t */\n\tpriority?: number\n}\n\n/** The reservation's name in the purse */\nconst HERO = 'melee.hero'\n\n/**\n * The melee brain's heroes module: a fallen hero revived, the next trained while it wants more, their price held in the\n * purse meanwhile. After the economy, before the building, as the old turn had it; `steps.heroes` and\n * `steps.buildOrder` honoured\n *\n * @beta\n */\nexport const heroes = (options: MeleeHeroesOptions = {}): AiModuleDef =>\n\tdefineModule('melee.heroes', (ai: Brain) => ({\n\t\tid: 'melee.heroes',\n\t\tphase: 'plan',\n\t\tafter: ['economy'],\n\t\tbefore: ['melee.build', 'melee.production'],\n\t\tthink: () => {\n\t\t\t// what the game says to make first holds back what the computer would make of itself, heroes too\n\t\t\tif (ai.plans.following || ai.area(Economy).waiting) return\n\t\t\trun(ai, { ...options, ...ai.settings.heroes })\n\t\t}\n\t}))\n\n/** The turn: revives, or trains the next */\nfunction run(ai: Brain, options: MeleeHeroesOptions): void {\n\tconst { registry, view } = ai\n\tconst { me } = view\n\tconst priority = options.priority ?? 35\n\tconst altars = view.typesOf('altar').flatMap((type) => view.mine.ofType(type.id).finished().items)\n\tconst idle = altars.find((altar) => !queueOf(altar).length)\n\tif (!idle) return\n\t// what a hero costs is held in the purse while it is short: nothing that can wait is bought meanwhile\n\tconst fallen = me.heroes.find((hero) => !hero.alive && hero.reviving === undefined)\n\tif (fallen) {\n\t\tconst price = fallen.reviveCost ?? {}\n\t\tif (ai.purse.spend(price)) {\n\t\t\tai.send({ type: 'revive', building: idle.id, hero: fallen.id })\n\t\t\tai.decide(`revives its ${fallen.type}`, { kind: 'hero' })\n\t\t} else ai.purse.reserve(HERO, price, priority)\n\t\treturn\n\t}\n\t// the second hero can wait until there is an army\n\tconst most = options.most ?? 2\n\tconst wanted = ai.time > (options.secondFrom ?? 240) ? most : Math.min(1, most)\n\tif (me.heroes.length >= wanted) return\n\tconst candidates = (view.def(idle).trains ?? [])\n\t\t.map((id) => registry.unit(id))\n\t\t.filter((def) => def.hero && availableToPlayer(def, { race: me.race, availability: me.availability }, def.id))\n\tconst next = ai.area(Micro).nextHero(\n\t\tcandidates,\n\t\tme.heroes.map((hero) => hero.type)\n\t)\n\tif (!next) return\n\tif (ai.plans.production.train(idle, next)) ai.decide(`trains ${an(next.id)}: hero ${me.heroes.length + 1} of ${wanted}`, { kind: 'hero' })\n\telse if (next.cost) ai.purse.reserve(HERO, next.cost, priority)\n}\n","import { type Brain } from '#engine/ai/brain'\nimport { Economy } from '../economy'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\n\n/*\n * What the melee player trains and researches (AI plan, D3; the part of its turn that was `runProduction`): the\n * brain's production plan (B3), thought in its place among the melee modules: towards the composition (even shares of\n * what it can train, what answers the rivals' armies seen pulling them about: riflemen against flyers), the units\n * wanted outright (a wave's group, the game's build order), supply kept ahead, and research of what its army uses\n * most with money to spare. Nothing while the economy waits for what the money is gathered at. The kit's own\n * `production()` module is the same think without the melee player's gate and `steps`\n */\n\n/**\n * The melee brain's production module: the production plan thought, after the building and before the picker, as the\n * old turn had it; `steps.production` honoured\n *\n * @beta\n */\nexport const production = (): AiModuleDef =>\n\tdefineModule('melee.production', (ai: Brain) => ({\n\t\tid: 'melee.production',\n\t\tphase: 'plan',\n\t\tafter: ['economy', 'melee.heroes', 'melee.build'],\n\t\tthink: () => {\n\t\t\tif (ai.area(Economy).waiting) return\n\t\t\tai.plans.production.think()\n\t\t}\n\t}))\n","import { type Brain } from '#engine/ai/brain'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\nimport { type AiCondition, evaluate } from '#engine/ai/rules'\n\n/*\n * The melee player gives up (RV92): once it cannot come back, it sends the engine's `surrender` command, as a person\n * would, rather than keep a game going with a farm and a tower nobody finds. Cannot come back is, by default: no hall\n * and no worker of its own (nothing to gather with nor to train a worker at), and what fighters it has outmatched by\n * their army as last seen (odds under 0.2), for half a minute on end. A game's own condition goes in its place\n * (`settings.army.surrender.when`, as data or a function), and `surrender: false` keeps it playing to the last (a\n * mission's computer, whose defeat is the story's to say)\n */\n\n/**\n * When the melee player gives up (`MeleeArmyOptions.surrender`): the condition, and how long it holds first\n *\n * @beta\n */\nexport interface MeleeSurrenderOptions {\n\t/**\n\t * When it cannot come back, as a condition (data or a function of the brain). By default: no hall and no worker of\n\t * its own, and its fighters (none at all, or) outmatched by their army as last seen in the last two minutes, odds\n\t * under 0.2\n\t */\n\twhen?: AiCondition\n\t/** Seconds the condition holds on end before it gives up: 30 when left out */\n\tafter?: number\n}\n\n/** What the module remembers, as a save keeps it: since when it is beaten, and whether it gave up */\ninterface SurrenderMemory {\n\tsince?: number\n\tdone?: boolean\n}\n\nconst AFTER = 30\n/** The odds of its fighters against their army as last seen under which they cannot win the game back */\nconst HOPELESS_ODDS = 0.2\n/** How long ago their army was seen, for those odds */\nconst ARMY_SEEN = 120\n\n/** The default: nothing to rebuild with, and nothing to fight with */\nfunction beaten(ai: Brain): boolean {\n\tconst { mine } = ai.view\n\tif (mine.withRole('hall').length || mine.workers().length) return false\n\tconst fighters = mine.fighters()\n\tif (!fighters.length) return true\n\tconst theirs: Record<string, number> = {}\n\tfor (const army of ai.knowledge.enemy.armySeen(ARMY_SEEN))\n\t\tfor (const [type, count] of Object.entries(army.types)) theirs[type] = (theirs[type] ?? 0) + count\n\tif (!Object.keys(theirs).length) return false\n\treturn ai.view.strength.odds(fighters, theirs) < HOPELESS_ODDS\n}\n\n/**\n * The melee brain's surrender module (`melee.surrender`): gives up once it cannot come back (see\n * `MeleeSurrenderOptions`), the engine's `surrender` command sent once. Its options under the settings' (`army.surrender`)\n *\n * @beta\n */\nexport const surrender = (options: MeleeSurrenderOptions = {}): AiModuleDef =>\n\tdefineModule('melee.surrender', (ai: Brain) => {\n\t\tlet memory: SurrenderMemory = {}\n\t\treturn {\n\t\t\tid: 'melee.surrender',\n\t\t\tphase: 'decide',\n\t\t\tthink: () => {\n\t\t\t\tconst given = ai.settings.army?.surrender\n\t\t\t\tif (given === false || memory.done || ai.view.me.defeated) return\n\t\t\t\tconst { when, after = AFTER } = { ...options, ...given }\n\t\t\t\tif (!(when === undefined ? beaten(ai) : evaluate(when, ai))) {\n\t\t\t\t\tmemory.since = undefined\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmemory.since ??= ai.tick\n\t\t\t\tif (ai.tick - memory.since < after * ai.session.tickRate) return\n\t\t\t\tmemory.done = true\n\t\t\t\tai.decide(`gives up: it cannot come back (${Math.round((ai.tick - memory.since) / ai.session.tickRate)} s)`, { kind: 'army' })\n\t\t\t\tai.send({ type: 'surrender' })\n\t\t\t},\n\t\t\tsave: () => (memory.since === undefined && !memory.done ? undefined : { ...memory }),\n\t\t\trestore: (data) => {\n\t\t\t\tmemory = { ...(data as SurrenderMemory) }\n\t\t\t},\n\t\t\tinspect: () => ({ since: memory.since, done: !!memory.done })\n\t\t}\n\t})\n","import type { Brain } from '#engine/ai/brain'\nimport { type AiModule, defineModule } from '#engine/ai/module'\nimport { defineBrain, type DefinedBrain } from '#engine/ai/define'\nimport { defence } from '#engine/ai/defence'\nimport { economy } from '#engine/ai/economy'\nimport { goals } from '#engine/ai/goals'\nimport { micro } from '#engine/ai/micro'\nimport { rules, words } from '#engine/ai/rules'\nimport { scouting } from '#engine/ai/scouting'\nimport { squads } from '#engine/ai/squads'\nimport { team } from '#engine/ai/team'\nimport { waves } from '#engine/ai/waves'\nimport { build } from './build'\nimport { army } from './goals'\nimport { heroes } from './heroes'\nimport { production } from './production'\nimport { surrender } from './surrender'\n\n/*\n * The melee brain (AI plan, D3): the engine's own computer player for a game like a melee, assembled from the kit\n * and nothing else (a test holds this folder to the public API). What a game played as melee lists first in\n * `GameModule.brains`, so that `world.computers.seat` with no brain seats it. One module a file, in\n * the order a think runs them:\n *\n * - `rules` (the brain's own, `meleeBrain.with({ rules })`) and `words` (attack, defend, retreat, hold, pause: B2)\n * - `defence` (C4) and `team` (C5): the raids counted and the team's board read, before the goals are picked\n * - `economy` (C4): the workers, base by base\n * - `melee.heroes`, `melee.build`, `melee.production` (D3, over B3): the heroes, the ladder of wants, what is trained\n * - `melee.army` (D3, over B1): the army's goals (attack, creep, raid, harass, expand) put on the picker\n * - `melee.surrender` (RV92): it gives up once it cannot come back (no hall, no worker, no army that could win)\n * - `goals` (B1): the picker, which runs every goal with what it claims: the army's, the defence's `defend`, the\n * team's `help`, the scouting's `scout`, and a game's own (`meleeBrain.with({ goals })`, `AiOptions.goals`)\n * - `scouting` (C3): nothing in its think, its goal is on the picker\n * - `waves` (D2): the waves given as data, where there are any\n * - `squads` (C1): every squad's task seen to, orders sent once and watched, regroups, retreats, reinforcements\n * - `micro` (C2): the fights of the squads: whom to hit, kiting, fleeing, spells, items, the heroes' skills\n *\n * A variant is `meleeBrain.with({ goals, rules, modules, without, ...anything of BrainDef })`; a part is left out by\n * its module's id (`without: ['melee.heroes']`); a part done another way is a module of one's own beside the rest.\n * How it plays is the seat's options and its profile (`AiOptions`, D1)\n */\n\n/**\n * The engine's melee computer player as a brain: what `world.computers.seat` seats where no brain is named and the game\n * lists it first. It thinks as its profile says (the difficulty's `every`), unless the\n * seat's options say how often. The file's comment lists its modules\n *\n * @beta\n */\nexport const meleeBrain: DefinedBrain = defineBrain({\n\tid: 'core.melee',\n\tmodules: [\n\t\t// the brain's own rules (`with({ rules })`) first: what a rule takes is not given orders by the rest\n\t\tdefineModule('rules', (ai: Brain) => (rules(ai.def.rules ?? []) as (ai: Brain) => AiModule)(ai)),\n\t\twords(),\n\t\tdefence(),\n\t\tteam(),\n\t\t// one hall past its first, where the difficulty and the personality say nothing\n\t\teconomy({ expansions: 1 }),\n\t\theroes(),\n\t\tbuild(),\n\t\tproduction(),\n\t\tarmy(),\n\t\tsurrender(),\n\t\tgoals(),\n\t\tscouting(),\n\t\twaves(),\n\t\tsquads(),\n\t\tmicro()\n\t]\n})\n\nexport { build as meleeBuild, MELEE_LADDER, type MeleeBuildOptions, type MeleeWant } from './build'\nexport { army as meleeArmy, MeleeArmy, type MeleeArmyMemory, type MeleeArmyModule, type MeleeArmyOptions, meleeArmyOf, MELEE_ARMY } from './goals'\nexport { heroes as meleeHeroes, type MeleeHeroesOptions } from './heroes'\nexport { production as meleeProduction } from './production'\nexport { surrender as meleeSurrender, type MeleeSurrenderOptions } from './surrender'\n","import { shapeBounds } from '#engine/areas'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain, type BrainDef, type BrainExtension } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { defineBrain } from './define'\nimport { consider, type Consideration, curve, defineGoal, type GoalDef, goals } from './goals'\nimport { micro } from './micro'\nimport type { AiRole } from './roles'\nimport { type AiAction, type AiCondition, evaluate, rules, words } from './rules'\nimport { type Squad, squads } from './squads'\nimport type { UnitSet } from './view'\nimport { point, where } from './geometry'\n\n/*\n * The mission brain (AI plan, D4): a computer player for a mission, made of the few parts a mission needs. Before it, a\n * mission had the whole melee player (which builds, trains, scouts and sends waves on its own clock: rarely what a\n * story wants) or wrote everything itself in a system beside the computer. Now it lists parts:\n *\n * missionBrain({\n * id: 'campaign.redHand',\n * modules: [holdPosition('camp'), guard('camp hall'), patrol(['ford', 'mill'])],\n * rules: [when.told('raid').do({ say: 'attack', data: { at: 'hall' } })]\n * })\n *\n * `missionBrain` is `defineBrain` with what every mission's computer has: its rules (`BrainDef.rules`) and the words\n * every brain may be told (B2), the goals' picker (B1), squads (C1) and micro (C2). Nothing builds, trains, gathers,\n * scouts or defends its bases the melee player's way (C4's `defence()` calls whole squads home to a raid, a guard and a\n * patrol with them): a mission says who holds what with its parts, and adds the kit's module for anything more.\n *\n * **The parts.** Each is a module that puts one goal on the picker (a goal holds units, so the parts, the words and a\n * rule's orders never fight over a unit: B1's \"who may move a unit\"), and remembers what it needs in the brain's memory:\n *\n * - `holdPosition(place)`: the units there hold it, fighting what comes within its reach and going back after.\n * - `patrol(points)`: a round of places walked again and again, fighting what is met.\n * - `guard(entity)`: units stay by a unit (they follow it) or a building (they hold round it) and fight what comes.\n * - `ambush(place, { then })`: units wait on hold, and spring once a rival walks into reach; then go back to wait,\n * stay, or do what `then` says (a word, a function).\n * - `waveFrom(place, { group, every })`: the units that come out of a spawner (what the mission's own rules spawn, or a\n * building that trains them) are gathered there and sent as a wave once there are enough, or every so often.\n * - `fleeWhen(condition)`: when it holds, the army runs (home, or to a place), and comes back when it no longer does.\n * - `surrenderWhen(condition)`: when it holds, the computer gives up (the engine's `surrender` command).\n *\n * **Its own units.** A part takes its units once, as it is first picked (those at its place, or those its `units`\n * say), and remembers them by id: a word that took them for a while (`attack`) gives them back to it after, and they\n * walk back to their post, wherever the word took them. With `refill`, units that come later and fit are taken too.\n *\n * Every part has a data form (places by name, conditions as data) and a function form (`units` as a function, a target\n * as a function, `then` as a function): a mission's JSON can hold the first.\n */\n\n/**\n * Where a mission's part is: a point, or a name the map or the rules gave an entity (`world.named`) or a region of the\n * map\n *\n * @beta\n */\nexport type MissionPlace = Vec2 | string\n\n/**\n * Which of its units a part takes, as data: those named (`named`), of a type, a role or a tag, near a place (`near`,\n * `within`), at most so many (`count`, the nearest the part's place first). Its fighters (soldiers and heroes) where\n * none of `named`, `type`, `role`, `tag` is given\n *\n * @beta\n */\nexport interface MissionUnitsData {\n\t/** Entities the map or the rules named (`world.named`): those of them that are its own */\n\tnamed?: string[]\n\t/** Of a type, or of any of a list */\n\ttype?: string | string[]\n\trole?: AiRole\n\ttag?: string\n\t/** Near a place */\n\tnear?: MissionPlace\n\t/** How near `near` (the part's reach when left out) */\n\twithin?: number\n\t/** At most so many, the nearest the part's place first */\n\tcount?: number\n}\n\n/**\n * Which of its units a part takes: data (`MissionUnitsData`), or a function choosing from those it may have\n * (`available`: what no goal holds, and what goals it may take from hold)\n *\n * @beta\n */\nexport type MissionUnits = MissionUnitsData | ((ai: Brain, available: UnitSet) => Iterable<EntityState>)\n\n/**\n * What every part of a mission takes\n *\n * @beta\n */\nexport interface MissionPartOptions {\n\t/**\n\t * Its id: the module's, the goal's and the squad's, what the report and the log name it by. `mission.<part>:<place>`\n\t * when left out (`mission.hold:camp`); give one where two parts of a kind share a place\n\t */\n\tid?: string\n\t/** Which of its units it takes, once, as it is first picked: those at its place when left out (its fighters for `fleeWhen`) */\n\tunits?: MissionUnits\n\t/** Whether units that come later and fit `units` are taken too: no when left out (`waveFrom` always takes what comes) */\n\trefill?: boolean\n\t/** Only while this holds: the part lets go of its units while it does not (a condition, as data or a function) */\n\twhen?: AiCondition\n\t/** What it is worth against the brain's other goals: 1 when left out (10 for `fleeWhen`) */\n\tweight?: number\n}\n\n/**\n * What a part remembers between thinks, as a save keeps it: its own units, and what its kind adds (an ambush's spring,\n * a wave's count)\n *\n * @beta\n */\nexport interface MissionPartMemory {\n\tv: 1\n\t/** Whether it took its units yet: they are taken once */\n\ttook: boolean\n\t/** Its own units, by id: what it takes back after a word or a rule had them */\n\tunits: number[]\n\t/** An ambush: the tick it sprang at, while sprung; how many times it sprang; whether its `then` was done */\n\tsprung?: number\n\ttimes?: number\n\tacted?: boolean\n\t/** A wave: how many were sent; the tick the last went at (or the part began at) */\n\tsent?: number\n\tlast?: number\n\t/** `surrenderWhen`: whether it gave up */\n\tdone?: boolean\n}\n\n/**\n * The mission brain's definition: a brain's (`BrainDef`) with the parts given as `modules`, after the ones every mission\n * has. Its `id` is what a save remembers the seat by: list the brain in `GameModule.brains`\n *\n * @beta\n */\nexport interface MissionBrainDef extends BrainExtension {\n\tid: string\n}\n\n/** How far a part reaches round its place, where neither it nor a region says: what holds a camp holds this much round it */\nconst REACH = 10\n/** How much past its reach a part's units are looked for as it first takes them */\nconst TAKE_PAST = 8\n/** How near a spawner a unit has come out of it */\nconst SPAWN_REACH = 10\n/** How far a unit with nowhere to run to runs from the nearest rival */\nconst FLEE_AWAY = 20\n\n/** A place as an id writes it */\nconst nameOf = (place: MissionPlace) => (typeof place === 'string' ? place : `${Math.round(place.x)},${Math.round(place.z)}`)\n\n/**\n * Where a place is for the player: a point as it is; a name, the entity it names where the player knows of it, else the\n * middle of the region of that name. Nothing for a name it does not know\n */\nfunction placeOf(ai: Brain, place: MissionPlace): Vec2 | undefined {\n\tif (typeof place !== 'string') return point(place)\n\tconst named = ai.view.named(place)\n\tif (named) return point(named)\n\tconst region = ai.view.region(place)\n\treturn region && { x: region.shape.x, z: region.shape.z }\n}\n\n/** How far a part reaches round its place: what it was given, else a region's size, else `REACH` */\nfunction reachOf(ai: Brain, place: MissionPlace, given: number | undefined): number {\n\tif (given !== undefined) return given\n\tif (typeof place === 'string' && !ai.view.named(place)) {\n\t\tconst shape = ai.view.region(place)?.shape\n\t\tif (shape) {\n\t\t\tconst { x0, z0, x1, z1 } = shapeBounds(shape)\n\t\t\treturn Math.max(x1 - x0, z1 - z0) / 2\n\t\t}\n\t}\n\treturn REACH\n}\n\n/** The part's `when`, as a consideration that vetoes it while the condition does not hold */\nconst whenOf = (condition: AiCondition | undefined): Consideration[] =>\n\tcondition === undefined ? [] : [consider('its condition holds', (ai) => (evaluate(condition, ai) ? 1 : 0), curve.step(1))]\n\n/** Does an action: a function of the brain, or a word it tells itself (`{ say, data }`) */\nfunction act(ai: Brain, action: AiAction): void {\n\tif (typeof action === 'function') action(ai)\n\telse ai.tell(action.say, action.data, ai.tick)\n}\n\n/**\n * The units a part's `units` choose of those it may have: the data form read (named, type, role, tag, near, count), or\n * the function asked; its fighters at its place where `fallback` says so\n */\nfunction choose(ai: Brain, units: MissionUnits, available: UnitSet, around: Vec2 | undefined, reach: number): EntityState[] {\n\tif (typeof units === 'function') return [...units(ai, available)]\n\tlet set = available.units().alive()\n\tif (units.named) {\n\t\tconst names = units.named\n\t\tset = set.where((entity) => entity.name !== undefined && names.includes(entity.name))\n\t} else if (units.type === undefined && units.role === undefined && units.tag === undefined) set = set.fighters()\n\tif (units.type !== undefined) {\n\t\tconst types = Array.isArray(units.type) ? units.type : [units.type]\n\t\tset = set.where((entity) => types.includes(entity.type))\n\t}\n\tif (units.role !== undefined) set = set.withRole(units.role)\n\tif (units.tag !== undefined) set = set.withTag(units.tag)\n\tif (units.near !== undefined) {\n\t\tconst near = placeOf(ai, units.near)\n\t\tif (!near) return []\n\t\tset = set.near(near, units.within ?? reach)\n\t}\n\tconst chosen = [...set]\n\tif (units.count !== undefined && around) {\n\t\tchosen.sort((a, b) => distSq(a, around) - distSq(b, around) || a.id - b.id)\n\t\treturn chosen.slice(0, Math.max(0, units.count))\n\t}\n\treturn units.count !== undefined ? chosen.slice(0, Math.max(0, units.count)) : chosen\n}\n\n/** What a part is made of, for each brain: its goal, and what of a module it has beside */\ninterface PartMade {\n\tgoal?: GoalDef\n\tthink?(): void\n\tinspect?(): Record<string, unknown>\n}\n\n/**\n * A part of a mission: a module (its id the part's) that puts its goal on the brain's picker and keeps its memory. A\n * brain without a `goals()` module (or the melee brain's) never runs the goal: the log says so once\n */\nfunction part(id: string, kind: string, make: (ai: Brain, memory: MissionPartMemory) => PartMade): AiModuleDef {\n\treturn defineModule(id, (ai: Brain): AiModule => {\n\t\tconst memory: MissionPartMemory = { v: 1, took: false, units: [] }\n\t\tconst made = make(ai, memory)\n\t\tif (made.goal) ai.goals.add(made.goal)\n\t\tlet warned = false\n\t\treturn {\n\t\t\tid,\n\t\t\tversion: 1,\n\t\t\tphase: 'decide',\n\t\t\tthink: () => {\n\t\t\t\tif (made.goal && !warned && !ai.module('goals')) {\n\t\t\t\t\twarned = true\n\t\t\t\t\tai.log.warn('ai', `the mission's part \"${id}\" is a goal, and the brain \"${ai.def.id}\" has no goals() module to pick it`)\n\t\t\t\t}\n\t\t\t\tmade.think?.()\n\t\t\t},\n\t\t\tsave: () => structuredClone(memory),\n\t\t\t// written into the same object: the goal's closures read it\n\t\t\trestore: (data) => {\n\t\t\t\tconst kept = data && typeof data === 'object' ? (data as MissionPartMemory) : undefined\n\t\t\t\tfor (const key of Object.keys(memory)) delete (memory as unknown as Record<string, unknown>)[key]\n\t\t\t\tObject.assign(memory, { v: 1, took: false, units: [] }, structuredClone(kept ?? {}))\n\t\t\t},\n\t\t\tinspect: () => ({ part: kind, units: [...memory.units], ...made.inspect?.() })\n\t\t}\n\t})\n}\n\n/**\n * The claim of a part that keeps its own units (`MissionPartMemory.units`): those it took, wherever they are, as it is\n * picked again; the first time (and with `refill`, each time) what its `units` choose\n */\nfunction ownUnits(\n\tmemory: MissionPartMemory,\n\toptions: MissionPartOptions,\n\tfallback: (ai: Brain) => MissionUnitsData,\n\taround: (ai: Brain) => Vec2 | undefined,\n\treach: (ai: Brain) => number\n): (ai: Brain, available: UnitSet) => readonly EntityState[] {\n\treturn (ai, available) => {\n\t\tconst kept = available.where((entity) => memory.units.includes(entity.id)).items\n\t\tif (memory.took && !options.refill) return kept\n\t\tconst more = choose(ai, options.units ?? fallback(ai), available, around(ai), reach(ai))\n\t\treturn [...kept, ...more.filter((entity) => !memory.units.includes(entity.id))]\n\t}\n}\n\n/**\n * A part's run, as each think begins: what it holds is its own from now on (`memory.units`, the dead let go of), and its\n * own units back in the pool (a word that had them is over) are taken back into its squad. The squad: made where there is\n * none. Those that came into it this think, by id\n */\nfunction muster(\n\tai: Brain,\n\tid: string,\n\tmemory: MissionPartMemory,\n\theld: UnitSet,\n\toptions: MissionPartOptions,\n\tchoosing?: () => readonly EntityState[]\n): {\n\tsquad: Squad\n\tcame: number[]\n} {\n\tconst { mine } = ai.view\n\tmemory.took = true\n\tconst own = new Set(memory.units.filter((unit) => mine.has(unit)))\n\tfor (const unit of held) own.add(unit.id)\n\t// its own, back from a word or a rule: what nothing holds now is given to it\n\tconst pool = ai.goals.pool()\n\tconst back = [...own].filter((unit) => pool.has(unit))\n\tif (options.refill && choosing) for (const entity of choosing()) if (pool.has(entity.id)) back.push(entity.id)\n\tlet squad = ai.squads.named(id)\n\tconst before = new Set(squad?.data.units ?? [])\n\tif (!squad || squad.owner !== id) squad = ai.squads.make(id, [...held.ids(), ...back], { owner: id })\n\telse squad.add([...[...held.ids()].filter((unit) => !before.has(unit)), ...back], 'back at its post')\n\tfor (const unit of squad.data.units) own.add(unit)\n\tmemory.units = [...own].filter((unit) => mine.has(unit)).sort((a, b) => a - b)\n\treturn { squad, came: squad.data.units.filter((unit) => !before.has(unit)) }\n}\n\n/**\n * Its units hold a place: they go there, fight what comes within its reach (`radius`, or the region's size, else 10),\n * and go back once it is gone. Its units: those at the place as it is first picked (within its reach and a little), or\n * what `units` say\n *\n * @beta\n */\nexport function holdPosition(place: MissionPlace, options: MissionPartOptions & { radius?: number } = {}): AiModuleDef {\n\tconst id = options.id ?? `mission.hold:${nameOf(place)}`\n\treturn part(id, 'hold', (_ai, memory) => {\n\t\tconst reach = (ai: Brain) => reachOf(ai, place, options.radius)\n\t\tconst at = (ai: Brain) => placeOf(ai, place)\n\t\tconst claim = ownUnits(memory, options, (ai) => ({ near: place, within: reach(ai) + TAKE_PAST }), at, reach)\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight,\n\t\t\t\tconsiderations: [...whenOf(options.when), consider('it knows where the place is', (ai) => (at(ai) ? 1 : 0), curve.step(1))],\n\t\t\t\tclaims: { units: claim },\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tconst { squad } = muster(ai, id, memory, claimed.units, options, () => claim(ai, ai.goals.pool()))\n\t\t\t\t\t// given its task as made, and again once a task of its own is over (a fall back on the odds): never over another\n\t\t\t\t\tif (squad.idle) squad.defend(at(ai)!, reach(ai))\n\t\t\t\t}\n\t\t\t}),\n\t\t\tinspect: () => ({ place: typeof place === 'string' ? place : point(place) })\n\t\t}\n\t})\n}\n\n/**\n * Its units walk a round of places, one after the other and back to the first, fighting what they meet on the way. Its\n * units: those near the first place as it is first picked, or what `units` say. Places it does not know are passed over\n *\n * @beta\n */\nexport function patrol(points: readonly MissionPlace[], options: MissionPartOptions = {}): AiModuleDef {\n\tif (!points.length) throw new Error('A patrol needs a place at least')\n\tconst id = options.id ?? `mission.patrol:${points.map(nameOf).join('>')}`\n\treturn part(id, 'patrol', (_ai, memory) => {\n\t\tconst round = (ai: Brain) => points.map((each) => placeOf(ai, each)).filter((each): each is Vec2 => !!each)\n\t\tconst first = (ai: Brain) => round(ai)[0]\n\t\tconst claim = ownUnits(\n\t\t\tmemory,\n\t\t\toptions,\n\t\t\t() => ({ near: points[0], within: REACH + TAKE_PAST }),\n\t\t\tfirst,\n\t\t\t() => REACH\n\t\t)\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight,\n\t\t\t\tconsiderations: [...whenOf(options.when), consider('places it knows', (ai) => round(ai).length, curve.step(1))],\n\t\t\t\tclaims: { units: claim },\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tconst { squad } = muster(ai, id, memory, claimed.units, options, () => claim(ai, ai.goals.pool()))\n\t\t\t\t\tif (squad.idle) squad.patrol(round(ai))\n\t\t\t\t}\n\t\t\t}),\n\t\t\tinspect: () => ({ points: points.map((each) => (typeof each === 'string' ? each : point(each))) })\n\t\t}\n\t})\n}\n\n/**\n * Its units stay by an entity, by its name (`world.named`) or its id: a unit they follow, a building they hold round\n * (within `radius`, 12 when left out), fighting what comes near it. While the entity stands: once it is gone, its units\n * are let go of. Its units: those near it as it is first picked (within 20), or what `units` say\n *\n * @beta\n */\nexport function guard(entity: string | number, options: MissionPartOptions & { radius?: number } = {}): AiModuleDef {\n\tconst id = options.id ?? `mission.guard:${entity}`\n\treturn part(id, 'guard', (_ai, memory) => {\n\t\tconst target = (ai: Brain): EntityState | undefined => {\n\t\t\tconst found = typeof entity === 'string' ? ai.view.named(entity) : ai.view.byId(entity)\n\t\t\treturn found && found.hp > 0 ? found : undefined\n\t\t}\n\t\tconst at = (ai: Brain) => {\n\t\t\tconst found = target(ai)\n\t\t\treturn found && point(found)\n\t\t}\n\t\tconst radius = options.radius ?? 12\n\t\tconst claim = ownUnits(\n\t\t\tmemory,\n\t\t\toptions,\n\t\t\t() => ({ near: typeof entity === 'string' ? entity : undefined, within: 20 }),\n\t\t\tat,\n\t\t\t() => 20\n\t\t)\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight,\n\t\t\t\tconsiderations: [...whenOf(options.when), consider('what it guards stands', (ai) => (target(ai) ? 1 : 0), curve.step(1))],\n\t\t\t\tclaims: {\n\t\t\t\t\tunits: (ai, available) => {\n\t\t\t\t\t\t// by id, with no name to look near: the nearest fighters to it, as data with `near` would\n\t\t\t\t\t\tif (typeof entity === 'number' && !options.units && !memory.took) {\n\t\t\t\t\t\t\tconst found = target(ai)\n\t\t\t\t\t\t\treturn found ? available.units().alive().fighters().near(found, 20).items : []\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn claim(ai, available)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tconst { squad } = muster(ai, id, memory, claimed.units, options, () => claim(ai, ai.goals.pool()))\n\t\t\t\t\tconst guarded = target(ai)!\n\t\t\t\t\tconst moves = ai.view.def(guarded).kind === 'unit' && (ai.view.strength.statsOf(guarded).moveSpeed ?? 0) > 0\n\t\t\t\t\t// a unit it follows; a building it holds round. Given again once a task of its own is over\n\t\t\t\t\tif (!squad.idle) return\n\t\t\t\t\tif (moves) squad.escort(guarded.id)\n\t\t\t\t\telse squad.defend(point(guarded), radius)\n\t\t\t\t}\n\t\t\t}),\n\t\t\tinspect: () => ({ guards: entity })\n\t\t}\n\t})\n}\n\n/**\n * What an ambush does once the fight it sprang is over: `return` to its place and wait again (the default), `stay`\n * where it is, or an action (a word it tells itself, `{ say: 'attack' }`, or a function of the brain), done once\n *\n * @beta\n */\nexport type AmbushThen = 'return' | 'stay' | AiAction\n\n/**\n * Its units wait at a place on hold (they hit what walks into reach and move for nothing), and spring once a rival's\n * unit comes within `radius` of it (or once `trigger` holds): they go for the intruders, fighting what they meet. Once\n * that fight is over, `then` (`AmbushThen`). `once`: it springs the first time only. Its units: those at the place as it\n * is first picked, or what `units` say\n *\n * @beta\n */\nexport function ambush(\n\tplace: MissionPlace,\n\toptions: MissionPartOptions & { radius?: number; trigger?: AiCondition; then?: AmbushThen; once?: boolean } = {}\n): AiModuleDef {\n\tconst id = options.id ?? `mission.ambush:${nameOf(place)}`\n\tconst then = options.then ?? 'return'\n\treturn part(id, 'ambush', (_ai, memory) => {\n\t\tconst reach = (ai: Brain) => reachOf(ai, place, options.radius)\n\t\tconst at = (ai: Brain) => placeOf(ai, place)\n\t\tconst claim = ownUnits(memory, options, (ai) => ({ near: place, within: reach(ai) + TAKE_PAST }), at, reach)\n\t\t/** The rivals' units in reach of the place: what springs it, and what it goes for */\n\t\tconst intruders = (ai: Brain, there: Vec2) => ai.view.enemies.units().alive().near(there, reach(ai))\n\t\tconst wait = (squad: Squad, there: Vec2, came: number[]) => {\n\t\t\tif (squad.current?.kind !== 'hold' || squad.idle) squad.hold(there)\n\t\t\t// its own back from elsewhere: to the place, and on hold there (the hold of the task holds where a unit stands)\n\t\t\telse if (came.length) {\n\t\t\t\tsquad.order({ type: 'move', point: there }, came)\n\t\t\t\tsquad.order({ type: 'hold' }, came, true)\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight,\n\t\t\t\tconsiderations: [...whenOf(options.when), consider('it knows where the place is', (ai) => (at(ai) ? 1 : 0), curve.step(1))],\n\t\t\t\tclaims: { units: claim },\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tconst { squad, came } = muster(ai, id, memory, claimed.units, options, () => claim(ai, ai.goals.pool()))\n\t\t\t\t\tconst there = at(ai)!\n\t\t\t\t\tif (memory.sprung === undefined) {\n\t\t\t\t\t\tconst done = options.once && (memory.times ?? 0) > 0\n\t\t\t\t\t\tif (done) {\n\t\t\t\t\t\t\tif (squad.idle) squad.hold()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst coming = intruders(ai, there)\n\t\t\t\t\t\tconst sprung = options.trigger !== undefined ? evaluate(options.trigger, ai) : coming.length > 0\n\t\t\t\t\t\tif (!sprung) return wait(squad, there, came)\n\t\t\t\t\t\tmemory.sprung = ai.tick\n\t\t\t\t\t\tmemory.times = (memory.times ?? 0) + 1\n\t\t\t\t\t\t// for the intruders where it sees them; else (a trigger of its own) the nearest rival it sees, else its place\n\t\t\t\t\t\tconst target = coming.centre() ?? ai.view.enemies.units().alive().nearest(there) ?? there\n\t\t\t\t\t\tai.decide(`${id} springs: ${coming.length} in reach, at ${where(target)}`, { kind: 'mission' })\n\t\t\t\t\t\tsquad.attack(point(target))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// sprung: the fight goes on while its task does; once over, what then\n\t\t\t\t\tif (!squad.idle) return\n\t\t\t\t\tmemory.sprung = undefined\n\t\t\t\t\tif (then === 'return' && !options.once) {\n\t\t\t\t\t\tai.decide(`${id} goes back to wait`, { kind: 'mission' })\n\t\t\t\t\t\treturn wait(squad, there, [])\n\t\t\t\t\t}\n\t\t\t\t\tif (then !== 'return' && then !== 'stay' && !memory.acted) {\n\t\t\t\t\t\tmemory.acted = true\n\t\t\t\t\t\tact(ai, then)\n\t\t\t\t\t}\n\t\t\t\t\tsquad.hold()\n\t\t\t\t}\n\t\t\t}),\n\t\t\tinspect: () => ({\n\t\t\t\tplace: typeof place === 'string' ? place : point(place),\n\t\t\t\t...(memory.sprung !== undefined && { sprung: memory.sprung }),\n\t\t\t\ttimes: memory.times ?? 0\n\t\t\t})\n\t\t}\n\t})\n}\n\n/**\n * Where a wave goes: a place (a point, or a name), or a function of the brain. The nearest building of a rival's it\n * knows of when left out, else the nearest rival it sees, else the first base the seat was told (`AiOptions.enemyBases`)\n *\n * @beta\n */\nexport type MissionTarget = MissionPlace | ((ai: Brain) => Vec2 | undefined)\n\n/** Where a wave goes from a place */\nfunction targetOf(ai: Brain, target: MissionTarget | undefined, from: Vec2): Vec2 | undefined {\n\tif (typeof target === 'function') return target(ai)\n\tif (target !== undefined) return placeOf(ai, target)\n\tconst known = ai.view.enemies.known().buildings().nearest(from) ?? ai.view.enemies.units().alive().nearest(from)\n\tif (known) return point(known)\n\tconst told = ai.options.enemyBases?.[0]\n\treturn told && point(told)\n}\n\n/**\n * The units that come out of a spawner (what the mission's own rules spawn there, or what a building there trains),\n * gathered there and sent as a wave: once there are as many as `group` says (a number, or so many of each type or\n * role: `{ footman: 4, caster: 1 }`; 4 when left out), or, with `every`, every so many seconds with what has gathered\n * (at least `minForces` of the group: a share, any when left out). A wave goes for `target` (`MissionTarget`) and, once\n * that is cleared, for the next it knows of. `first`: seconds before the first wave may go (`every`, else none). Nothing\n * is trained or built: a mission with no economy feeds it\n *\n * @beta\n */\nexport function waveFrom(\n\tsource: MissionPlace,\n\toptions: Omit<MissionPartOptions, 'units' | 'refill'> & {\n\t\tgroup?: number | Record<string, number>\n\t\tevery?: number\n\t\tminForces?: number\n\t\tfirst?: number\n\t\ttarget?: MissionTarget\n\t\tradius?: number\n\t} = {}\n): AiModuleDef {\n\tconst id = options.id ?? `mission.wave:${nameOf(source)}`\n\tconst group = options.group ?? 4\n\tconst size = typeof group === 'number' ? group : Object.values(group).reduce((sum, n) => sum + n, 0)\n\treturn part(id, 'wave', (_ai, memory) => {\n\t\tconst from = (ai: Brain) => placeOf(ai, source)\n\t\tconst reach = (ai: Brain) => reachOf(ai, source, options.radius ?? SPAWN_REACH)\n\t\t/** Whether a unit is of the group: any fighter for a number, else of a type or role it names */\n\t\tconst fits = (ai: Brain, entity: EntityState) =>\n\t\t\ttypeof group === 'number'\n\t\t\t\t? ai.view.hasRole(entity, 'soldier') || ai.view.hasRole(entity, 'hero')\n\t\t\t\t: Object.keys(group).some((kind) => entity.type === kind || ai.view.hasRole(entity, kind as AiRole))\n\t\t/** What came out of the spawner and no one holds yet */\n\t\tconst come = (ai: Brain, available: UnitSet) => {\n\t\t\tconst at = from(ai)\n\t\t\tif (!at) return []\n\t\t\tconst held = new Set(ai.squads.of(id).squads.flatMap((squad) => squad.data.units))\n\t\t\treturn available\n\t\t\t\t.units()\n\t\t\t\t.alive()\n\t\t\t\t.near(at, reach(ai))\n\t\t\t\t.where((entity) => !held.has(entity.id) && !ai.goals.holder(entity.id) && fits(ai, entity)).items\n\t\t}\n\t\t/** Whether the gathered make a wave now: the group whole, or the time come with enough of it */\n\t\tconst ready = (ai: Brain, gathered: readonly EntityState[]) => {\n\t\t\tif (!gathered.length) return false\n\t\t\tconst whole =\n\t\t\t\ttypeof group === 'number'\n\t\t\t\t\t? gathered.length >= group\n\t\t\t\t\t: Object.entries(group).every(\n\t\t\t\t\t\t\t([kind, n]) => gathered.filter((entity) => entity.type === kind || ai.view.hasRole(entity, kind as AiRole)).length >= n\n\t\t\t\t\t\t)\n\t\t\tconst last = memory.last ?? ai.tick\n\t\t\tconst wait = (memory.sent ?? 0) === 0 ? (options.first ?? options.every ?? 0) : (options.every ?? 0)\n\t\t\tconst time = ai.tick - last >= Math.round(wait * ai.session.tickRate)\n\t\t\tif (!time) return false\n\t\t\tif (whole) return true\n\t\t\treturn options.every !== undefined && gathered.length >= Math.max(1, Math.ceil(size * (options.minForces ?? 0)))\n\t\t}\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight,\n\t\t\t\tconsiderations: [...whenOf(options.when), consider('it knows where the spawner is', (ai) => (from(ai) ? 1 : 0), curve.step(1))],\n\t\t\t\tclaims: { units: (ai, available) => come(ai, available) },\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tmemory.last ??= ai.tick\n\t\t\t\t\tmemory.took = true\n\t\t\t\t\tconst at = from(ai)!\n\t\t\t\t\t// what came out since: into the gathering, on hold where it stands\n\t\t\t\t\tconst fresh = come(ai, ai.goals.pool())\n\t\t\t\t\tlet gathering = ai.squads.named(id)\n\t\t\t\t\tconst waves = ai.squads.of(id).squads.filter((squad) => squad !== gathering)\n\t\t\t\t\tconst sent = new Set(waves.flatMap((squad) => squad.data.units))\n\t\t\t\t\tconst waiting = [...[...claimed.units.ids()].filter((unit) => !sent.has(unit)), ...fresh.map((entity) => entity.id)]\n\t\t\t\t\tif (waiting.length) {\n\t\t\t\t\t\tif (!gathering) gathering = claimed.squad(id, waiting).hold()\n\t\t\t\t\t\telse gathering.add(waiting, 'came out')\n\t\t\t\t\t}\n\t\t\t\t\tmemory.units = [...new Set([...sent, ...(gathering?.data.units ?? [])])].sort((a, b) => a - b)\n\t\t\t\t\t// a wave that cleared what it went for goes for the next; with nothing known, it stands where it is\n\t\t\t\t\tfor (const wave of waves) {\n\t\t\t\t\t\tif (!wave.idle || !wave.centre()) continue\n\t\t\t\t\t\tconst next = targetOf(ai, options.target, wave.centre()!)\n\t\t\t\t\t\tif (next) wave.attack(next)\n\t\t\t\t\t\telse wave.hold()\n\t\t\t\t\t}\n\t\t\t\t\tconst gathered = gathering?.units().items ?? []\n\t\t\t\t\tif (!gathering || !ready(ai, gathered)) return\n\t\t\t\t\tconst target = targetOf(ai, options.target, at)\n\t\t\t\t\tif (!target) return\n\t\t\t\t\tconst n = (memory.sent ?? 0) + 1\n\t\t\t\t\tmemory.sent = n\n\t\t\t\t\tmemory.last = ai.tick\n\t\t\t\t\tclaimed.squad(`${id} ${n}`, gathered).attack(target)\n\t\t\t\t\tai.decide(`${id} sends wave ${n} of ${gathered.length} at ${where(target)}`, { kind: 'mission' })\n\t\t\t\t}\n\t\t\t}),\n\t\t\tinspect: () => ({ source: typeof source === 'string' ? source : point(source), sent: memory.sent ?? 0, last: memory.last })\n\t\t}\n\t})\n}\n\n/**\n * When the condition holds, its units run: to `to` (a place), else home, else away from the nearest rival; and stand\n * there while it holds. Once it no longer does, they are let go of, and the parts that had them take them back. An\n * urgent goal worth 10: it takes its units from any other. Its units: its fighters, or what `units` say\n *\n * @beta\n */\nexport function fleeWhen(condition: AiCondition, options: Omit<MissionPartOptions, 'refill'> & { to?: MissionPlace } = {}): AiModuleDef {\n\tconst id = options.id ?? 'mission.flee'\n\treturn part(id, 'flee', () => {\n\t\t/** Where to run: the place, home, or away from the nearest rival, on the map */\n\t\tconst refuge = (ai: Brain, squad: Squad): Vec2 | undefined => {\n\t\t\tconst to = options.to !== undefined ? placeOf(ai, options.to) : undefined\n\t\t\tif (to) return to\n\t\t\tconst home = ai.view.home()\n\t\t\tif (home) return point(home)\n\t\t\tconst middle = squad.centre()\n\t\t\tconst foe = middle && ai.view.enemies.units().alive().nearest(middle)\n\t\t\tif (!middle || !foe) return undefined\n\t\t\tconst dx = middle.x - foe.x\n\t\t\tconst dz = middle.z - foe.z\n\t\t\tconst length = Math.sqrt(dx * dx + dz * dz) || 1\n\t\t\tconst { width, depth } = ai.session.terrain\n\t\t\treturn {\n\t\t\t\tx: Math.min(width - 1, Math.max(1, middle.x + (dx / length) * FLEE_AWAY)),\n\t\t\t\tz: Math.min(depth - 1, Math.max(1, middle.z + (dz / length) * FLEE_AWAY))\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tgoal: defineGoal({\n\t\t\t\tid,\n\t\t\t\tweight: options.weight ?? 10,\n\t\t\t\turgent: true,\n\t\t\t\tconsiderations: [consider('it is time to run', (ai) => (evaluate(condition, ai) ? 1 : 0), curve.step(1)), ...whenOf(options.when)],\n\t\t\t\tclaims: { units: (ai, available) => choose(ai, options.units ?? {}, available, ai.view.home(), REACH) },\n\t\t\t\tcommitment: 0,\n\t\t\t\trun: (ai, claimed) => {\n\t\t\t\t\tif (!claimed.first) {\n\t\t\t\t\t\t// those that ran and stand there now: on hold\n\t\t\t\t\t\tconst squad = ai.squads.named(id)\n\t\t\t\t\t\tif (squad?.idle) squad.hold()\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst squad = claimed.squad(id, claimed.units)\n\t\t\t\t\tconst to = refuge(ai, squad)\n\t\t\t\t\tai.decide(`${id}: ${claimed.units.length} run${to ? ` to ${where(to)}` : ''}`, { kind: 'mission' })\n\t\t\t\t\tif (to) squad.retreat(to, 'told to run')\n\t\t\t\t\telse squad.hold()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}\n\n/**\n * When the condition holds, the computer gives up: the engine's `surrender` command, as a player's, once. Out of the\n * game as if beaten\n *\n * @beta\n */\nexport function surrenderWhen(condition: AiCondition, options: { id?: string } = {}): AiModuleDef {\n\tconst id = options.id ?? 'mission.surrender'\n\treturn part(id, 'surrender', (ai, memory) => ({\n\t\tthink: () => {\n\t\t\tif (memory.done || !evaluate(condition, ai)) return\n\t\t\tmemory.done = true\n\t\t\tai.decide(`${id}: gives up`, { kind: 'mission' })\n\t\t\tai.send({ type: 'surrender' })\n\t\t},\n\t\tinspect: () => ({ done: !!memory.done })\n\t}))\n}\n\n/**\n * A computer player for a mission: a brain (`defineBrain`) of what every mission's computer has (its rules, the words\n * every brain may be told, the goals' picker, squads, micro) and the parts it is given (`modules`: `holdPosition`,\n * `patrol`, `guard`, `ambush`, `waveFrom`, `fleeWhen`, `surrenderWhen`, any module of the kit's or of its own). Nothing\n * builds, trains, gathers, scouts or answers raids on its bases unless a module for it is given (`economy()`,\n * `scouting()`, `defence()`). Everything else of `BrainDef` as for any brain (`goals`, `micro`, `without`, `knowledge`)\n *\n * @beta\n */\nexport function missionBrain(def: MissionBrainDef): BrainDef {\n\tconst { modules = [], ...rest } = def\n\treturn defineBrain({\n\t\t...rest,\n\t\tmodules: [\n\t\t\t// its own rules first, as the melee brain's: what a rule takes is not given orders by the rest\n\t\t\tdefineModule('rules', (ai: Brain) => (rules(ai.def.rules ?? []) as (ai: Brain) => AiModule)(ai)),\n\t\t\twords(),\n\t\t\t...modules,\n\t\t\tgoals(),\n\t\t\tsquads(),\n\t\t\tmicro()\n\t\t]\n\t})\n}\n","import { exp } from '#engine/exactMath'\nimport { farthestReach } from '#engine/attacks'\nimport { Team } from './team'\nimport type { Lane } from '#engine/lanes'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain, type BrainDef, type BrainExtension } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule, moduleKey } from './module'\nimport { defineBrain } from './define'\nimport { consider, curve, defineGoal, type GoalDef, goals } from './goals'\nimport { micro, type TargetPicker } from './micro'\nimport { rules, words } from './rules'\nimport { type Squad, squads } from './squads'\nimport { defineTask, type TaskState } from './task'\nimport { team } from './team'\nimport type { UnitSet } from './view'\nimport { heroOfState } from '#engine/hero'\nimport { point, where } from './geometry'\nimport { LANE_ENGAGED, RESEND } from './reach'\n\n/*\n * The lanes brain (AI plan, D5): a computer player for a game of lanes, as in a MOBA (`withLanes`, `docs/use-cases/\n * lanes.md`). No economy, no building, no army of its own to train: each player is a hero or two, and the waves of\n * minions walk the lanes by themselves (the lanes' rules send them). What a player does is where its hero goes: along\n * a lane behind its own wave, back home when hurt, to an ally's hero in a fight, to a camp of creeps when there is no\n * wave to walk with. It is the proof that the kit is not a melee's alone: the same goals, squads, micro and team\n * play, without the economy, the plans or the waves of D2.\n *\n * Its modules: its rules and the words every brain may be told (B2), `lanes` (this file: the lanes read, the heroes'\n * rest, and the goals below put on the picker), `team` (C5: the team's board, people's pings), the picker (B1), squads\n * (C1) and micro (C2: whom a hero hits, its spells, its potions, the shop, its skills). The minions are the lanes', not\n * the computer's: no goal claims them (only what it `commands`, its heroes), so they walk on as the lanes sent them.\n *\n * **Its goals**, one picker, each holding the heroes it runs with (B1's \"who may move a unit\"):\n *\n * - `lanes.push:<lane>` (one a lane, 1): the hero walks the lane a little behind its side's wave (the minion of its side\n * furthest along it, its **front**), fighting what comes; with no wave there, it waits by its side's furthest tower on\n * the lane. It never steps into reach of one of their towers with no minion of its side there to take the shots, and\n * falls back along the lane once outmatched where it stands (`backOdds`). Scored by the wave of its side on the lane,\n * the odds at its front, the allies' heroes there already (two heroes of a side on one lane leave another lane alone)\n * and how far the hero is from it: the lane with the most of its side's strength, and no ally on it, comes first.\n * - `lanes.back` (urgent, 10): a hero under `backAt` of its health goes home (by an ability that takes it home, where\n * it has one and nothing is near, else on foot) and rests there until it is back at `returnAt`, or `restFor` seconds\n * have passed: at home, micro's shopping buys it a potion and drinks it.\n * - `lanes.help` (1.3): an ally's hero in a fight with one of theirs, near enough, where the odds with it are good: the\n * hero goes with it (the `escort` task), and back to its lane once the fight is over. A person's ping for help (the\n * team's board) is one too.\n * - `lanes.camp` (0.6): with no wave of its side on any lane (before the first, between two), the hero takes the nearest\n * camp of creeps it can beat.\n *\n * **Whom a hero hits** (`lanesTargets`, micro's picker): a minion its next hit kills (a last hit: what gives the\n * bounty), else one of their heroes not under one of their towers (a hero hit there turns the towers on the one who hit\n * it: `withLanes`), else a building (a tower its side's minions are taking the shots of, their core), else the weakest\n * of the rest. Never a hero or anything else under their tower with no minion of its side in that tower's reach.\n *\n * Every number has a data form (`LanesPlayOptions`, the seat's `AiOptions.lanes` over the module's); which units it\n * commands and where home is have a function form.\n */\n\n/**\n * How a lanes brain plays (`lanesPlay(options)`, the seat's `AiOptions.lanes` over it): its heroes' rest, how far it\n * goes for an ally or a camp, how near its wave it walks. Data, but for `units` and `home` as functions\n *\n * @beta\n */\nexport interface LanesPlayOptions {\n\t/**\n\t * Which of its units it commands: its heroes when left out. The rest (the minions) are the lanes', and walk as they\n\t * were sent\n\t */\n\tunits?: (ai: Brain, unit: EntityState) => boolean\n\t/** Where its heroes go to rest: a point, or a function. Its side's building by its side's ends of the lanes when left out (a core) */\n\thome?: Vec2 | ((ai: Brain) => Vec2 | undefined)\n\t/** Only these lanes, by their path's name: every lane of the map when left out */\n\tlanes?: string[]\n\t/** The share of its health under which a hero goes home to rest: 0.35 */\n\tbackAt?: number\n\t/** The share at which a resting hero goes back out: 0.85 */\n\treturnAt?: number\n\t/** Seconds a hero rests at home at most, healed or not: 40 */\n\trestFor?: number\n\t/** Whether a hero going home uses an ability that takes it there (a recall), where nothing hostile is near: yes when left out */\n\trecall?: boolean\n\t/** The odds where a hero stands on its lane under which it falls back along it: 0.3 */\n\tbackOdds?: number\n\t/** How many cells behind its side's wave a hero walks: 3 */\n\tbehind?: number\n\t/** An ally's hero in a fight it goes to: within `reach` cells of it (30), where the odds with it are at least `odds` (0.4). `false` never */\n\thelp?: false | { reach?: number; odds?: number }\n\t/** A camp it takes with no wave to walk with: within `reach` cells (50), where the odds against it are at least `odds` (0.6). `false` never */\n\tcamps?: false | { reach?: number; odds?: number }\n\t/** Whether a hero hits the minion its next hit kills before anything else (a last hit): yes when left out */\n\tlastHits?: boolean\n}\n\n/**\n * What the lanes module remembers between thinks, as a save keeps it: the heroes resting, since when; when each last\n * used an ability that takes it home\n *\n * @beta\n */\nexport interface LanesPlayMemory {\n\tv: 1\n\t/** The heroes resting, by id: the tick they turned for home */\n\tresting: Record<string, number>\n\t/** When each hero last set off home by its recall, by id */\n\trecalled: Record<string, number>\n\t/** When each resting hero was last sent home on foot, by id */\n\tsent: Record<string, number>\n}\n\n/**\n * A lane as one side reads it (`LanesPlay.lanes`): the path, measured from that side's end (`from`: the end its own\n * spawner stands at), its length\n *\n * @beta\n */\nexport interface LaneSide {\n\t/** The name of its path: what the goal and squad of the lane are named by (`lanes.push:mid`) */\n\tpath: string\n\tpoints: readonly Vec2[]\n\t/** The end of the lane that is its side's: 0 the first point's, 1 the last's */\n\tfrom: 0 | 1\n\t/** Cells from end to end, along it */\n\tlength: number\n}\n\n/**\n * A lane as it stands this think, for one side: its waves' fronts (in cells along it from its side's end), who is on\n * it, the towers by it\n *\n * @beta\n */\nexport interface LaneState {\n\tlane: LaneSide\n\t/** How far along its side's furthest minion is: none with no minion of its side on the lane */\n\tfront?: number\n\t/** How far along their nearest minion is: none with none of theirs on it */\n\ttheirFront?: number\n\t/** Its side's minions on it (the player's own and its allies'), and theirs */\n\tours: EntityState[]\n\ttheirs: EntityState[]\n\t/** The heroes on it: its allies' (the player's own left out), and theirs */\n\tallies: EntityState[]\n\tenemies: EntityState[]\n\t/** The towers by it, its side's and theirs (theirs as remembered), with how far along each stands */\n\tourTowers: { tower: EntityState; at: number }[]\n\ttheirTowers: { tower: EntityState; at: number }[]\n}\n\n/** How far from a lane's line a unit is on it */\nconst ON_LANE = 7\n/** How far from a lane's line a tower is by it */\nconst BY_LANE = 9\n/** How near a hero is to where it was sent to be there */\nconst THERE = 4\n/** How far a hero's place on its lane moves before it is sent there again */\nconst MOVED = 4\n/** How near home a hero is home */\nconst HOME = 8\n/** How near an ally's hero one of theirs is for the two to be in a fight */\nconst FIGHTING = 10\n/** How far behind where it stands a hero falls back to, where none of its side's towers is nearer */\nconst FALL_BACK = 14\n/** Seconds between two recalls of a hero: one that was hurt in the channel walks */\nconst RECALL_AGAIN = 10\n\n/**\n * Where a place is along a line of points, and how far off it: `along` in cells from the first point, `off` from the\n * line's nearest point. What every question of a lane comes to\n */\nfunction measure(points: readonly Vec2[], at: Vec2): { along: number; off: number } {\n\tlet best = Infinity\n\tlet along = 0\n\tlet walked = 0\n\tfor (let i = 1; i < points.length; i++) {\n\t\tconst a = points[i - 1]\n\t\tconst dx = points[i].x - a.x\n\t\tconst dz = points[i].z - a.z\n\t\tconst lengthSq = dx * dx + dz * dz\n\t\tconst length = Math.sqrt(lengthSq)\n\t\tconst t = lengthSq > 0 ? Math.min(Math.max(((at.x - a.x) * dx + (at.z - a.z) * dz) / lengthSq, 0), 1) : 0\n\t\tconst ox = at.x - (a.x + dx * t)\n\t\tconst oz = at.z - (a.z + dz * t)\n\t\tconst off = ox * ox + oz * oz\n\t\tif (off < best) {\n\t\t\tbest = off\n\t\t\talong = walked + length * t\n\t\t}\n\t\twalked += length\n\t}\n\treturn { along, off: Math.sqrt(best) }\n}\n\n/** The length of a line of points */\nfunction lengthOf(points: readonly Vec2[]): number {\n\tlet length = 0\n\tfor (let i = 1; i < points.length; i++) length += Math.sqrt(distSq(points[i - 1], points[i]))\n\treturn length\n}\n\n/** The point so far along a line of points from its first */\nfunction pointAlong(points: readonly Vec2[], along: number): Vec2 {\n\tlet left = Math.max(0, along)\n\tfor (let i = 1; i < points.length; i++) {\n\t\tconst a = points[i - 1]\n\t\tconst length = Math.sqrt(distSq(a, points[i]))\n\t\tif (left <= length && length > 0) {\n\t\t\tconst t = left / length\n\t\t\treturn { x: a.x + (points[i].x - a.x) * t, z: a.z + (points[i].z - a.z) * t }\n\t\t}\n\t\tleft -= length\n\t}\n\treturn point(points[points.length - 1])\n}\n\n/**\n * Where a place is on a side's lane: how far along from the side's end, how far off the line\n *\n * @beta\n */\nexport function onLane(lane: LaneSide, at: Vec2): { along: number; off: number } {\n\tconst measured = measure(lane.points, at)\n\treturn { along: lane.from === 0 ? measured.along : lane.length - measured.along, off: measured.off }\n}\n\n/**\n * The point so far along a side's lane from its end\n *\n * @beta\n */\nexport function laneAt(lane: LaneSide, along: number): Vec2 {\n\tconst clamped = Math.min(Math.max(along, 0), lane.length)\n\treturn pointAlong(lane.points, lane.from === 0 ? clamped : lane.length - clamped)\n}\n\n/** A unit's share of its health */\nfunction health(ai: Brain, unit: EntityState): number {\n\tconst max = unit.maxHp ?? ai.view.strength.statsOf(unit).health\n\treturn max > 0 ? unit.hp / max : 1\n}\n\n/** How far a tower reaches: its attack's range and its size, a cell more */\nfunction reachOf(ai: Brain, tower: EntityState): number {\n\treturn farthestReach(ai.view.def(tower), ai.view.strength.statsOf(tower)) + ai.view.def(tower).radius + 1\n}\n\n/** Their towers, as remembered: buildings of theirs that attack */\nconst theirTowers = (ai: Brain): UnitSet =>\n\tai.cache('lanes.theirTowers', () =>\n\t\tai.view.enemies\n\t\t\t.known()\n\t\t\t.buildings()\n\t\t\t.alive()\n\t\t\t.where((_entity, def) => !!def.attacks?.length)\n\t)\n\n/** Whether a place is in reach of one of their towers with no minion of its side in that tower's reach to take the shots */\nfunction exposed(ai: Brain, at: Vec2, pad = 0): boolean {\n\tfor (const tower of theirTowers(ai)) {\n\t\tconst reach = reachOf(ai, tower) + pad\n\t\tif (distSq(tower, at) > reach * reach) continue\n\t\tconst covered = ai.view.all\n\t\t\t.units()\n\t\t\t.alive()\n\t\t\t.near(tower, reachOf(ai, tower))\n\t\t\t.where((unit) => ai.view.isFriendly(unit) && !heroOfState(unit) && !ai.view.def(unit).hero)\n\t\tif (!covered.length) return true\n\t}\n\treturn false\n}\n\n/**\n * Whom a hero of a lanes brain hits (micro's `targets`, the file's comment): the minion its next hit kills, one of their\n * heroes not under their tower, a building (a tower its side's minions take the shots of), the weakest of the rest; never\n * what stands where their tower would turn on it\n *\n * @beta\n */\nexport const lanesTargets =\n\t(options: Pick<LanesPlayOptions, 'lastHits'> = {}): TargetPicker =>\n\t(ai, squad, foes) => {\n\t\tconst { view } = ai\n\t\tconst hitters = squad.units()\n\t\tconst middle = hitters.centre()\n\t\tif (!middle) return undefined\n\t\t// what it may hit at all: not where their tower would turn on it (a hero hit under it), not a tower with nothing to tank it\n\t\tconst safe = foes.where((foe, def) => {\n\t\t\t// a tower with its side's minions in its reach to take its shots; any other building out of their towers' reach\n\t\t\tif (def.kind === 'building') return def.attacks?.length ? !exposed(ai, foe, -reachOf(ai, foe)) : !exposed(ai, foe)\n\t\t\tif (def.hero || heroOfState(foe))\n\t\t\t\treturn !theirTowers(ai).some((tower) => {\n\t\t\t\t\tconst reach = reachOf(ai, tower) + 2\n\t\t\t\t\treturn distSq(tower, foe) <= reach * reach\n\t\t\t\t})\n\t\t\treturn !exposed(ai, foe)\n\t\t})\n\t\tif (!safe.length) return undefined\n\t\tconst nearest = (set: readonly EntityState[]) =>\n\t\t\tset.reduce<EntityState | undefined>((best, each) => (!best || distSq(each, middle) < distSq(best, middle) ? each : best), undefined)\n\t\t// a last hit: a minion the hardest hitter's next blow kills\n\t\tif (options.lastHits !== false) {\n\t\t\tconst blow = Math.max(0, ...hitters.map((unit) => view.strength.statsOf(unit).attackDamage))\n\t\t\tconst dying = safe.where((foe, def) => def.kind === 'unit' && !def.hero && !heroOfState(foe) && foe.hp <= blow)\n\t\t\tconst last = nearest(dying.items)\n\t\t\tif (last) return last\n\t\t}\n\t\tconst heroes = safe.where((foe, def) => !!def.hero || !!heroOfState(foe))\n\t\tif (heroes.length) return heroes.items.reduce((best, each) => (health(ai, each) < health(ai, best) ? each : best))\n\t\tconst buildings = safe.buildings()\n\t\tif (buildings.length) return nearest(buildings.items)\n\t\treturn safe.items.reduce((best, each) =>\n\t\t\teach.hp < best.hp || (each.hp === best.hp && distSq(each, middle) < distSq(best, middle)) ? each : best\n\t\t)\n\t}\n\n/**\n * The lanes of a lanes brain, read as its side sees them, and what its heroes do on them (`ai.module('lanes')`'s\n * `play`): the module's goals read it\n *\n * @beta\n */\nexport class LanesPlay {\n\treadonly memory: LanesPlayMemory = { v: 1, resting: {}, recalled: {}, sent: {} }\n\tprivate sides: LaneSide[] | undefined\n\n\tconstructor(\n\t\t/** The brain it plays for */\n\t\treadonly ai: Brain,\n\t\t/** How it plays: the module's, the seat's over it */\n\t\treadonly options: LanesPlayOptions\n\t) {}\n\n\t/** The lanes as its side reads them: each measured from the end its side's spawner stands at. None it has no end of */\n\tlanes(): readonly LaneSide[] {\n\t\tif (this.sides) return this.sides\n\t\tconst { view } = this.ai\n\t\tconst only = this.options.lanes\n\t\tconst ours = (end: Lane['ends'][number]) => !!end && (end.player === view.playerId || view.player(end.player)?.relation === 'ally')\n\t\tconst found: LaneSide[] = []\n\t\tfor (const lane of view.lanes()) {\n\t\t\tif (only && !only.includes(lane.path)) continue\n\t\t\tconst from = ours(lane.ends[0]) ? 0 : ours(lane.ends[1]) ? 1 : undefined\n\t\t\tif (from === undefined) continue\n\t\t\tfound.push({ path: lane.path, points: lane.points, from, length: lengthOf(lane.points) })\n\t\t}\n\t\t// found once the players are known: a view with no players yet (before the first snapshot) is asked again\n\t\tif (view.players.length) this.sides = found\n\t\treturn found\n\t}\n\n\t/** A lane of its side's, by its path's name */\n\tlane(path: string): LaneSide | undefined {\n\t\treturn this.lanes().find((lane) => lane.path === path)\n\t}\n\n\t/** The units it commands: its heroes, or what `units` says. Alive */\n\tcommanded(units: UnitSet = this.ai.view.mine): UnitSet {\n\t\tconst { units: commands } = this.options\n\t\tconst alive = units.units().alive()\n\t\treturn commands ? alive.where((unit) => commands(this.ai, unit)) : alive.heroes()\n\t}\n\n\t/**\n\t * Where its heroes rest: `home`, else its side's building nearest the middle of its side's ends of the lanes (a core),\n\t * else that middle, else its first building\n\t */\n\thome(): Vec2 | undefined {\n\t\tconst { home } = this.options\n\t\tif (home) return typeof home === 'function' ? home(this.ai) : point(home)\n\t\tconst ends = this.lanes().map((lane) => laneAt(lane, 0))\n\t\tif (ends.length) {\n\t\t\tconst middle = { x: ends.reduce((sum, end) => sum + end.x, 0) / ends.length, z: ends.reduce((sum, end) => sum + end.z, 0) / ends.length }\n\t\t\t// the building of its side there (a core, a fountain), where there is one: what heals and guards it\n\t\t\tconst { view } = this.ai\n\t\t\tconst building = view.all\n\t\t\t\t.buildings()\n\t\t\t\t.alive()\n\t\t\t\t.where((entity) => view.isFriendly(entity))\n\t\t\t\t.near(middle, HOME * 2)\n\t\t\t\t.nearest(middle)\n\t\t\treturn building ? point(building) : middle\n\t\t}\n\t\tconst first = this.ai.view.home()\n\t\treturn first && point(first)\n\t}\n\n\t/** Each lane as it stands this think: fronts, minions, heroes, towers. Once a think */\n\tstates(): readonly LaneState[] {\n\t\treturn this.ai.cache('lanes.states', () => this.lanes().map((lane) => this.stateOf(lane)))\n\t}\n\n\t/** One lane as it stands this think */\n\tstate(path: string): LaneState | undefined {\n\t\treturn this.states().find((state) => state.lane.path === path)\n\t}\n\n\tprivate stateOf(lane: LaneSide): LaneState {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst state: LaneState = { lane, ours: [], theirs: [], allies: [], enemies: [], ourTowers: [], theirTowers: [] }\n\t\tfor (const unit of view.all.units().alive()) {\n\t\t\tconst friendly = view.isFriendly(unit)\n\t\t\tif (!friendly && !(view.isHostile(unit) && !view.isCreep(unit))) continue\n\t\t\tconst { along, off } = onLane(lane, unit)\n\t\t\tif (off > ON_LANE) continue\n\t\t\tconst hero = !!view.def(unit).hero || !!heroOfState(unit)\n\t\t\tif (hero) {\n\t\t\t\tif (!friendly) state.enemies.push(unit)\n\t\t\t\telse if (unit.owner !== view.playerId) state.allies.push(unit)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (friendly) {\n\t\t\t\tstate.ours.push(unit)\n\t\t\t\tif (state.front === undefined || along > state.front) state.front = along\n\t\t\t} else {\n\t\t\t\tstate.theirs.push(unit)\n\t\t\t\tif (state.theirFront === undefined || along < state.theirFront) state.theirFront = along\n\t\t\t}\n\t\t}\n\t\tconst towers = view.all\n\t\t\t.known()\n\t\t\t.buildings()\n\t\t\t.alive()\n\t\t\t.where((_entity, def) => !!def.attacks?.length)\n\t\tfor (const tower of towers) {\n\t\t\tconst { along, off } = onLane(lane, tower)\n\t\t\tif (off > BY_LANE) continue\n\t\t\tif (view.isFriendly(tower)) state.ourTowers.push({ tower, at: along })\n\t\t\telse if (view.isHostile(tower) && !view.isCreep(tower)) state.theirTowers.push({ tower, at: along })\n\t\t}\n\t\treturn state\n\t}\n\n\t/**\n\t * Where a hero walks on a lane now: a little behind its side's front; with no wave there, by its side's furthest tower\n\t * on it (or a little out of its end); never into reach of a tower of theirs that no minion of its side is in reach of\n\t */\n\tspot(path: string): Vec2 | undefined {\n\t\tconst state = this.state(path)\n\t\tif (!state) return undefined\n\t\tconst { lane } = state\n\t\tconst behind = this.options.behind ?? 3\n\t\tlet along: number\n\t\tif (state.front !== undefined) along = state.front - behind\n\t\telse along = Math.max(6, ...state.ourTowers.map((each) => each.at - 2))\n\t\t// not into a tower's reach that its side's minions are not taking the shots of\n\t\tfor (const { tower, at } of state.theirTowers) {\n\t\t\tconst reach = reachOf(this.ai, tower)\n\t\t\tconst covered = state.ours.some((unit) => distSq(unit, tower) <= reach * reach)\n\t\t\tif (!covered && along > at - reach - 1) along = at - reach - 1\n\t\t}\n\t\treturn laneAt(lane, Math.max(0, along))\n\t}\n\n\t/**\n\t * What is at stake on a lane, 0..1: how far along its side's wave is (a tower of theirs to take, their core), or how\n\t * near its side's end theirs is (its own towers under attack), whichever is more\n\t */\n\tstake(path: string): number {\n\t\tconst state = this.state(path)\n\t\tif (!state) return 0\n\t\tconst { length } = state.lane\n\t\tconst ours = state.front === undefined ? 0 : state.front / length\n\t\tconst theirs = state.theirFront === undefined ? 0 : 1 - state.theirFront / length\n\t\treturn Math.min(1, Math.max(ours, theirs))\n\t}\n\n\t/** Where a hero outmatched on a lane falls back to: its side's nearest tower behind it, or so far back along it */\n\tfallBack(path: string, from: Vec2): Vec2 | undefined {\n\t\tconst state = this.state(path)\n\t\tif (!state) return undefined\n\t\tconst { along } = onLane(state.lane, from)\n\t\tconst behind = state.ourTowers.filter((each) => each.at < along - 2).sort((a, b) => b.at - a.at)[0]\n\t\treturn behind ? laneAt(state.lane, behind.at - 2) : laneAt(state.lane, along - FALL_BACK)\n\t}\n\n\t/** The odds of its side against theirs where a unit stands (`Strength.odds`): their towers that reach there count */\n\toddsAt(at: Vec2, reach = LANE_ENGAGED): number {\n\t\tconst { view } = this.ai\n\t\tconst near = view.all.units().alive().near(at, reach)\n\t\tconst ours = near.where((unit) => view.isFriendly(unit))\n\t\tconst theirs = [...near.where((unit) => view.isHostile(unit)).items]\n\t\tfor (const tower of theirTowers(this.ai)) {\n\t\t\tconst towerReach = reachOf(this.ai, tower)\n\t\t\tif (distSq(tower, at) <= towerReach * towerReach) theirs.push(tower)\n\t\t}\n\t\treturn theirs.length ? view.strength.odds(ours, theirs) : 1\n\t}\n\n\t/** The heroes resting, alive */\n\tresting(): readonly EntityState[] {\n\t\treturn this.commanded().where((hero) => this.memory.resting[hero.id] !== undefined).items\n\t}\n\n\t/** Heroes turned for home, those back out: what the `lanes.back` goal reads. Each think, before the goals */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tconst { memory } = this\n\t\tconst backAt = this.options.backAt ?? 0.35\n\t\tconst returnAt = this.options.returnAt ?? 0.85\n\t\tconst restFor = (this.options.restFor ?? 40) * ai.session.tickRate\n\t\tconst heroes = this.commanded()\n\t\tfor (const id in memory.resting) if (!heroes.has(Number(id))) delete memory.resting[id]\n\t\tfor (const id in memory.recalled) if (!heroes.has(Number(id))) delete memory.recalled[id]\n\t\tfor (const id in memory.sent) if (memory.resting[id] === undefined) delete memory.sent[id]\n\t\tfor (const hero of heroes) {\n\t\t\tconst share = health(ai, hero)\n\t\t\tconst since = memory.resting[hero.id]\n\t\t\tif (since === undefined) {\n\t\t\t\tif (share < backAt) {\n\t\t\t\t\tmemory.resting[hero.id] = ai.tick\n\t\t\t\t\tai.decide(`${hero.type} ${hero.id} goes home to rest at ${Math.round(share * 100)}%`, { kind: 'lanes' })\n\t\t\t\t}\n\t\t\t} else if (share >= returnAt || ai.tick - since >= restFor) {\n\t\t\t\tdelete memory.resting[hero.id]\n\t\t\t\tai.decide(`${hero.type} ${hero.id} rested, back out at ${Math.round(share * 100)}%`, { kind: 'lanes' })\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sends a resting hero home: by an ability that takes it there (one whose effects, at its end, teleport home), where\n\t * it has one ready and nothing hostile is near; else on foot. Nothing while it channels, or once home\n\t */\n\tsendHome(hero: EntityState): void {\n\t\tconst { ai } = this\n\t\tconst home = this.home()\n\t\tif (!home || !hero.own || hero.own.hidden) return\n\t\tif (distSq(hero, home) <= HOME * HOME || hero.own.order === 'cast') return\n\t\tconst recalled = this.memory.recalled[hero.id]\n\t\tconst safe = !ai.view.hostile.alive().near(hero, 12).length\n\t\tif (this.options.recall !== false && safe && (recalled === undefined || ai.tick - recalled >= RECALL_AGAIN * ai.session.tickRate)) {\n\t\t\tconst ability = hero.own.abilities?.find((state) => {\n\t\t\t\tif (state.level < 1 || state.cooldown > 0 || state.charges === 0) return false\n\t\t\t\tconst def = ai.registry.ability(state.id)\n\t\t\t\treturn [...def.effects, ...(def.channel?.finished ?? [])].some((effect) => effect.type === 'teleport' && effect.to === 'home')\n\t\t\t})\n\t\t\tif (ability) {\n\t\t\t\tthis.memory.recalled[hero.id] = ai.tick\n\t\t\t\tai.send({ type: 'cast', entities: [hero.id], ability: ability.id })\n\t\t\t\tai.decide(`${hero.type} ${hero.id} recalls home`, { kind: 'lanes' })\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tif (hero.own.order === 'move') return\n\t\tconst sent = this.memory.sent[hero.id]\n\t\tif (sent !== undefined && ai.tick - sent < RESEND * ai.session.tickRate) return\n\t\tthis.memory.sent[hero.id] = ai.tick\n\t\tai.send({ type: 'order', entities: [hero.id], order: { type: 'move', point: home } })\n\t}\n\n\t/** An ally's hero in a fight one of its heroes could go to: the most hurt, near enough; or a person's call for help */\n\tcall(from: Vec2): Vec2 | undefined {\n\t\tconst help = this.options.help\n\t\tif (help === false) return undefined\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst reach = help?.reach ?? 30\n\t\tconst theirHeroes = view.enemies\n\t\t\t.units()\n\t\t\t.alive()\n\t\t\t.where((unit, def) => !!def.hero || !!heroOfState(unit))\n\t\tlet best: EntityState | undefined\n\t\tfor (const ally of view.allies.units().alive().heroes()) {\n\t\t\tif (distSq(ally, from) > reach * reach || !theirHeroes.near(ally, FIGHTING).length) continue\n\t\t\tif (!best || health(ai, ally) < health(ai, best)) best = ally\n\t\t}\n\t\tif (best) return point(best)\n\t\tconst ping = ai.area(Team).enabled\n\t\t\t? ai\n\t\t\t\t\t.area(Team)\n\t\t\t\t\t.requests('help')\n\t\t\t\t\t.find((request) => request.by === 'ping' && distSq(request.at, from) <= reach * reach)\n\t\t\t: undefined\n\t\treturn ping && point(ping.at)\n\t}\n\n\t/** The ally's hero nearest a place: what a hero helping goes with */\n\tallyAt(at: Vec2): EntityState | undefined {\n\t\treturn this.ai.view.allies.units().alive().heroes().near(at, 2).first()\n\t}\n\n\t/** The nearest camp it may take from a place: not cleared, in reach, its creeps (as seen) beatable */\n\tcamp(hero: EntityState): Vec2 | undefined {\n\t\tconst camps = this.options.camps\n\t\tif (camps === false) return undefined\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst reach = camps?.reach ?? 50\n\t\tconst odds = camps?.odds ?? 0.6\n\t\tlet best: { at: Vec2; d: number } | undefined\n\t\tfor (const camp of view.camps()) {\n\t\t\tif (camp.cleared) continue\n\t\t\tconst d = distSq(camp, hero)\n\t\t\tif (d > reach * reach || (best && d >= best.d)) continue\n\t\t\t// as seen; a camp out of sight by its levels against the hero's\n\t\t\tconst creeps = view.creeps.alive().near(camp, 8)\n\t\t\tconst beatable = creeps.length ? view.strength.odds([hero], creeps) >= odds : camp.level <= 2 + 2 * (heroOfState(hero)?.level ?? 1)\n\t\t\tif (beatable) best = { at: { x: camp.x, z: camp.z }, d }\n\t\t}\n\t\treturn best?.at\n\t}\n}\n\n/** The kit's lane task: a hero walks a lane behind its side's wave (`LanesPlay.spot`), falling back once outmatched */\nconst PUSH = defineTask('lanes.push', {\n\tstart(ai, squad, state) {\n\t\tstate.phase = 'going'\n\t\tstate.phaseSince = ai.tick\n\t\tpushOn(ai, squad, state, true)\n\t},\n\tthink(ai, squad, state) {\n\t\tpushOn(ai, squad, state, false)\n\t},\n\twhere: (ai, _squad, state) => playOf(ai)?.spot(state.data.lane as string),\n\thandles: ['retreat', 'regroup', 'reinforce'],\n\tstanding: true\n})\n\n/** The lanes module's play, where the brain has one */\nconst playOf = (ai: Brain): LanesPlay | undefined => ai.module(LANES)?.play\n\n/** A hero on its lane: to its spot, fighting on the way; back along it when outmatched */\nfunction pushOn(ai: Brain, squad: Squad, state: TaskState, first: boolean): void {\n\tconst play = playOf(ai)\n\tconst path = state.data.lane as string\n\tconst lane = play?.state(path)\n\tconst middle = squad.centre()\n\tif (!play || !lane || !middle) {\n\t\tsquad.finish('lost')\n\t\treturn\n\t}\n\tconst fighting = ai.view.hostile.alive().near(middle, LANE_ENGAGED).length > 0\n\t// outmatched where it stands: back along the lane (a retreat, which micro leaves alone), then on again\n\tif (fighting && play.oddsAt(middle) < (play.options.backOdds ?? 0.3)) {\n\t\tconst to = play.fallBack(path, middle)\n\t\tif (to) {\n\t\t\tai.decide(`squad ${squad.name} falls back along ${path} to ${where(to)}: outmatched (odds ${play.oddsAt(middle).toFixed(2)})`, {\n\t\t\t\tkind: 'lanes'\n\t\t\t})\n\t\t\tsquad.retreat(to, 'outmatched on its lane')\n\t\t\treturn\n\t\t}\n\t}\n\tconst spot = play.spot(path)!\n\tconst phase = lane.front !== undefined ? 'pushing' : 'waiting'\n\tif (state.phase !== phase) {\n\t\tstate.phase = phase\n\t\tstate.phaseSince = ai.tick\n\t}\n\t// in a fight, micro has it: sent on only once the fight is over, or standing idle\n\tconst idle = squad.idleUnits()\n\tif (fighting && !idle.length) return\n\tconst sentTo = state.memory.at as Vec2 | undefined\n\tconst moved = !sentTo || distSq(sentTo, spot) > MOVED * MOVED\n\tconst away = squad.units().some((unit) => distSq(unit, spot) > THERE * THERE)\n\tif (!first && !(away && (moved || (idle.length && squad.mayResend())))) return\n\tstate.memory.at = point(spot)\n\tsquad.fight(spot)\n}\n\n/**\n * The lanes module, with the play it runs (`LanesPlay`): what the tests reach\n *\n * @beta\n */\nexport interface LanesModule extends AiModule {\n\tplay: LanesPlay\n}\n\n/**\n * What finds a lanes brain's module with its shape (`ai.module(LANES)`)\n *\n * @beta\n */\nexport const LANES = moduleKey<LanesModule>('lanes')\n\n/** The goals of a lanes brain over its play (the file's comment) */\nfunction laneGoals(ai: Brain, play: LanesPlay): GoalDef[] {\n\t/** Its heroes free to go: alive, not resting */\n\tconst free = (available: UnitSet) => play.commanded(available).where((hero) => play.memory.resting[hero.id] === undefined)\n\tconst nearestTo = (set: UnitSet, at: Vec2 | undefined) => (at ? set.nearest(at) : set.first())\n\tconst lanes = (ai.session.can.computer?.lanes() ?? [])\n\t\t.map((lane) => lane.path)\n\t\t.filter((path) => !play.options.lanes || play.options.lanes.includes(path))\n\tconst push = lanes.map((path) => {\n\t\tconst id = `lanes.push:${path}`\n\t\treturn defineGoal({\n\t\t\tid,\n\t\t\tweight: 1,\n\t\t\tcommitment: 30,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('a lane of its side', () => (play.lane(path) ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider('a hero free', () => free(ai.view.mine).length, curve.step(1)),\n\t\t\t\t// the lane with the most of its side's strength first; one with none still worth a hero waiting by its tower\n\t\t\t\tconsider(\n\t\t\t\t\t'its wave on it',\n\t\t\t\t\t() => ai.view.strength.sum(play.state(path)?.ours ?? []),\n\t\t\t\t\tcurve.custom((x) => 0.3 + 0.7 * (1 - exp(-x / 60)))\n\t\t\t\t),\n\t\t\t\t// where its side is winning (its wave far along: a tower to take, their core) or losing (theirs at its towers)\n\t\t\t\tconsider(\n\t\t\t\t\t'what is at stake',\n\t\t\t\t\t() => play.stake(path),\n\t\t\t\t\tcurve.custom((x) => 0.4 + 0.6 * x)\n\t\t\t\t),\n\t\t\t\tconsider(\n\t\t\t\t\t'the odds at its front',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tconst spot = play.spot(path)\n\t\t\t\t\t\treturn spot ? play.oddsAt(spot, 14) : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.custom((odds) => 0.2 + odds)\n\t\t\t\t),\n\t\t\t\t// two heroes of a side on a lane leave another to their heroes; a third, more so\n\t\t\t\tconsider('allies already on it', () => play.state(path)?.allies.length ?? 0, curve.inverse(2)),\n\t\t\t\tconsider(\n\t\t\t\t\t'how far its hero is',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tconst spot = play.spot(path)\n\t\t\t\t\t\tconst hero = nearestTo(free(ai.view.mine), spot)\n\t\t\t\t\t\treturn hero && spot ? Math.sqrt(distSq(hero, spot)) : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.inverse(60)\n\t\t\t\t)\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\t// one hero a lane: the nearest of those free to it, so that two heroes of a player take two lanes\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst hero = nearestTo(free(available), play.spot(path))\n\t\t\t\t\treturn hero ? [hero] : []\n\t\t\t\t}\n\t\t\t},\n\t\t\trun: (_ai, claimed) => {\n\t\t\t\tconst squad = claimed.squad(id, claimed.units, { retreatAt: false })\n\t\t\t\t// given as made, and again once a fall back along it is over\n\t\t\t\tif (squad.idle) squad.task(PUSH, { lane: path })\n\t\t\t}\n\t\t})\n\t})\n\tconst back = defineGoal({\n\t\tid: 'lanes.back',\n\t\tweight: 10,\n\t\turgent: true,\n\t\tcommitment: 0,\n\t\tconsiderations: [consider('a hero to rest', () => play.resting().length, curve.step(1))],\n\t\tclaims: { units: () => play.resting() },\n\t\trun: (ai, claimed) => {\n\t\t\t// one that turned for home while another goal had it: taken from that goal; one rested: let go of\n\t\t\tconst hold = ai.goals.held('lanes.back')\n\t\t\tconst resting = play.resting()\n\t\t\tconst fresh = resting.filter((hero) => !hold?.units.includes(hero.id)).map((hero) => hero.id)\n\t\t\tif (fresh.length) {\n\t\t\t\tai.goals.take(fresh, 'urgent')\n\t\t\t\tai.goals.give('lanes.back', fresh)\n\t\t\t}\n\t\t\tconst rested = claimed.units.where((hero) => play.memory.resting[hero.id] === undefined).ids()\n\t\t\tif (rested.size) ai.goals.drop('lanes.back', rested)\n\t\t\t// on its own: no squad, so micro's shopping finds it with nothing to do at home\n\t\t\tfor (const hero of resting) play.sendHome(hero)\n\t\t}\n\t})\n\tconst help = defineGoal({\n\t\tid: 'lanes.help',\n\t\tweight: 1.3,\n\t\tcommitment: 6,\n\t\tconsiderations: [\n\t\t\tconsider(\n\t\t\t\t'an ally in a fight near',\n\t\t\t\t() => {\n\t\t\t\t\tconst hero = free(ai.view.mine).first()\n\t\t\t\t\treturn hero && play.call(hero) ? 1 : 0\n\t\t\t\t},\n\t\t\t\tcurve.step(1)\n\t\t\t),\n\t\t\tconsider(\n\t\t\t\t'the odds there with it',\n\t\t\t\t() => {\n\t\t\t\t\tconst hero = free(ai.view.mine).first()\n\t\t\t\t\tconst at = hero && play.call(hero)\n\t\t\t\t\tif (!hero || !at) return 0\n\t\t\t\t\tconst near = ai.view.all.units().alive().near(at, 12)\n\t\t\t\t\tconst theirs = near.where((unit) => ai.view.isHostile(unit))\n\t\t\t\t\treturn theirs.length ? ai.view.strength.odds([...near.where((unit) => ai.view.isFriendly(unit)).items, hero], theirs) : 1\n\t\t\t\t},\n\t\t\t\tcurve.custom((odds) => (odds >= ((play.options.help || {}).odds ?? 0.4) ? odds : 0))\n\t\t\t)\n\t\t],\n\t\tclaims: {\n\t\t\tunits: (_ai, available) => {\n\t\t\t\tconst heroes = free(available)\n\t\t\t\tconst hero = heroes.first()\n\t\t\t\tconst at = hero && play.call(hero)\n\t\t\t\tconst chosen = at && heroes.nearest(at)\n\t\t\t\treturn chosen ? [chosen] : []\n\t\t\t}\n\t\t},\n\t\trun: (ai, claimed) => {\n\t\t\tconst hero = claimed.units.first()\n\t\t\tconst at = hero && play.call(hero)\n\t\t\tif (!hero || !at) return\n\t\t\tconst ally = play.allyAt(at)\n\t\t\tconst squad = claimed.squad('lanes.help', claimed.units, { retreatAt: false })\n\t\t\tif (claimed.first) ai.decide(`${hero.type} ${hero.id} goes to help at ${where(at)}`, { kind: 'lanes' })\n\t\t\tif (squad.idle || (ally && squad.current?.kind !== 'escort')) {\n\t\t\t\tif (ally) squad.escort(ally.id)\n\t\t\t\telse squad.attack(at)\n\t\t\t}\n\t\t}\n\t})\n\tconst camp = defineGoal({\n\t\tid: 'lanes.camp',\n\t\tweight: 0.6,\n\t\tcommitment: 15,\n\t\tconsiderations: [\n\t\t\tconsider('no wave to walk with', () => play.states().filter((state) => state.ours.length > 0).length, curve.inverse(0.01)),\n\t\t\tconsider(\n\t\t\t\t'a camp it can take',\n\t\t\t\t() => {\n\t\t\t\t\tconst hero = free(ai.view.mine).first()\n\t\t\t\t\treturn hero && play.camp(hero) ? 1 : 0\n\t\t\t\t},\n\t\t\t\tcurve.step(1)\n\t\t\t)\n\t\t],\n\t\tclaims: {\n\t\t\tunits: (_ai, available) => {\n\t\t\t\tconst hero = free(available).first()\n\t\t\t\treturn hero && play.camp(hero) ? [hero] : []\n\t\t\t}\n\t\t},\n\t\trun: (_ai, claimed) => {\n\t\t\tconst hero = claimed.units.first()\n\t\t\tconst at = hero && play.camp(hero)\n\t\t\tconst squad = claimed.squad('lanes.camp', claimed.units, { retreatAt: false })\n\t\t\tif (squad.idle && at) squad.creep(at)\n\t\t}\n\t})\n\treturn [...push, back, ...(play.options.help === false ? [] : [help]), ...(play.options.camps === false ? [] : [camp])]\n}\n\n/**\n * The module of a lanes brain: the lanes read for its side, its heroes' rest, and its goals put on the picker (the\n * file's comment). Its options under the brain's settings (`AiSettings.lanes`)\n *\n * @beta\n */\nexport const lanesPlay = (options: LanesPlayOptions = {}): AiModuleDef =>\n\tdefineModule('lanes', (ai: Brain): LanesModule => {\n\t\tconst play = new LanesPlay(ai, { ...options, ...ai.settings.lanes })\n\t\tai.squads.define(PUSH)\n\t\tai.goals.add(...laneGoals(ai, play))\n\t\treturn {\n\t\t\tid: 'lanes',\n\t\t\tversion: 1,\n\t\t\tphase: 'decide',\n\t\t\tplay,\n\t\t\tthink: () => play.think(),\n\t\t\tsave: () => structuredClone(play.memory),\n\t\t\t// written into the same object: the goals' closures read it\n\t\t\trestore: (data) => {\n\t\t\t\tconst kept = data && typeof data === 'object' ? (data as Partial<LanesPlayMemory>) : {}\n\t\t\t\tplay.memory.resting = { ...kept.resting }\n\t\t\t\tplay.memory.recalled = { ...kept.recalled }\n\t\t\t\tplay.memory.sent = { ...kept.sent }\n\t\t\t},\n\t\t\tinspect: () => ({\n\t\t\t\tlanes: play.states().map((state) => ({\n\t\t\t\t\tlane: state.lane.path,\n\t\t\t\t\tfront: state.front === undefined ? undefined : Math.round(state.front),\n\t\t\t\t\ttheirFront: state.theirFront === undefined ? undefined : Math.round(state.theirFront),\n\t\t\t\t\tours: state.ours.length,\n\t\t\t\t\ttheirs: state.theirs.length\n\t\t\t\t})),\n\t\t\t\tresting: Object.keys(play.memory.resting).map(Number)\n\t\t\t})\n\t\t}\n\t})\n\n/**\n * The engine's computer player for a game of lanes (`withLanes`): a brain of its rules, the words, `lanesPlay`, the\n * team, the picker, squads and micro (the file's comment). Heroes walk the lanes with their waves, rest at home when\n * hurt, help an ally's hero, take a camp with no wave to walk with. A variant is `lanesBrain.with({ ... })`; a game's\n * own lanes brain is `lanesBrainOf({ id, lanes, ... })`\n *\n * @beta\n */\nexport function lanesBrainOf(def: BrainExtension & { id: string; lanes?: LanesPlayOptions }): BrainDef {\n\tconst { lanes, modules = [], settings, ...rest } = def\n\treturn defineBrain({\n\t\t...rest,\n\t\tsettings: {\n\t\t\t...settings,\n\t\t\t// heroes are its to bring home (`lanes.back`), not micro's to send off alone; whom they hit, the lanes' way\n\t\t\tmicro: { heroesFlee: false, unitsFlee: false, focusEvery: 2, targets: lanesTargets(lanes), ...settings?.micro },\n\t\t\t// the minions are the lanes', so a call for help is the lanes' goal's to answer (`lanes.help`), and it asks for none\n\t\t\tteam: { defendUsers: false, askForHelp: false, ...settings?.team }\n\t\t},\n\t\tmodules: [\n\t\t\t// its own rules first, as every brain's: what a rule takes is not given orders by the rest\n\t\t\tdefineModule('rules', (ai: Brain) => (rules(ai.def.rules ?? []) as (ai: Brain) => AiModule)(ai)),\n\t\t\twords(),\n\t\t\tteam(),\n\t\t\tlanesPlay(lanes),\n\t\t\t...modules,\n\t\t\tgoals(),\n\t\t\tsquads(),\n\t\t\tmicro()\n\t\t]\n\t})\n}\n\n/**\n * The engine's computer player for a game of lanes, as it is: `lanesBrainOf({ id: 'core.lanes' })`. List it in the\n * game's `GameModule.brains` and seat it (`world.computers.seat(player, { brain: lanesBrain })`)\n *\n * @beta\n */\nexport const lanesBrain: BrainDef = lanesBrainOf({ id: 'core.lanes' })\n","import { type MissionRule, missionRulesPack } from '#engine/missionRules'\nimport type { GamePack } from '#engine/packs/pack'\nimport { ruleWatcher } from './computer'\n\n/**\n * Mission rules as data (campaign plan MS1): the rules a map keeps (`MissionRule`, under `GameMap.data.rules`, written\n * in the editor's Rules panel) run as the game plays, `rules` of the game's own code beside them. Each `when` a\n * condition of the computer players' language holds (`docs/ai.md`), asked as a player, `do`es its actions\n * (`MissionActionData`: an objective of the map's given, done or failed, a line said, a cinematic played, a prefab\n * spawned, a computer told, a relation set, a timer started, win, lose). Checked once a second; what the rules\n * remember is in the world's state, so a save mid-mission has it. The code reaches the rules with `tellRules` and hears\n * them fire as `ruleFired`; the map's checks say what is wrong with them (`checkMissionRules`). Of `@v12-engine/engine/ai`, as\n * a condition is asked of a watcher seated as the computer players are (`ruleWatcher`); the map objectives pack\n * (`mapObjectives`) goes with it, for the objectives a rule gives\n *\n * @beta\n */\nexport function missionRules(options: { rules?: MissionRule[] } = {}): GamePack {\n\treturn missionRulesPack({ ...options, watch: ruleWatcher })\n}\n"],"mappings":"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"}