@v12-engine/engine 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abilities/buffs.d.ts +83 -0
  3. package/dist/abilities/castTold.d.ts +12 -0
  4. package/dist/abilities/charges.d.ts +28 -0
  5. package/dist/abilities/dispel.d.ts +9 -0
  6. package/dist/abilities/effectFields.d.ts +10 -0
  7. package/dist/abilities/effects/buff.d.ts +8 -0
  8. package/dist/abilities/effects/core.d.ts +1 -0
  9. package/dist/abilities/effects/damage.d.ts +1 -0
  10. package/dist/abilities/effects/heal.d.ts +2 -0
  11. package/dist/abilities/effects/missile.d.ts +1 -0
  12. package/dist/abilities/effects/moves.d.ts +11 -0
  13. package/dist/abilities/effects/passives.d.ts +15 -0
  14. package/dist/abilities/effects/sight.d.ts +4 -0
  15. package/dist/abilities/effects/spawn.d.ts +2 -0
  16. package/dist/abilities/effects/timed.d.ts +4 -0
  17. package/dist/abilities/effects/trade.d.ts +1 -0
  18. package/dist/abilities/effects.d.ts +122 -0
  19. package/dist/abilities/land.d.ts +21 -0
  20. package/dist/abilities/scaled.d.ts +21 -0
  21. package/dist/abilities/text.d.ts +113 -0
  22. package/dist/ai/area.d.ts +53 -0
  23. package/dist/ai/brain.d.ts +528 -0
  24. package/dist/ai/budget.d.ts +67 -0
  25. package/dist/ai/checks.d.ts +115 -0
  26. package/dist/ai/computer.d.ts +166 -0
  27. package/dist/ai/defence.d.ts +108 -0
  28. package/dist/ai/define.d.ts +21 -0
  29. package/dist/ai/economy.d.ts +129 -0
  30. package/dist/ai/geometry.d.ts +35 -0
  31. package/dist/ai/goals.d.ts +360 -0
  32. package/dist/ai/index.d.ts +38 -0
  33. package/dist/ai/knowledge.d.ts +418 -0
  34. package/dist/ai/lanes.d.ts +232 -0
  35. package/dist/ai/melee/build.d.ts +61 -0
  36. package/dist/ai/melee/goals.d.ts +299 -0
  37. package/dist/ai/melee/heroes.d.ts +27 -0
  38. package/dist/ai/melee/index.d.ts +14 -0
  39. package/dist/ai/melee/production.d.ts +8 -0
  40. package/dist/ai/melee/surrender.d.ts +24 -0
  41. package/dist/ai/micro.d.ts +278 -0
  42. package/dist/ai/mission.d.ts +195 -0
  43. package/dist/ai/missionRules.d.ts +18 -0
  44. package/dist/ai/module.d.ts +116 -0
  45. package/dist/ai/options.d.ts +61 -0
  46. package/dist/ai/plans/build.d.ts +280 -0
  47. package/dist/ai/plans/placement.d.ts +82 -0
  48. package/dist/ai/plans/plans.d.ts +105 -0
  49. package/dist/ai/plans/production.d.ts +210 -0
  50. package/dist/ai/plans/purse.d.ts +73 -0
  51. package/dist/ai/plans/tech.d.ts +37 -0
  52. package/dist/ai/profiles.d.ts +204 -0
  53. package/dist/ai/reach.d.ts +4 -0
  54. package/dist/ai/report.d.ts +203 -0
  55. package/dist/ai/roles.d.ts +133 -0
  56. package/dist/ai/rules.d.ts +288 -0
  57. package/dist/ai/scouting.d.ts +98 -0
  58. package/dist/ai/settings.d.ts +73 -0
  59. package/dist/ai/squads.d.ts +429 -0
  60. package/dist/ai/strength.d.ts +167 -0
  61. package/dist/ai/task.d.ts +118 -0
  62. package/dist/ai/tasks/attack.d.ts +7 -0
  63. package/dist/ai/tasks/capture.d.ts +21 -0
  64. package/dist/ai/tasks/creep.d.ts +16 -0
  65. package/dist/ai/tasks/defend.d.ts +29 -0
  66. package/dist/ai/tasks/drop.d.ts +34 -0
  67. package/dist/ai/tasks/escort.d.ts +16 -0
  68. package/dist/ai/tasks/gather.d.ts +23 -0
  69. package/dist/ai/tasks/harass.d.ts +7 -0
  70. package/dist/ai/tasks/hold.d.ts +20 -0
  71. package/dist/ai/tasks/index.d.ts +32 -0
  72. package/dist/ai/tasks/move.d.ts +19 -0
  73. package/dist/ai/tasks/patrol.d.ts +8 -0
  74. package/dist/ai/tasks/retreat.d.ts +20 -0
  75. package/dist/ai/tasks/scout.d.ts +29 -0
  76. package/dist/ai/tasks/shared.d.ts +74 -0
  77. package/dist/ai/team.d.ts +155 -0
  78. package/dist/ai/threat.d.ts +91 -0
  79. package/dist/ai/view.d.ts +366 -0
  80. package/dist/ai/waves.d.ts +126 -0
  81. package/dist/ai.js +6239 -0
  82. package/dist/ai.js.map +1 -0
  83. package/dist/aiTesting.d.ts +179 -0
  84. package/dist/areas.d.ts +149 -0
  85. package/dist/attacks.d.ts +66 -0
  86. package/dist/attributes.d.ts +66 -0
  87. package/dist/brain-BvVdUhX8.js +7659 -0
  88. package/dist/brain-BvVdUhX8.js.map +1 -0
  89. package/dist/builds-C6LfgvEU.js +460 -0
  90. package/dist/builds-C6LfgvEU.js.map +1 -0
  91. package/dist/bytes.d.ts +6 -0
  92. package/dist/camps.d.ts +95 -0
  93. package/dist/capture.d.ts +131 -0
  94. package/dist/cellLayers.d.ts +75 -0
  95. package/dist/cinematics.d.ts +194 -0
  96. package/dist/clock.d.ts +32 -0
  97. package/dist/commands.d.ts +235 -0
  98. package/dist/components.d.ts +184 -0
  99. package/dist/computers.d.ts +108 -0
  100. package/dist/concealment.d.ts +61 -0
  101. package/dist/coreComponents-syuh2fPG.js +5149 -0
  102. package/dist/coreComponents-syuh2fPG.js.map +1 -0
  103. package/dist/coreComponents.d.ts +1 -0
  104. package/dist/dashing.d.ts +8 -0
  105. package/dist/debug.d.ts +36 -0
  106. package/dist/debug.js +3 -0
  107. package/dist/debugCommands-CzjrSm66.js +14739 -0
  108. package/dist/debugCommands-CzjrSm66.js.map +1 -0
  109. package/dist/debugCommands.d.ts +213 -0
  110. package/dist/debugging.d.ts +10 -0
  111. package/dist/definitions.d.ts +43 -0
  112. package/dist/defs.d.ts +1162 -0
  113. package/dist/denying.d.ts +81 -0
  114. package/dist/destructibles.d.ts +27 -0
  115. package/dist/determinism-BCymQwiE.js +518 -0
  116. package/dist/determinism-BCymQwiE.js.map +1 -0
  117. package/dist/determinism.d.ts +121 -0
  118. package/dist/dialog.d.ts +94 -0
  119. package/dist/effectRefs.d.ts +16 -0
  120. package/dist/effects.d.ts +80 -0
  121. package/dist/endings.d.ts +22 -0
  122. package/dist/engagement.d.ts +108 -0
  123. package/dist/engineEvents.d.ts +710 -0
  124. package/dist/entity.d.ts +409 -0
  125. package/dist/entityIndex.d.ts +50 -0
  126. package/dist/errors.d.ts +85 -0
  127. package/dist/events.d.ts +97 -0
  128. package/dist/exactMath.d.ts +63 -0
  129. package/dist/features.d.ts +10 -0
  130. package/dist/fields.d.ts +114 -0
  131. package/dist/fixture.d.ts +17 -0
  132. package/dist/fog.d.ts +110 -0
  133. package/dist/formation.d.ts +111 -0
  134. package/dist/friendlyFire.d.ts +26 -0
  135. package/dist/game-DiJEN-Ks.js +5800 -0
  136. package/dist/game-DiJEN-Ks.js.map +1 -0
  137. package/dist/game.d.ts +501 -0
  138. package/dist/gameData.d.ts +325 -0
  139. package/dist/gameFiles.d.ts +26 -0
  140. package/dist/gates.d.ts +28 -0
  141. package/dist/generate.d.ts +403 -0
  142. package/dist/generateWorker.d.ts +39 -0
  143. package/dist/grid.d.ts +53 -0
  144. package/dist/ground.d.ts +127 -0
  145. package/dist/groundSpeed.d.ts +22 -0
  146. package/dist/hero.d.ts +177 -0
  147. package/dist/home.d.ts +14 -0
  148. package/dist/hooks.d.ts +780 -0
  149. package/dist/hotReload.d.ts +76 -0
  150. package/dist/ids.d.ts +26 -0
  151. package/dist/index.d.ts +227 -0
  152. package/dist/index.js +4701 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/inspect-D9dWHmZ0.js +491 -0
  155. package/dist/inspect-D9dWHmZ0.js.map +1 -0
  156. package/dist/inspect.d.ts +176 -0
  157. package/dist/inventory.d.ts +18 -0
  158. package/dist/items.d.ts +91 -0
  159. package/dist/lanes.d.ts +213 -0
  160. package/dist/life.d.ts +53 -0
  161. package/dist/local-Dkovq42k.js +1379 -0
  162. package/dist/local-Dkovq42k.js.map +1 -0
  163. package/dist/log.d.ts +140 -0
  164. package/dist/manaBurn.d.ts +39 -0
  165. package/dist/map/file.d.ts +114 -0
  166. package/dist/map/images.d.ts +18 -0
  167. package/dist/map/look.d.ts +47 -0
  168. package/dist/map/pathProfile.d.ts +13 -0
  169. package/dist/map/resize.d.ts +54 -0
  170. package/dist/map/schema.d.ts +10 -0
  171. package/dist/map/terrain.d.ts +32 -0
  172. package/dist/map/types.d.ts +613 -0
  173. package/dist/map.d.ts +7 -0
  174. package/dist/mapCheck/cells.d.ts +19 -0
  175. package/dist/mapCheck/rule.d.ts +30 -0
  176. package/dist/mapCheck/rules/names.d.ts +3 -0
  177. package/dist/mapCheck/rules/objects.d.ts +3 -0
  178. package/dist/mapCheck/rules/paths.d.ts +3 -0
  179. package/dist/mapCheck/rules/players.d.ts +3 -0
  180. package/dist/mapCheck/rules/races.d.ts +3 -0
  181. package/dist/mapCheck/rules/random.d.ts +3 -0
  182. package/dist/mapCheck/rules/regions.d.ts +3 -0
  183. package/dist/mapCheck/rules/targets.d.ts +3 -0
  184. package/dist/mapCheck/rules/walking.d.ts +3 -0
  185. package/dist/mapCheck.d.ts +23 -0
  186. package/dist/mapFields.d.ts +364 -0
  187. package/dist/mapFile.d.ts +23 -0
  188. package/dist/mapMeasure.d.ts +95 -0
  189. package/dist/mapMerge.d.ts +19 -0
  190. package/dist/mapObjectives.d.ts +82 -0
  191. package/dist/mapObjects.d.ts +1 -0
  192. package/dist/math.d.ts +44 -0
  193. package/dist/messages.d.ts +150 -0
  194. package/dist/missionRules-C-bGxm0Q.js +523 -0
  195. package/dist/missionRules-C-bGxm0Q.js.map +1 -0
  196. package/dist/missionRules.d.ts +179 -0
  197. package/dist/mods.d.ts +146 -0
  198. package/dist/names.d.ts +93 -0
  199. package/dist/navigation/agentParams.d.ts +4 -0
  200. package/dist/navigation/air.d.ts +89 -0
  201. package/dist/navigation/builds.d.ts +140 -0
  202. package/dist/navigation/groundAreas.d.ts +23 -0
  203. package/dist/navigation/navigation.d.ts +127 -0
  204. package/dist/navigation/recast.d.ts +214 -0
  205. package/dist/navigation/sidePaths.d.ts +69 -0
  206. package/dist/navigation/sized.d.ts +1 -0
  207. package/dist/navigation-worker.js +11 -0
  208. package/dist/navigation-worker.js.map +1 -0
  209. package/dist/nearest.d.ts +8 -0
  210. package/dist/noise.d.ts +12 -0
  211. package/dist/objectives.d.ts +93 -0
  212. package/dist/orders/basic.d.ts +96 -0
  213. package/dist/orders/build.d.ts +91 -0
  214. package/dist/orders/cast.d.ts +105 -0
  215. package/dist/orders/facts.d.ts +14 -0
  216. package/dist/orders/harvest.d.ts +94 -0
  217. package/dist/orders/idle.d.ts +7 -0
  218. package/dist/orders/items.d.ts +14 -0
  219. package/dist/orders/queue.d.ts +24 -0
  220. package/dist/pack.schema.json +6621 -0
  221. package/dist/packs/director/index.d.ts +81 -0
  222. package/dist/packs/heroes/campaign.d.ts +137 -0
  223. package/dist/packs/heroes/carry.d.ts +59 -0
  224. package/dist/packs/heroes/commands.d.ts +6 -0
  225. package/dist/packs/heroes/hire.d.ts +9 -0
  226. package/dist/packs/heroes/index.d.ts +12 -0
  227. package/dist/packs/heroes/making.d.ts +16 -0
  228. package/dist/packs/heroes/respawn.d.ts +42 -0
  229. package/dist/packs/moba/index.d.ts +34 -0
  230. package/dist/packs/pack.d.ts +84 -0
  231. package/dist/packs-g5thvmGn.js +3199 -0
  232. package/dist/packs-g5thvmGn.js.map +1 -0
  233. package/dist/packs.d.ts +84 -0
  234. package/dist/paths.d.ts +51 -0
  235. package/dist/plain.d.ts +17 -0
  236. package/dist/player.d.ts +117 -0
  237. package/dist/portals.d.ts +66 -0
  238. package/dist/prefabs.d.ts +139 -0
  239. package/dist/presetBuildings.d.ts +52 -0
  240. package/dist/presetGround.d.ts +22 -0
  241. package/dist/profiles-B3NS9jwk.js +335 -0
  242. package/dist/profiles-B3NS9jwk.js.map +1 -0
  243. package/dist/races.d.ts +136 -0
  244. package/dist/randomGroups.d.ts +2 -0
  245. package/dist/registry.d.ts +464 -0
  246. package/dist/remains.d.ts +119 -0
  247. package/dist/replication.d.ts +103 -0
  248. package/dist/rng.d.ts +17 -0
  249. package/dist/rules.d.ts +395 -0
  250. package/dist/rulesCheck.d.ts +37 -0
  251. package/dist/runes.d.ts +41 -0
  252. package/dist/save.d.ts +277 -0
  253. package/dist/scenario.d.ts +56 -0
  254. package/dist/scheduler.d.ts +67 -0
  255. package/dist/score.d.ts +306 -0
  256. package/dist/sequences.d.ts +132 -0
  257. package/dist/server/doorman.d.ts +21 -0
  258. package/dist/server/gameServer.d.ts +346 -0
  259. package/dist/server/index.d.ts +24 -0
  260. package/dist/server/lobby.d.ts +1 -0
  261. package/dist/server/log.d.ts +13 -0
  262. package/dist/server/match.d.ts +24 -0
  263. package/dist/server/mode.d.ts +168 -0
  264. package/dist/server/navigation-worker.d.ts +1 -0
  265. package/dist/server/navigation.d.ts +11 -0
  266. package/dist/server/ops.d.ts +78 -0
  267. package/dist/server/packs.d.ts +15 -0
  268. package/dist/server/ratings.d.ts +62 -0
  269. package/dist/server/relay.d.ts +34 -0
  270. package/dist/server/rooms.d.ts +162 -0
  271. package/dist/server/seat.d.ts +2 -0
  272. package/dist/server/seatSettings.d.ts +15 -0
  273. package/dist/server/secret.d.ts +5 -0
  274. package/dist/server/start.d.ts +54 -0
  275. package/dist/server/websocket.d.ts +74 -0
  276. package/dist/server.js +2861 -0
  277. package/dist/server.js.map +1 -0
  278. package/dist/session/can.d.ts +20 -0
  279. package/dist/session/commandReplay.d.ts +92 -0
  280. package/dist/session/debug.d.ts +65 -0
  281. package/dist/session/delay.d.ts +15 -0
  282. package/dist/session/delta.d.ts +98 -0
  283. package/dist/session/entityState.d.ts +1 -0
  284. package/dist/session/local.d.ts +214 -0
  285. package/dist/session/memory.d.ts +27 -0
  286. package/dist/session/protocol.d.ts +1155 -0
  287. package/dist/session/remote.d.ts +530 -0
  288. package/dist/session/replay.d.ts +114 -0
  289. package/dist/session/seed.d.ts +7 -0
  290. package/dist/session/share.d.ts +78 -0
  291. package/dist/session/socket.d.ts +8 -0
  292. package/dist/session/wire.d.ts +153 -0
  293. package/dist/session/worker.d.ts +227 -0
  294. package/dist/shared.d.ts +171 -0
  295. package/dist/sides.d.ts +75 -0
  296. package/dist/sight.d.ts +27 -0
  297. package/dist/simulate-oXBiw1Ff.js +167 -0
  298. package/dist/simulate-oXBiw1Ff.js.map +1 -0
  299. package/dist/simulate-worker.d.ts +1 -0
  300. package/dist/simulate-worker.js +28 -0
  301. package/dist/simulate-worker.js.map +1 -0
  302. package/dist/simulate.d.ts +154 -0
  303. package/dist/smart.d.ts +9 -0
  304. package/dist/spatial.d.ts +62 -0
  305. package/dist/spawning.d.ts +33 -0
  306. package/dist/stances.d.ts +76 -0
  307. package/dist/start.d.ts +71 -0
  308. package/dist/stats.d.ts +122 -0
  309. package/dist/summons.d.ts +63 -0
  310. package/dist/systems/abilities.d.ts +3 -0
  311. package/dist/systems/combat.d.ts +71 -0
  312. package/dist/systems/combatTold.d.ts +14 -0
  313. package/dist/systems/construction.d.ts +34 -0
  314. package/dist/systems/economy.d.ts +21 -0
  315. package/dist/systems/fog.d.ts +19 -0
  316. package/dist/systems/life.d.ts +3 -0
  317. package/dist/systems/movement.d.ts +105 -0
  318. package/dist/systems/orders.d.ts +7 -0
  319. package/dist/systems/production.d.ts +49 -0
  320. package/dist/systems/productionQueue.d.ts +40 -0
  321. package/dist/systems/victory.d.ts +14 -0
  322. package/dist/talk.d.ts +65 -0
  323. package/dist/tech.d.ts +62 -0
  324. package/dist/techTree.d.ts +38 -0
  325. package/dist/terrain.d.ts +173 -0
  326. package/dist/terrainSave.d.ts +29 -0
  327. package/dist/testing.d.ts +58 -0
  328. package/dist/testing.js +822 -0
  329. package/dist/testing.js.map +1 -0
  330. package/dist/tiles.d.ts +34 -0
  331. package/dist/timers.d.ts +146 -0
  332. package/dist/tomes.d.ts +48 -0
  333. package/dist/trade.d.ts +28 -0
  334. package/dist/transport.d.ts +76 -0
  335. package/dist/tunables.d.ts +45 -0
  336. package/dist/upkeep.d.ts +16 -0
  337. package/dist/veterancy.d.ts +80 -0
  338. package/dist/walls.d.ts +86 -0
  339. package/dist/world.d.ts +1118 -0
  340. package/package.json +80 -5
  341. package/README.md +0 -3
@@ -0,0 +1,335 @@
1
+ //#region src/ai/settings.ts
2
+ /**
3
+ * Where each flag that an area has a name for goes in it, and whether it is a share (`true`: the share a lower layer or
4
+ * the area gives; a number: that share; `false`: never)
5
+ */
6
+ var FLAGGED = {
7
+ defendUsers: [["team", "defendUsers"], "switch"],
8
+ say: [["team", "say"], "switch"],
9
+ targetHeroes: [["micro", "targetHeroes"], "switch"],
10
+ ignoreInjured: [["micro", "ignoreInjured"], "switch"],
11
+ removeInjuries: [["micro", "removeInjuries"], "switch"],
12
+ takeItems: [["micro", "takeItems"], "switch"],
13
+ buyItems: [["micro", "buyItems"], "switch"],
14
+ smartArtillery: [["micro", "smartArtillery"], "switch"],
15
+ kite: [["micro", "kite"], "switch"],
16
+ unitsFlee: [["micro", "unitsFlee"], "share"],
17
+ heroesFlee: [["micro", "heroesFlee"], "share"],
18
+ groupsFlee: [["squads", "retreatAt"], "share"],
19
+ workersFlee: [["economy", "workersFlee"], "switch"],
20
+ repairStructures: [[
21
+ "plans",
22
+ "build",
23
+ "repair"
24
+ ], "switch"],
25
+ rebuild: [[
26
+ "plans",
27
+ "build",
28
+ "rebuild"
29
+ ], "switch"],
30
+ scout: [["scouting", "scout"], "off"]
31
+ };
32
+ /** Of what a layer gives, the lists that add to the lower layers' rather than replace them */
33
+ var ADDED = /* @__PURE__ */ new Set(["plans.build.wants", "waves.groups"]);
34
+ /** Of what a layer gives, the tables merged key by key with the lower layers' rather than replaced */
35
+ var MERGED = /* @__PURE__ */ new Set([
36
+ "plans",
37
+ "plans.build",
38
+ "plans.production",
39
+ "plans.build.placement"
40
+ ]);
41
+ var isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
42
+ /** A copy of a layer with its flags taken into the areas they name, the area's own value of the same layer over it */
43
+ function folded(layer, ai) {
44
+ const copy = { ...layer };
45
+ for (const [flag, value] of Object.entries(layer.flags ?? {})) {
46
+ const where = FLAGGED[flag];
47
+ if (!where) continue;
48
+ const said = typeof value === "function" ? ai ? value(ai) : void 0 : value;
49
+ if (said === void 0) continue;
50
+ const [path, kind] = where;
51
+ const word = kind === "switch" ? !!said : kind === "off" ? said === false ? false : void 0 : said;
52
+ if (word === void 0) continue;
53
+ let at = copy;
54
+ for (const key of path.slice(0, -1)) {
55
+ at[key] = { ...at[key] };
56
+ at = at[key];
57
+ }
58
+ const key = path[path.length - 1];
59
+ if (at[key] === void 0) at[key] = word;
60
+ }
61
+ return copy;
62
+ }
63
+ /** A layer's values over the lower layers', key by key: see `ADDED`, `MERGED`; `true` over a share keeps the share */
64
+ function over(under, given, path) {
65
+ const merged = { ...under };
66
+ for (const [key, value] of Object.entries(given)) {
67
+ if (value === void 0) continue;
68
+ const at = path ? `${path}.${key}` : key;
69
+ const below = merged[key];
70
+ if (ADDED.has(at) && Array.isArray(value)) merged[key] = [...below ?? [], ...value];
71
+ else if ((MERGED.has(at) || !path) && isObject(value) && isObject(below)) merged[key] = over(below, value, at);
72
+ else if (value === true && typeof below === "number") continue;
73
+ else merged[key] = value;
74
+ }
75
+ return merged;
76
+ }
77
+ /**
78
+ * The settings layered, lowest first (see the file's comment): each area's values key by key, a flag taken into the area
79
+ * it names in its own layer. A flag that is a function of the brain is asked of `ai`, and left out where none is given
80
+ *
81
+ * @beta
82
+ */
83
+ function resolveSettings(layers, ai) {
84
+ let resolved = {};
85
+ for (const layer of layers) if (layer) resolved = over(resolved, folded(layer, ai), "");
86
+ for (const [path, kind] of Object.values(FLAGGED)) {
87
+ if (kind !== "share") continue;
88
+ const area = resolved[path[0]];
89
+ if (area?.[path[1]] === true) resolved[path[0]] = {
90
+ ...area,
91
+ [path[1]]: void 0
92
+ };
93
+ }
94
+ return resolved;
95
+ }
96
+ //#endregion
97
+ //#region src/ai/profiles.ts
98
+ /**
99
+ * The engine's defaults of how well it plays: the bottom layer. The areas' numbers are each area's own where no layer
100
+ * says them (`Economy`'s 8 workers)
101
+ *
102
+ * @beta
103
+ */
104
+ var DEFAULT_PROFILE = {
105
+ difficulty: "normal",
106
+ personality: "balanced",
107
+ every: 1,
108
+ mistakes: 0,
109
+ vision: "fair"
110
+ };
111
+ /** The numbers the strongest difficulties share */
112
+ var STRONG = {
113
+ every: .5,
114
+ economy: {
115
+ workers: 10,
116
+ expansions: 2
117
+ },
118
+ army: {
119
+ firstAttack: 105,
120
+ attackEvery: 34,
121
+ waveSize: 8
122
+ },
123
+ defence: { radius: 22 },
124
+ scouting: { lookEvery: 60 }
125
+ };
126
+ /**
127
+ * The engine's difficulties: how well it plays. `normal` is the areas' own numbers. `insane` sees through the fog and
128
+ * gets half again of what its workers bring in, as the classic insane computer does
129
+ *
130
+ * @beta
131
+ */
132
+ var DIFFICULTIES = {
133
+ easy: {
134
+ every: 2,
135
+ commandsPerThink: 12,
136
+ mistakes: .25,
137
+ economy: {
138
+ workers: 6,
139
+ expansions: 0
140
+ },
141
+ army: {
142
+ firstAttack: 240,
143
+ attackEvery: 70,
144
+ waveSize: 4
145
+ },
146
+ defence: { radius: 10 },
147
+ scouting: { lookEvery: 150 },
148
+ heroes: { most: 1 }
149
+ },
150
+ normal: {},
151
+ hard: STRONG,
152
+ insane: {
153
+ ...STRONG,
154
+ vision: "all",
155
+ handicap: { income: 1.5 }
156
+ }
157
+ };
158
+ /**
159
+ * The engine's personalities: how it likes to play. Over the difficulty, so a rusher rushes on any of them
160
+ *
161
+ * @beta
162
+ */
163
+ var PERSONALITIES = {
164
+ balanced: {},
165
+ rusher: {
166
+ army: {
167
+ firstAttack: 90,
168
+ attackEvery: 30,
169
+ waveSize: 4
170
+ },
171
+ economy: { expansions: 0 },
172
+ defence: { towers: 0 },
173
+ weights: {
174
+ creep: .5,
175
+ harass: 1.2,
176
+ expand: .5
177
+ },
178
+ flags: { noMercy: true }
179
+ },
180
+ turtle: {
181
+ army: { firstAttack: 300 },
182
+ defence: {
183
+ towers: 2,
184
+ odds: .8
185
+ },
186
+ economy: { expansions: 0 },
187
+ weights: {
188
+ attack: .8,
189
+ creep: .6,
190
+ raid: .5,
191
+ harass: .2,
192
+ expand: 1.2
193
+ },
194
+ flags: { workersFlee: true }
195
+ },
196
+ expander: {
197
+ economy: {
198
+ expansions: 3,
199
+ expandWhen: { all: [{ time: { after: 150 } }, { units: { role: "barracks" } }] }
200
+ },
201
+ weights: {
202
+ attack: .9,
203
+ expand: 1.5
204
+ }
205
+ },
206
+ harasser: {
207
+ army: {
208
+ attackEvery: 30,
209
+ waveSize: 4
210
+ },
211
+ weights: {
212
+ creep: 1.2,
213
+ raid: 1.5,
214
+ harass: 1.5
215
+ },
216
+ flags: {
217
+ kite: true,
218
+ heroesFlee: .5,
219
+ noMercy: true
220
+ }
221
+ }
222
+ };
223
+ /**
224
+ * The difficulties a game's computers may play at, by name: the engine's, the game's over them
225
+ *
226
+ * @beta
227
+ */
228
+ function difficultiesOf(registry) {
229
+ return {
230
+ ...DIFFICULTIES,
231
+ ...registry?.module?.ai?.difficulties
232
+ };
233
+ }
234
+ /**
235
+ * The personalities a game's computers may have, by name: the engine's, the game's over them
236
+ *
237
+ * @beta
238
+ */
239
+ function personalitiesOf(registry) {
240
+ return {
241
+ ...PERSONALITIES,
242
+ ...registry?.module?.ai?.personalities
243
+ };
244
+ }
245
+ /** What a profile says of how well it plays, beside its settings: layered field by field (the handicap and the budget merged) */
246
+ var HOW_WELL = [
247
+ "brain",
248
+ "difficulty",
249
+ "personality",
250
+ "every",
251
+ "commandsPerThink",
252
+ "mistakes",
253
+ "vision",
254
+ "budget",
255
+ "handicap"
256
+ ];
257
+ /** A profile's settings: what is not of how well it plays */
258
+ function settingsOf(profile) {
259
+ if (!profile) return void 0;
260
+ const settings = { ...profile };
261
+ for (const key of HOW_WELL) delete settings[key];
262
+ return settings;
263
+ }
264
+ /**
265
+ * The profile a seat plays by (`Brain.profile`): the brain's settings (`BrainDef.settings`), the game's defaults, the
266
+ * race's (`GameAi.races`, for the `race` the seat plays), the difficulty, the personality, the seat's own
267
+ * (`AiOptions.settings`, the map's under it), each over the one before; how well it plays from the engine's defaults,
268
+ * the game's, the race's, the difficulty, the personality and the seat's `every` and `budget`. A name the game does not
269
+ * have is passed over, and `unknown` names it
270
+ *
271
+ * @beta
272
+ */
273
+ function resolveProfile(options, registry, brain, race) {
274
+ const defaults = registry?.module?.ai?.defaults;
275
+ const raced = race !== void 0 ? registry?.module?.ai?.races?.[race] : void 0;
276
+ const difficulty = options.difficulty ?? raced?.difficulty ?? defaults?.difficulty ?? "normal";
277
+ const personality = options.personality ?? raced?.personality ?? defaults?.personality ?? "balanced";
278
+ const difficulties = difficultiesOf(registry);
279
+ const personalities = personalitiesOf(registry);
280
+ const unknown = [];
281
+ if (!difficulties[difficulty]) unknown.push(`difficulty "${difficulty}"`);
282
+ if (!personalities[personality]) unknown.push(`personality "${personality}"`);
283
+ const seat = {
284
+ ...options.every !== void 0 && { every: options.every },
285
+ ...options.budget !== void 0 && { budget: typeof options.budget === "number" ? { modulesPerTick: options.budget } : options.budget }
286
+ };
287
+ const profile = {};
288
+ for (const each of [
289
+ DEFAULT_PROFILE,
290
+ defaults,
291
+ raced,
292
+ difficulties[difficulty],
293
+ personalities[personality],
294
+ seat
295
+ ]) for (const key of HOW_WELL) {
296
+ const value = each?.[key];
297
+ if (value === void 0) continue;
298
+ profile[key] = key === "budget" || key === "handicap" ? {
299
+ ...profile[key],
300
+ ...value
301
+ } : value;
302
+ }
303
+ profile.difficulty = difficulty;
304
+ profile.personality = personality;
305
+ const layers = [
306
+ brain,
307
+ settingsOf(defaults),
308
+ settingsOf(raced),
309
+ settingsOf(difficulties[difficulty]),
310
+ settingsOf(personalities[personality]),
311
+ options.settings
312
+ ].filter((layer) => !!layer);
313
+ return {
314
+ profile: {
315
+ ...resolveSettings(layers),
316
+ ...profile
317
+ },
318
+ layers,
319
+ unknown
320
+ };
321
+ }
322
+ /**
323
+ * A flag's value as asked now: a function of the brain worked out, data as it is. For a flag no area has a name for
324
+ * (No Mercy, Random Paths, Allow Home Changes): the rest are the areas' (`ai.settings`)
325
+ *
326
+ * @beta
327
+ */
328
+ function flagOf(ai, name) {
329
+ const value = ai.settings.flags?.[name];
330
+ return typeof value === "function" ? value(ai) : value;
331
+ }
332
+ //#endregion
333
+ export { flagOf as a, resolveSettings as c, difficultiesOf as i, DIFFICULTIES as n, personalitiesOf as o, PERSONALITIES as r, resolveProfile as s, DEFAULT_PROFILE as t };
334
+
335
+ //# sourceMappingURL=profiles-B3NS9jwk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles-B3NS9jwk.js","names":[],"sources":["../src/ai/settings.ts","../src/ai/profiles.ts"],"sourcesContent":["/**\n * The settings of a brain (design review B2): every number and switch its areas play by, in one schema keyed by area,\n * each under the area's own names (`{ economy: { workers }, defence: { radius, towers }, micro: { unitsFlee } }`). Every\n * layer speaks it, lowest first:\n *\n * the brain's definition (`BrainDef.settings`) → the game's defaults (`GameAi.defaults`) → the race's\n * (`GameAi.races`) → the difficulty → the personality → the map (`MapAi.settings`, `MapAi.races`) → the seat\n * (`AiOptions.settings`)\n *\n * and `resolveSettings` layers them once: an area's values key by key, the higher layer's over the lower's. What a\n * module was made with (`economy({ workers })`) is under all of them, and what no layer says is the area's own default\n * (`Economy`'s 8 workers). An area reads what it plays by from `ai.settings` and nothing else.\n *\n * The classic flags (`AiFlags`) are a section of their own, for a lobby and the editor's flags list: a flag that says what\n * an area has a name for (Kite: `micro.kite`, Units Flee: `micro.unitsFlee`) is taken into that area in the layer that\n * says it, so that a higher layer's word goes over it either way. A flag may be a function of the brain: worked out each\n * think, as `ai.settings` is\n */\nimport type { DefenceOptions } from './defence'\nimport type { EconomyOptions } from './economy'\nimport type { Brain } from './brain'\nimport type { LanesPlayOptions } from './lanes'\nimport type { MeleeArmyOptions } from './melee/goals'\nimport type { MeleeHeroesOptions } from './melee/heroes'\nimport type { MicroOptions } from './micro'\nimport type { PlansOptions } from './plans/plans'\nimport type { AiFlags } from './profiles'\nimport type { ScoutingOptions } from './scouting'\nimport type { SquadsOptions } from './squads'\nimport type { TeamOptions } from './team'\nimport type { WavesOptions } from './waves'\n\n/**\n * What a brain's areas play by, by area, each under its own names (see the file's comment): what every layer gives, from\n * the brain's definition to the seat. Plain data where a lobby, a map or a save holds it; a function in it is code, not\n * kept in a save\n *\n * @beta\n */\nexport interface AiSettings {\n\t/** The workers and the bases (`Economy`) */\n\teconomy?: EconomyOptions\n\t/** What it defends and how (`Defence`) */\n\tdefence?: DefenceOptions\n\t/** How often it looks and with whom (`Scouting`) */\n\tscouting?: ScoutingOptions\n\t/** How its units fight (`Micro`) */\n\tmicro?: MicroOptions\n\t/** How its squads go, and the tasks they may be given (`Squads`) */\n\tsquads?: SquadsOptions\n\t/** How it plays with its team (`Team`) */\n\tteam?: TeamOptions\n\t/** The waves it was given (`Waves`) */\n\twaves?: WavesOptions\n\t/** What it builds, trains and researches, and in what order (`Plans`) */\n\tplans?: PlansOptions\n\t/** The melee army: when it attacks, how many go, how a wave goes (`melee.army`) */\n\tarmy?: MeleeArmyOptions\n\t/** The melee player's heroes: how many, and from when (`melee.heroes`) */\n\theroes?: MeleeHeroesOptions\n\t/** A lanes brain's play (`lanes`) */\n\tlanes?: LanesPlayOptions\n\t/** How much each goal weighs, by its id (1 when left out): the picker's (`Goals`) */\n\tweights?: Record<string, number>\n\t/** The classic flags (see the file's comment) */\n\tflags?: AiFlags\n}\n\n/**\n * Where each flag that an area has a name for goes in it, and whether it is a share (`true`: the share a lower layer or\n * the area gives; a number: that share; `false`: never)\n */\nconst FLAGGED: Readonly<Partial<Record<keyof AiFlags, readonly [path: readonly string[], kind: 'switch' | 'share' | 'off']>>> = {\n\tdefendUsers: [['team', 'defendUsers'], 'switch'],\n\tsay: [['team', 'say'], 'switch'],\n\ttargetHeroes: [['micro', 'targetHeroes'], 'switch'],\n\tignoreInjured: [['micro', 'ignoreInjured'], 'switch'],\n\tremoveInjuries: [['micro', 'removeInjuries'], 'switch'],\n\ttakeItems: [['micro', 'takeItems'], 'switch'],\n\tbuyItems: [['micro', 'buyItems'], 'switch'],\n\tsmartArtillery: [['micro', 'smartArtillery'], 'switch'],\n\tkite: [['micro', 'kite'], 'switch'],\n\tunitsFlee: [['micro', 'unitsFlee'], 'share'],\n\theroesFlee: [['micro', 'heroesFlee'], 'share'],\n\tgroupsFlee: [['squads', 'retreatAt'], 'share'],\n\tworkersFlee: [['economy', 'workersFlee'], 'switch'],\n\trepairStructures: [['plans', 'build', 'repair'], 'switch'],\n\trebuild: [['plans', 'build', 'rebuild'], 'switch'],\n\t// only its no: the scouting's `scout` is who goes, where it is not `false`\n\tscout: [['scouting', 'scout'], 'off']\n}\n\n/** Of what a layer gives, the lists that add to the lower layers' rather than replace them */\nconst ADDED = new Set(['plans.build.wants', 'waves.groups'])\n\n/** Of what a layer gives, the tables merged key by key with the lower layers' rather than replaced */\nconst MERGED = new Set(['plans', 'plans.build', 'plans.production', 'plans.build.placement'])\n\ntype Loose = Record<string, unknown>\n\nconst isObject = (value: unknown): value is Loose => typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** A copy of a layer with its flags taken into the areas they name, the area's own value of the same layer over it */\nfunction folded(layer: AiSettings, ai: Brain | undefined): Loose {\n\tconst copy: Loose = { ...layer }\n\tfor (const [flag, value] of Object.entries(layer.flags ?? {})) {\n\t\tconst where = FLAGGED[flag as keyof AiFlags]\n\t\tif (!where) continue\n\t\tconst said = typeof value === 'function' ? (ai ? (value as (ai: Brain) => unknown)(ai) : undefined) : value\n\t\tif (said === undefined) continue\n\t\tconst [path, kind] = where\n\t\tconst word = kind === 'switch' ? !!said : kind === 'off' ? (said === false ? false : undefined) : said\n\t\tif (word === undefined) continue\n\t\tlet at = copy\n\t\tfor (const key of path.slice(0, -1)) {\n\t\t\tat[key] = { ...(at[key] as Loose | undefined) }\n\t\t\tat = at[key] as Loose\n\t\t}\n\t\tconst key = path[path.length - 1]\n\t\tif (at[key] === undefined) at[key] = word\n\t}\n\treturn copy\n}\n\n/** A layer's values over the lower layers', key by key: see `ADDED`, `MERGED`; `true` over a share keeps the share */\nfunction over(under: Loose, given: Loose, path: string): Loose {\n\tconst merged: Loose = { ...under }\n\tfor (const [key, value] of Object.entries(given)) {\n\t\tif (value === undefined) continue\n\t\tconst at = path ? `${path}.${key}` : key\n\t\tconst below = merged[key]\n\t\tif (ADDED.has(at) && Array.isArray(value)) merged[key] = [...((below as unknown[] | undefined) ?? []), ...value]\n\t\telse if ((MERGED.has(at) || !path) && isObject(value) && isObject(below)) merged[key] = over(below, value, at)\n\t\telse if (value === true && typeof below === 'number') continue\n\t\telse merged[key] = value\n\t}\n\treturn merged\n}\n\n/**\n * The settings layered, lowest first (see the file's comment): each area's values key by key, a flag taken into the area\n * it names in its own layer. A flag that is a function of the brain is asked of `ai`, and left out where none is given\n *\n * @beta\n */\nexport function resolveSettings(layers: readonly (AiSettings | undefined)[], ai?: Brain): AiSettings {\n\tlet resolved: Loose = {}\n\tfor (const layer of layers) if (layer) resolved = over(resolved, folded(layer, ai), '')\n\t// a share left at `true` is the area's own\n\tfor (const [path, kind] of Object.values(FLAGGED)) {\n\t\tif (kind !== 'share') continue\n\t\tconst area = resolved[path[0]] as Loose | undefined\n\t\tif (area?.[path[1]] === true) resolved[path[0]] = { ...area, [path[1]]: undefined }\n\t}\n\treturn resolved as AiSettings\n}\n","import type { Registry } from '#engine/registry'\nimport type { AiConditionTest } from './rules'\nimport type { ThinkBudgetOptions } from './budget'\nimport type { AiOptions } from './options'\nimport type { Brain } from './brain'\nimport { type AiSettings, resolveSettings } from './settings'\n\n/*\n * Profiles (AI plan, D1): how a computer player plays, as one piece of plain data. A profile (`AiProfile`) is the\n * settings of its areas (`AiSettings`, keyed by area: see settings.ts) and how well it plays, and is made of layers,\n * lowest first:\n *\n * the brain's → the game's defaults → the race's → the difficulty (by name) → the personality (by name) → the map → the seat\n *\n * - **A race's** (`GameAi.races`, by the race the seat plays) is how the game's computers play that race: its build\n * order, its heroes, its composition, a flag the race's roster asks for. Under the difficulty and the personality,\n * so that a hard rusher of either race is still hard and still rushes; the map's (`MapAi.races`) goes over the map's\n * settings for a player whose race the map leaves to the lobby.\n * - **A difficulty** (`easy`, `normal`, `hard`, `insane`, or a game's own: `GameModule.ai.difficulties`) is how\n * well it plays: how often it thinks, how many commands a think may send (`commandsPerThink`, a person's hands), how\n * often it slips (`mistakes`: a think's fights left alone, a wave sent early; drawn with its own numbers, so the same\n * game slips alike), whether it sees through the fog (`vision: 'all'`, insane only: the one way a computer sees what\n * its seat does not, an observer's session), and the handicaps it is given (`handicap`: more of what its workers\n * bring in, more health, more damage, quicker making, asked of the game through its hooks as the computer is seated).\n * - **A personality** (`balanced`, `rusher`, `turtle`, `expander`, `harasser`, or a game's own: `GameModule.ai.personalities`) is how\n * it likes to play: how much each goal weighs (`weights`), when it attacks and expands, how many towers it puts up.\n * - **The map's and the seat's** are what the map (`MapAi`), the lobby or the mission give (`AiOptions.settings`).\n *\n * `ai.profile` is the profile resolved; `ai.settings` its settings as the areas read them, worked out once a think.\n * Every field is data a lobby, a map or an editor can hold; a flag may be a function of the brain instead (code: given\n * again by the game, not kept in a save).\n */\n\n/**\n * A flag's value: as data, or worked out by the brain as it is asked (code, not kept in a save)\n *\n * @beta\n */\nexport type AiFlag<T> = T | ((ai: Brain) => T)\n\n/**\n * The classic RTS behaviour flags, where the meaning holds, and the kit's own beside them: each a yes or no, a number where\n * one says how much, or a function of the brain\n *\n * @beta\n */\nexport interface AiFlags {\n\t/** Helps its allies, people and computers, where asked (the team's `help` goal) */\n\tdefendUsers?: AiFlag<boolean>\n\t/** Hits heroes first among those alike (the micro's targets) */\n\ttargetHeroes?: AiFlag<boolean>\n\t/** Mends damaged buildings when no enemy reaches them (the build plan's `repair`) */\n\trepairStructures?: AiFlag<boolean>\n\t/** A hero leaves a fight under this share of its health: `true` at the share under it, `false` never (`micro.heroesFlee`) */\n\theroesFlee?: AiFlag<boolean | number>\n\t/** A unit leaves a fight under this share of its health: `true` at the share under it, `false` never (`micro.unitsFlee`) */\n\tunitsFlee?: AiFlag<boolean | number>\n\t/** A squad falls back from a fight away from home under these odds: `true` at the odds under it, `false` never (`squads.retreatAt`) */\n\tgroupsFlee?: AiFlag<boolean | number>\n\t/** Attacks before its time when the enemy's army as last seen is weak against its own: at these odds (`true`: 0.75) */\n\tnoMercy?: AiFlag<boolean | number>\n\t/** A unit that fled stays out until healed */\n\tignoreInjured?: AiFlag<boolean>\n\t/** The hurt go home to heal between fights */\n\tremoveInjuries?: AiFlag<boolean>\n\t/** Picks up what lies about */\n\ttakeItems?: AiFlag<boolean>\n\t/** Its heroes buy from shops in reach */\n\tbuyItems?: AiFlag<boolean>\n\t/** Builds its hall again where it can, once its home falls, rather than where it first stood: yes when left out */\n\tallowHomeChanges?: AiFlag<boolean>\n\t/** Siege units shoot buildings and stay behind their squad */\n\tsmartArtillery?: AiFlag<boolean>\n\t/** Each wave takes a way of its own to the target, by the brain's numbers: straight, or round one side or the other */\n\trandomPaths?: AiFlag<boolean>\n\t/** Builds again what it lost */\n\trebuild?: AiFlag<boolean>\n\t/** Ranged units step back from melee they outrun */\n\tkite?: AiFlag<boolean>\n\t/** Workers a raid is on walk to a safe base */\n\tworkersFlee?: AiFlag<boolean>\n\t/** Says its lines to its side (the team's `say`) */\n\tsay?: AiFlag<boolean>\n\t/** Sends a unit to look at the enemy (the scouting's goal) */\n\tscout?: AiFlag<boolean>\n}\n\n/**\n * How a computer player plays, as plain data: the settings of its areas (`AiSettings`) and how well it plays, every field\n * optional, layered (see the file's comment). What a difficulty, a personality and a game's defaults give\n *\n * @beta\n */\nexport interface AiProfile extends AiSettings {\n\t/**\n\t * The brain it plays with, by id (one the game lists in `GameModule.brains`): what a race's profile says\n\t * (`GameAi.races`, campaign plan AR3), for a seat that names none and a map that says none. The game's first brain\n\t * where nothing says\n\t */\n\tbrain?: string\n\t/** The difficulty by name: `easy`, `normal`, `hard`, `insane`, or a game's own (`GameModule.ai.difficulties`). `normal` when left out */\n\tdifficulty?: string\n\t/** The personality by name: `balanced`, `rusher`, `turtle`, `expander`, `harasser`, or a game's own. `balanced` when left out */\n\tpersonality?: string\n\t/** Seconds between thinks: its reactions */\n\tevery?: number\n\t/** Commands a think may send at the most, like a person's hands: no limit when left out */\n\tcommandsPerThink?: number\n\t/** How often it slips, 0 to 1: a think's fights left alone, a wave sent early. Drawn with the brain's own numbers */\n\tmistakes?: number\n\t/** `fair`: it sees what its seat does. `all`: it sees through the fog (an observer's session), for insane only */\n\tvision?: 'fair' | 'all'\n\t/**\n\t * How much of a think one tick may do (`ThinkBudgetOptions`): modules a tick, units looked at a tick, the milliseconds\n\t * a module is warned over (4). Nothing sliced when left out: a game sets it where its numbers ask, at many computers\n\t */\n\tbudget?: ThinkBudgetOptions\n\t/**\n\t * What it is given beyond the rules, each a factor (1 is none), through the game's hooks while it is seated:\n\t * `income`, what its workers bring in (1.5: half again; `beforeDeposit`); `health`, the most health of everything\n\t * it has (`stats`); `damage`, the damage it deals (`beforeDamage`, before armour); `buildTime`, how long what it\n\t * trains, builds and researches takes (0.8: a fifth sooner; `beforeProduce`). The classic handicap is `health`\n\t */\n\thandicap?: AiHandicap\n}\n\n/**\n * What a computer is given beyond the rules (`AiProfile.handicap`): each a factor, 1 (or left out) for none\n *\n * @beta\n */\nexport interface AiHandicap {\n\t/** What its workers bring in, through the game's `beforeDeposit` hook */\n\tincome?: number\n\t/** The most health of everything it has, through a `stats` hook: the classic handicap */\n\thealth?: number\n\t/** The damage it deals, before armour, through a `beforeDamage` hook */\n\tdamage?: number\n\t/** How long what it trains, builds and researches takes, through a `beforeProduce` hook: under 1 is sooner */\n\tbuildTime?: number\n}\n\n/**\n * A difficulty's or a personality's profile, the engine's or a game's\n *\n * @beta\n */\nexport type AiProfileTable = Record<string, AiProfile>\n\n/**\n * The engine's defaults of how well it plays: the bottom layer. The areas' numbers are each area's own where no layer\n * says them (`Economy`'s 8 workers)\n *\n * @beta\n */\nexport const DEFAULT_PROFILE: Readonly<AiProfile> = {\n\tdifficulty: 'normal',\n\tpersonality: 'balanced',\n\tevery: 1,\n\tmistakes: 0,\n\tvision: 'fair'\n}\n\n/** The numbers the strongest difficulties share */\nconst STRONG: AiProfile = {\n\tevery: 0.5,\n\teconomy: { workers: 10, expansions: 2 },\n\tarmy: { firstAttack: 105, attackEvery: 34, waveSize: 8 },\n\tdefence: { radius: 22 },\n\tscouting: { lookEvery: 60 }\n}\n\n/**\n * The engine's difficulties: how well it plays. `normal` is the areas' own numbers. `insane` sees through the fog and\n * gets half again of what its workers bring in, as the classic insane computer does\n *\n * @beta\n */\nexport const DIFFICULTIES: Readonly<AiProfileTable> = {\n\teasy: {\n\t\tevery: 2,\n\t\tcommandsPerThink: 12,\n\t\tmistakes: 0.25,\n\t\teconomy: { workers: 6, expansions: 0 },\n\t\tarmy: { firstAttack: 240, attackEvery: 70, waveSize: 4 },\n\t\tdefence: { radius: 10 },\n\t\tscouting: { lookEvery: 150 },\n\t\theroes: { most: 1 }\n\t},\n\tnormal: {},\n\thard: STRONG,\n\tinsane: { ...STRONG, vision: 'all', handicap: { income: 1.5 } }\n}\n\n/**\n * The engine's personalities: how it likes to play. Over the difficulty, so a rusher rushes on any of them\n *\n * @beta\n */\nexport const PERSONALITIES: Readonly<AiProfileTable> = {\n\tbalanced: {},\n\trusher: {\n\t\tarmy: { firstAttack: 90, attackEvery: 30, waveSize: 4 },\n\t\teconomy: { expansions: 0 },\n\t\tdefence: { towers: 0 },\n\t\tweights: { creep: 0.5, harass: 1.2, expand: 0.5 },\n\t\tflags: { noMercy: true }\n\t},\n\tturtle: {\n\t\tarmy: { firstAttack: 300 },\n\t\tdefence: { towers: 2, odds: 0.8 },\n\t\teconomy: { expansions: 0 },\n\t\tweights: { attack: 0.8, creep: 0.6, raid: 0.5, harass: 0.2, expand: 1.2 },\n\t\tflags: { workersFlee: true }\n\t},\n\texpander: {\n\t\teconomy: { expansions: 3, expandWhen: { all: [{ time: { after: 150 } }, { units: { role: 'barracks' } }] } },\n\t\tweights: { attack: 0.9, expand: 1.5 }\n\t},\n\tharasser: {\n\t\tarmy: { attackEvery: 30, waveSize: 4 },\n\t\tweights: { creep: 1.2, raid: 1.5, harass: 1.5 },\n\t\tflags: { kite: true, heroesFlee: 0.5, noMercy: true }\n\t}\n}\n\n/**\n * What a game says of its computer players' profiles (`GameModule.ai`): difficulties and personalities of its own, and\n * defaults over the engine's\n *\n * @beta\n */\nexport interface GameAi {\n\t/** Difficulties of its own, by name, beside (or over) the engine's */\n\tdifficulties?: AiProfileTable\n\t/** Personalities of its own, by name */\n\tpersonalities?: AiProfileTable\n\t/** Conditions of its own, by id, for the data form (`{ is: 'mygame.bridgeDown', args }`), a map's file among them */\n\tconditions?: Record<string, AiConditionTest>\n\t/** Defaults over the engine's, under the difficulty */\n\tdefaults?: AiProfile\n\t/**\n\t * How its computers play each of its races (`GameModule.races`), by race id: a layer over `defaults` and under the\n\t * difficulty, for a seat of that race (its build order, heroes, composition, flags; how often it thinks). Its\n\t * `difficulty` and `personality` are the seat's where the lobby and the map say none\n\t */\n\traces?: AiProfileTable\n\t/** Whether a lobby offers its seats a difficulty and a personality (`seatSettingsOf`): yes when left out */\n\tlobby?: boolean\n}\n\n/**\n * The difficulties a game's computers may play at, by name: the engine's, the game's over them\n *\n * @beta\n */\nexport function difficultiesOf(registry?: Pick<Registry, 'module'>): AiProfileTable {\n\treturn { ...DIFFICULTIES, ...registry?.module?.ai?.difficulties }\n}\n\n/**\n * The personalities a game's computers may have, by name: the engine's, the game's over them\n *\n * @beta\n */\nexport function personalitiesOf(registry?: Pick<Registry, 'module'>): AiProfileTable {\n\treturn { ...PERSONALITIES, ...registry?.module?.ai?.personalities }\n}\n\n/** What a profile says of how well it plays, beside its settings: layered field by field (the handicap and the budget merged) */\nconst HOW_WELL = ['brain', 'difficulty', 'personality', 'every', 'commandsPerThink', 'mistakes', 'vision', 'budget', 'handicap'] as const\n\n/**\n * A profile resolved (`resolveProfile`): what it plays by, and its settings' layers as given, lowest first, for the brain\n * to work out each think (a flag may be a function of it)\n *\n * @beta\n */\nexport interface ResolvedProfile {\n\t/** The profile, its settings layered (a flag's function left out) */\n\tprofile: AiProfile\n\t/** Its settings' layers, lowest first: the brain's, the game's, the race's, the difficulty's, the personality's, the seat's (the map's under it) */\n\tlayers: readonly AiSettings[]\n\t/** A difficulty or a personality the game does not have, passed over */\n\tunknown: string[]\n}\n\n/** A profile's settings: what is not of how well it plays */\nfunction settingsOf(profile: AiProfile | undefined): AiSettings | undefined {\n\tif (!profile) return undefined\n\tconst settings: Record<string, unknown> = { ...profile }\n\tfor (const key of HOW_WELL) delete settings[key]\n\treturn settings as AiSettings\n}\n\n/**\n * The profile a seat plays by (`Brain.profile`): the brain's settings (`BrainDef.settings`), the game's defaults, the\n * race's (`GameAi.races`, for the `race` the seat plays), the difficulty, the personality, the seat's own\n * (`AiOptions.settings`, the map's under it), each over the one before; how well it plays from the engine's defaults,\n * the game's, the race's, the difficulty, the personality and the seat's `every` and `budget`. A name the game does not\n * have is passed over, and `unknown` names it\n *\n * @beta\n */\nexport function resolveProfile(options: AiOptions, registry?: Pick<Registry, 'module'>, brain?: AiSettings, race?: string): ResolvedProfile {\n\tconst defaults = registry?.module?.ai?.defaults\n\tconst raced = race !== undefined ? registry?.module?.ai?.races?.[race] : undefined\n\tconst difficulty = options.difficulty ?? raced?.difficulty ?? defaults?.difficulty ?? 'normal'\n\tconst personality = options.personality ?? raced?.personality ?? defaults?.personality ?? 'balanced'\n\tconst difficulties = difficultiesOf(registry)\n\tconst personalities = personalitiesOf(registry)\n\tconst unknown: string[] = []\n\tif (!difficulties[difficulty]) unknown.push(`difficulty \"${difficulty}\"`)\n\tif (!personalities[personality]) unknown.push(`personality \"${personality}\"`)\n\tconst seat: AiProfile = {\n\t\t...(options.every !== undefined && { every: options.every }),\n\t\t...(options.budget !== undefined && { budget: typeof options.budget === 'number' ? { modulesPerTick: options.budget } : options.budget })\n\t}\n\tconst profile: Record<string, unknown> = {}\n\tfor (const each of [DEFAULT_PROFILE, defaults, raced, difficulties[difficulty], personalities[personality], seat])\n\t\tfor (const key of HOW_WELL) {\n\t\t\tconst value = each?.[key]\n\t\t\tif (value === undefined) continue\n\t\t\tprofile[key] = key === 'budget' || key === 'handicap' ? { ...(profile[key] as object | undefined), ...(value as object) } : value\n\t\t}\n\tprofile.difficulty = difficulty\n\tprofile.personality = personality\n\tconst layers = [\n\t\tbrain,\n\t\tsettingsOf(defaults),\n\t\tsettingsOf(raced),\n\t\tsettingsOf(difficulties[difficulty]),\n\t\tsettingsOf(personalities[personality]),\n\t\toptions.settings\n\t].filter((layer): layer is AiSettings => !!layer)\n\treturn { profile: { ...resolveSettings(layers), ...(profile as AiProfile) }, layers, unknown }\n}\n\n/**\n * A flag's value as asked now: a function of the brain worked out, data as it is. For a flag no area has a name for\n * (No Mercy, Random Paths, Allow Home Changes): the rest are the areas' (`ai.settings`)\n *\n * @beta\n */\nexport function flagOf<K extends keyof AiFlags>(ai: Brain, name: K): Exclude<AiFlags[K], (ai: Brain) => unknown> | undefined {\n\tconst value = ai.settings.flags?.[name]\n\treturn (typeof value === 'function' ? (value as (ai: Brain) => unknown)(ai) : value) as Exclude<AiFlags[K], (ai: Brain) => unknown> | undefined\n}\n"],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import type { ResourceKind } from './defs';
2
+ import { type PlayerId } from './entity';
3
+ import type { GameModule } from './game';
4
+ import type { HookDef } from './hooks';
5
+ import type { Player } from './player';
6
+ import type { Registry } from './registry';
7
+ import { type StartDef } from './start';
8
+ import type { World } from './world';
9
+ /**
10
+ * A side a player can play, with a roster of its own: melee's humans and undead. Optional: a game that lists none
11
+ * (`GameModule.races`) has no race anywhere, no choice of one in the lobby and nothing kept from anyone. A unit type or
12
+ * an upgrade of a race (`UnitTypeDef.race`, `UpgradeDef.race`) is only its players' to make; one of none, everyone's.
13
+ * Each player has one (`raceOf`): chosen in the lobby (a seat setting the server offers by itself, `seatSettingsOf`),
14
+ * given to the world as it is made (`PlayerInit.race`, `MapWorldOptions.races`), or changed by the rules (`setRace`)
15
+ *
16
+ * @beta
17
+ */
18
+ export interface RaceDef {
19
+ id: string;
20
+ /** What players are shown: in the lobby, on the scores */
21
+ name: string;
22
+ /**
23
+ * The definition this one is a copy of, made from the data (`copyOf` in a `data.json`, the editor's Copy as new):
24
+ * what it is drawn, heard and pictured as where the game gives it no look of its own
25
+ */
26
+ basedOn?: string;
27
+ /** What it is like, for a tooltip */
28
+ description?: string;
29
+ /** Its picture, by the id the game's view knows icons by */
30
+ icon?: string;
31
+ /**
32
+ * What its players start with of each resource, by resource id, over what the game starts everyone with
33
+ * (`ResourceDef.start`). Not for a player given resources of their own (`PlayerInit.resources`, a map's)
34
+ */
35
+ resources?: Partial<Record<ResourceKind, number>>;
36
+ /**
37
+ * What its players get at the start of a game on a map, in place of the game's (`GameModule.start`): its own hall and
38
+ * workers, as data (`StartData`: what a race made in the Data panel has, `start.hall` and the rest editable there)
39
+ * or as code (`StartCode`)
40
+ */
41
+ start?: StartDef;
42
+ /**
43
+ * Run for each of its players once a world is made from a map, after everything the map puts down and the starts:
44
+ * what its players begin with that is not a unit (a ground of its own around its halls, a state)
45
+ */
46
+ onStart?(world: World, player: PlayerId): void;
47
+ /**
48
+ * Hook handlers of its own, run only for what is of its players (`RaceHookDef`): how it gathers, where it may build.
49
+ * With these a race plays differently with no test of the race in the game's code
50
+ */
51
+ hooks?: RaceHookDef[];
52
+ /**
53
+ * What a race made as a copy of another (`basedOn`: `copyOf` in a `data.json`, the editor's Copy as new) keeps of the
54
+ * original's code: its `hooks` and its `onStart`, each kept unless said `false` here. A copy keeps both when this is
55
+ * left out, so a race copied from the undead gathers at a cursed mine and builds on blight as they do; one that
56
+ * says `hooks: false` plays by the game's rules alone. Its `start` is data, the copy's own to change; a `start` in
57
+ * code is kept whole. Two toggles in the Data panel, on a copy
58
+ */
59
+ inherits?: {
60
+ hooks?: boolean;
61
+ onStart?: boolean;
62
+ };
63
+ }
64
+ /**
65
+ * A hook handler of a race (`RaceDef.hooks`): run only where the event is of one of the race's players. Whose an event
66
+ * is, is `of(event)` where it is given, or else its `player`, or else the owner of the first there is of its `entity`,
67
+ * `caster`, `attacker`, `worker`, `buyer`, `hero`, `producer`, `source`, `target`: the one doing it before the one it
68
+ * is done to (a damage is its source's)
69
+ *
70
+ * @beta
71
+ */
72
+ export type RaceHookDef = HookDef & {
73
+ /** The player an event is of, where it is not the one found by default */
74
+ of?: (event: any) => PlayerId | undefined;
75
+ };
76
+ /** The player a hook's event is of (see `RaceHookDef`): undefined for one of nobody's */
77
+ export declare function playerOfEvent(event: unknown): PlayerId | undefined;
78
+ /** Each race's hook handlers, each to run only for what is of the race's players */
79
+ export declare function raceHooks(game: GameModule): HookDef[];
80
+ /**
81
+ * A race, as the game lists it (`GameModule.races`)
82
+ *
83
+ * @beta
84
+ */
85
+ export declare const defineRace: (def: RaceDef) => RaceDef;
86
+ /**
87
+ * What is chosen for a seat or a player to have a race drawn for them as the game starts, from the world's own
88
+ * numbers: the same on every machine
89
+ *
90
+ * @beta
91
+ */
92
+ export declare const RANDOM_RACE = "random";
93
+ /**
94
+ * The race a player plays: none in a game without races, and none for the neutral players and the creeps
95
+ *
96
+ * @beta
97
+ */
98
+ export declare const raceOf: (world: World, player: PlayerId) => string | undefined;
99
+ /**
100
+ * Makes a player play another race from now on: a campaign's mission, a game's own way of choosing. What they have
101
+ * stays theirs; what they may make is the new race's. Throws for a race the game does not have, or for the neutral
102
+ * players and the creeps
103
+ *
104
+ * @beta
105
+ */
106
+ export declare function setRace(world: World, player: PlayerId, race: string): void;
107
+ /**
108
+ * Whether a player may make a unit type or research an upgrade at all, as their race goes (`UnitTypeDef.race`), and
109
+ * then as the game's `available` hook says: what they may not is not on their buttons, and an order for it is
110
+ * refused. What it requires is another question (`unlocked`), asked only of what is available
111
+ *
112
+ * @beta
113
+ */
114
+ export declare function isAvailable(world: World, player: PlayerId, kind: 'unit' | 'upgrade', id: string): boolean;
115
+ /**
116
+ * The races players get as a world is made: what each was given, one drawn for those given `random`, and the game's
117
+ * first for a player given none. Nobody's in a game without races. Throws for a race the game does not have
118
+ */
119
+ export declare function settleRaces(players: Iterable<Player>, registry: Registry, draw: (count: number) => number, among?: readonly string[]): void;
120
+ /**
121
+ * Throws for races that cannot be: one there twice, one called `random`, a unit type or upgrade of a race the game does
122
+ * not have, a resource a race starts with that the game has not, or a start as data (a race's, or the game's) that names
123
+ * a unit type the game has not, saying which was meant where one is close. Run as a registry is made (`createRegistry`,
124
+ * every world's); for a game's own tests
125
+ *
126
+ * @beta
127
+ */
128
+ export declare function checkRaces(game: GameModule): void;
129
+ /**
130
+ * Gives each player of a world just made what their race starts them with (`RaceDef.resources`), but those given
131
+ * resources of their own
132
+ */
133
+ export declare function raceResources(world: World, players: readonly {
134
+ id: PlayerId;
135
+ resources?: unknown;
136
+ }[]): void;
@@ -0,0 +1,2 @@
1
+ /** What a thing placed on a map drops when it dies: one item from its table, on the ground where it fell */
2
+ export declare const dropFromTable: import("./events").ListenerDef;