@v12-engine/engine 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/LICENSE +21 -0
  2. package/dist/abilities/buffs.d.ts +83 -0
  3. package/dist/abilities/castTold.d.ts +12 -0
  4. package/dist/abilities/charges.d.ts +28 -0
  5. package/dist/abilities/dispel.d.ts +9 -0
  6. package/dist/abilities/effectFields.d.ts +10 -0
  7. package/dist/abilities/effects/buff.d.ts +8 -0
  8. package/dist/abilities/effects/core.d.ts +1 -0
  9. package/dist/abilities/effects/damage.d.ts +1 -0
  10. package/dist/abilities/effects/heal.d.ts +2 -0
  11. package/dist/abilities/effects/missile.d.ts +1 -0
  12. package/dist/abilities/effects/moves.d.ts +11 -0
  13. package/dist/abilities/effects/passives.d.ts +15 -0
  14. package/dist/abilities/effects/sight.d.ts +4 -0
  15. package/dist/abilities/effects/spawn.d.ts +2 -0
  16. package/dist/abilities/effects/timed.d.ts +4 -0
  17. package/dist/abilities/effects/trade.d.ts +1 -0
  18. package/dist/abilities/effects.d.ts +122 -0
  19. package/dist/abilities/land.d.ts +21 -0
  20. package/dist/abilities/scaled.d.ts +21 -0
  21. package/dist/abilities/text.d.ts +113 -0
  22. package/dist/ai/area.d.ts +53 -0
  23. package/dist/ai/brain.d.ts +528 -0
  24. package/dist/ai/budget.d.ts +67 -0
  25. package/dist/ai/checks.d.ts +115 -0
  26. package/dist/ai/computer.d.ts +166 -0
  27. package/dist/ai/defence.d.ts +108 -0
  28. package/dist/ai/define.d.ts +21 -0
  29. package/dist/ai/economy.d.ts +129 -0
  30. package/dist/ai/geometry.d.ts +35 -0
  31. package/dist/ai/goals.d.ts +360 -0
  32. package/dist/ai/index.d.ts +38 -0
  33. package/dist/ai/knowledge.d.ts +418 -0
  34. package/dist/ai/lanes.d.ts +232 -0
  35. package/dist/ai/melee/build.d.ts +61 -0
  36. package/dist/ai/melee/goals.d.ts +299 -0
  37. package/dist/ai/melee/heroes.d.ts +27 -0
  38. package/dist/ai/melee/index.d.ts +14 -0
  39. package/dist/ai/melee/production.d.ts +8 -0
  40. package/dist/ai/melee/surrender.d.ts +24 -0
  41. package/dist/ai/micro.d.ts +278 -0
  42. package/dist/ai/mission.d.ts +195 -0
  43. package/dist/ai/missionRules.d.ts +18 -0
  44. package/dist/ai/module.d.ts +116 -0
  45. package/dist/ai/options.d.ts +61 -0
  46. package/dist/ai/plans/build.d.ts +280 -0
  47. package/dist/ai/plans/placement.d.ts +82 -0
  48. package/dist/ai/plans/plans.d.ts +105 -0
  49. package/dist/ai/plans/production.d.ts +210 -0
  50. package/dist/ai/plans/purse.d.ts +73 -0
  51. package/dist/ai/plans/tech.d.ts +37 -0
  52. package/dist/ai/profiles.d.ts +204 -0
  53. package/dist/ai/reach.d.ts +4 -0
  54. package/dist/ai/report.d.ts +203 -0
  55. package/dist/ai/roles.d.ts +133 -0
  56. package/dist/ai/rules.d.ts +288 -0
  57. package/dist/ai/scouting.d.ts +98 -0
  58. package/dist/ai/settings.d.ts +73 -0
  59. package/dist/ai/squads.d.ts +429 -0
  60. package/dist/ai/strength.d.ts +167 -0
  61. package/dist/ai/task.d.ts +118 -0
  62. package/dist/ai/tasks/attack.d.ts +7 -0
  63. package/dist/ai/tasks/capture.d.ts +21 -0
  64. package/dist/ai/tasks/creep.d.ts +16 -0
  65. package/dist/ai/tasks/defend.d.ts +29 -0
  66. package/dist/ai/tasks/drop.d.ts +34 -0
  67. package/dist/ai/tasks/escort.d.ts +16 -0
  68. package/dist/ai/tasks/gather.d.ts +23 -0
  69. package/dist/ai/tasks/harass.d.ts +7 -0
  70. package/dist/ai/tasks/hold.d.ts +20 -0
  71. package/dist/ai/tasks/index.d.ts +32 -0
  72. package/dist/ai/tasks/move.d.ts +19 -0
  73. package/dist/ai/tasks/patrol.d.ts +8 -0
  74. package/dist/ai/tasks/retreat.d.ts +20 -0
  75. package/dist/ai/tasks/scout.d.ts +29 -0
  76. package/dist/ai/tasks/shared.d.ts +74 -0
  77. package/dist/ai/team.d.ts +155 -0
  78. package/dist/ai/threat.d.ts +91 -0
  79. package/dist/ai/view.d.ts +366 -0
  80. package/dist/ai/waves.d.ts +126 -0
  81. package/dist/ai.js +6239 -0
  82. package/dist/ai.js.map +1 -0
  83. package/dist/aiTesting.d.ts +179 -0
  84. package/dist/areas.d.ts +149 -0
  85. package/dist/attacks.d.ts +66 -0
  86. package/dist/attributes.d.ts +66 -0
  87. package/dist/brain-BvVdUhX8.js +7659 -0
  88. package/dist/brain-BvVdUhX8.js.map +1 -0
  89. package/dist/builds-C6LfgvEU.js +460 -0
  90. package/dist/builds-C6LfgvEU.js.map +1 -0
  91. package/dist/bytes.d.ts +6 -0
  92. package/dist/camps.d.ts +95 -0
  93. package/dist/capture.d.ts +131 -0
  94. package/dist/cellLayers.d.ts +75 -0
  95. package/dist/cinematics.d.ts +194 -0
  96. package/dist/clock.d.ts +32 -0
  97. package/dist/commands.d.ts +235 -0
  98. package/dist/components.d.ts +184 -0
  99. package/dist/computers.d.ts +108 -0
  100. package/dist/concealment.d.ts +61 -0
  101. package/dist/coreComponents-syuh2fPG.js +5149 -0
  102. package/dist/coreComponents-syuh2fPG.js.map +1 -0
  103. package/dist/coreComponents.d.ts +1 -0
  104. package/dist/dashing.d.ts +8 -0
  105. package/dist/debug.d.ts +36 -0
  106. package/dist/debug.js +3 -0
  107. package/dist/debugCommands-CzjrSm66.js +14739 -0
  108. package/dist/debugCommands-CzjrSm66.js.map +1 -0
  109. package/dist/debugCommands.d.ts +213 -0
  110. package/dist/debugging.d.ts +10 -0
  111. package/dist/definitions.d.ts +43 -0
  112. package/dist/defs.d.ts +1162 -0
  113. package/dist/denying.d.ts +81 -0
  114. package/dist/destructibles.d.ts +27 -0
  115. package/dist/determinism-BCymQwiE.js +518 -0
  116. package/dist/determinism-BCymQwiE.js.map +1 -0
  117. package/dist/determinism.d.ts +121 -0
  118. package/dist/dialog.d.ts +94 -0
  119. package/dist/effectRefs.d.ts +16 -0
  120. package/dist/effects.d.ts +80 -0
  121. package/dist/endings.d.ts +22 -0
  122. package/dist/engagement.d.ts +108 -0
  123. package/dist/engineEvents.d.ts +710 -0
  124. package/dist/entity.d.ts +409 -0
  125. package/dist/entityIndex.d.ts +50 -0
  126. package/dist/errors.d.ts +85 -0
  127. package/dist/events.d.ts +97 -0
  128. package/dist/exactMath.d.ts +63 -0
  129. package/dist/features.d.ts +10 -0
  130. package/dist/fields.d.ts +114 -0
  131. package/dist/fixture.d.ts +17 -0
  132. package/dist/fog.d.ts +110 -0
  133. package/dist/formation.d.ts +111 -0
  134. package/dist/friendlyFire.d.ts +26 -0
  135. package/dist/game-DiJEN-Ks.js +5800 -0
  136. package/dist/game-DiJEN-Ks.js.map +1 -0
  137. package/dist/game.d.ts +501 -0
  138. package/dist/gameData.d.ts +325 -0
  139. package/dist/gameFiles.d.ts +26 -0
  140. package/dist/gates.d.ts +28 -0
  141. package/dist/generate.d.ts +403 -0
  142. package/dist/generateWorker.d.ts +39 -0
  143. package/dist/grid.d.ts +53 -0
  144. package/dist/ground.d.ts +127 -0
  145. package/dist/groundSpeed.d.ts +22 -0
  146. package/dist/hero.d.ts +177 -0
  147. package/dist/home.d.ts +14 -0
  148. package/dist/hooks.d.ts +780 -0
  149. package/dist/hotReload.d.ts +76 -0
  150. package/dist/ids.d.ts +26 -0
  151. package/dist/index.d.ts +227 -0
  152. package/dist/index.js +4701 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/inspect-D9dWHmZ0.js +491 -0
  155. package/dist/inspect-D9dWHmZ0.js.map +1 -0
  156. package/dist/inspect.d.ts +176 -0
  157. package/dist/inventory.d.ts +18 -0
  158. package/dist/items.d.ts +91 -0
  159. package/dist/lanes.d.ts +213 -0
  160. package/dist/life.d.ts +53 -0
  161. package/dist/local-Dkovq42k.js +1379 -0
  162. package/dist/local-Dkovq42k.js.map +1 -0
  163. package/dist/log.d.ts +140 -0
  164. package/dist/manaBurn.d.ts +39 -0
  165. package/dist/map/file.d.ts +114 -0
  166. package/dist/map/images.d.ts +18 -0
  167. package/dist/map/look.d.ts +47 -0
  168. package/dist/map/pathProfile.d.ts +13 -0
  169. package/dist/map/resize.d.ts +54 -0
  170. package/dist/map/schema.d.ts +10 -0
  171. package/dist/map/terrain.d.ts +32 -0
  172. package/dist/map/types.d.ts +613 -0
  173. package/dist/map.d.ts +7 -0
  174. package/dist/mapCheck/cells.d.ts +19 -0
  175. package/dist/mapCheck/rule.d.ts +30 -0
  176. package/dist/mapCheck/rules/names.d.ts +3 -0
  177. package/dist/mapCheck/rules/objects.d.ts +3 -0
  178. package/dist/mapCheck/rules/paths.d.ts +3 -0
  179. package/dist/mapCheck/rules/players.d.ts +3 -0
  180. package/dist/mapCheck/rules/races.d.ts +3 -0
  181. package/dist/mapCheck/rules/random.d.ts +3 -0
  182. package/dist/mapCheck/rules/regions.d.ts +3 -0
  183. package/dist/mapCheck/rules/targets.d.ts +3 -0
  184. package/dist/mapCheck/rules/walking.d.ts +3 -0
  185. package/dist/mapCheck.d.ts +23 -0
  186. package/dist/mapFields.d.ts +364 -0
  187. package/dist/mapFile.d.ts +23 -0
  188. package/dist/mapMeasure.d.ts +95 -0
  189. package/dist/mapMerge.d.ts +19 -0
  190. package/dist/mapObjectives.d.ts +82 -0
  191. package/dist/mapObjects.d.ts +1 -0
  192. package/dist/math.d.ts +44 -0
  193. package/dist/messages.d.ts +150 -0
  194. package/dist/missionRules-C-bGxm0Q.js +523 -0
  195. package/dist/missionRules-C-bGxm0Q.js.map +1 -0
  196. package/dist/missionRules.d.ts +179 -0
  197. package/dist/mods.d.ts +146 -0
  198. package/dist/names.d.ts +93 -0
  199. package/dist/navigation/agentParams.d.ts +4 -0
  200. package/dist/navigation/air.d.ts +89 -0
  201. package/dist/navigation/builds.d.ts +140 -0
  202. package/dist/navigation/groundAreas.d.ts +23 -0
  203. package/dist/navigation/navigation.d.ts +127 -0
  204. package/dist/navigation/recast.d.ts +214 -0
  205. package/dist/navigation/sidePaths.d.ts +69 -0
  206. package/dist/navigation/sized.d.ts +1 -0
  207. package/dist/navigation-worker.js +11 -0
  208. package/dist/navigation-worker.js.map +1 -0
  209. package/dist/nearest.d.ts +8 -0
  210. package/dist/noise.d.ts +12 -0
  211. package/dist/objectives.d.ts +93 -0
  212. package/dist/orders/basic.d.ts +96 -0
  213. package/dist/orders/build.d.ts +91 -0
  214. package/dist/orders/cast.d.ts +105 -0
  215. package/dist/orders/facts.d.ts +14 -0
  216. package/dist/orders/harvest.d.ts +94 -0
  217. package/dist/orders/idle.d.ts +7 -0
  218. package/dist/orders/items.d.ts +14 -0
  219. package/dist/orders/queue.d.ts +24 -0
  220. package/dist/pack.schema.json +6621 -0
  221. package/dist/packs/director/index.d.ts +81 -0
  222. package/dist/packs/heroes/campaign.d.ts +137 -0
  223. package/dist/packs/heroes/carry.d.ts +59 -0
  224. package/dist/packs/heroes/commands.d.ts +6 -0
  225. package/dist/packs/heroes/hire.d.ts +9 -0
  226. package/dist/packs/heroes/index.d.ts +12 -0
  227. package/dist/packs/heroes/making.d.ts +16 -0
  228. package/dist/packs/heroes/respawn.d.ts +42 -0
  229. package/dist/packs/moba/index.d.ts +34 -0
  230. package/dist/packs/pack.d.ts +84 -0
  231. package/dist/packs-g5thvmGn.js +3199 -0
  232. package/dist/packs-g5thvmGn.js.map +1 -0
  233. package/dist/packs.d.ts +84 -0
  234. package/dist/paths.d.ts +51 -0
  235. package/dist/plain.d.ts +17 -0
  236. package/dist/player.d.ts +117 -0
  237. package/dist/portals.d.ts +66 -0
  238. package/dist/prefabs.d.ts +139 -0
  239. package/dist/presetBuildings.d.ts +52 -0
  240. package/dist/presetGround.d.ts +22 -0
  241. package/dist/profiles-B3NS9jwk.js +335 -0
  242. package/dist/profiles-B3NS9jwk.js.map +1 -0
  243. package/dist/races.d.ts +136 -0
  244. package/dist/randomGroups.d.ts +2 -0
  245. package/dist/registry.d.ts +464 -0
  246. package/dist/remains.d.ts +119 -0
  247. package/dist/replication.d.ts +103 -0
  248. package/dist/rng.d.ts +17 -0
  249. package/dist/rules.d.ts +395 -0
  250. package/dist/rulesCheck.d.ts +37 -0
  251. package/dist/runes.d.ts +41 -0
  252. package/dist/save.d.ts +277 -0
  253. package/dist/scenario.d.ts +56 -0
  254. package/dist/scheduler.d.ts +67 -0
  255. package/dist/score.d.ts +306 -0
  256. package/dist/sequences.d.ts +132 -0
  257. package/dist/server/doorman.d.ts +21 -0
  258. package/dist/server/gameServer.d.ts +346 -0
  259. package/dist/server/index.d.ts +24 -0
  260. package/dist/server/lobby.d.ts +1 -0
  261. package/dist/server/log.d.ts +13 -0
  262. package/dist/server/match.d.ts +24 -0
  263. package/dist/server/mode.d.ts +168 -0
  264. package/dist/server/navigation-worker.d.ts +1 -0
  265. package/dist/server/navigation.d.ts +11 -0
  266. package/dist/server/ops.d.ts +78 -0
  267. package/dist/server/packs.d.ts +15 -0
  268. package/dist/server/ratings.d.ts +62 -0
  269. package/dist/server/relay.d.ts +34 -0
  270. package/dist/server/rooms.d.ts +162 -0
  271. package/dist/server/seat.d.ts +2 -0
  272. package/dist/server/seatSettings.d.ts +15 -0
  273. package/dist/server/secret.d.ts +5 -0
  274. package/dist/server/start.d.ts +54 -0
  275. package/dist/server/websocket.d.ts +74 -0
  276. package/dist/server.js +2861 -0
  277. package/dist/server.js.map +1 -0
  278. package/dist/session/can.d.ts +20 -0
  279. package/dist/session/commandReplay.d.ts +92 -0
  280. package/dist/session/debug.d.ts +65 -0
  281. package/dist/session/delay.d.ts +15 -0
  282. package/dist/session/delta.d.ts +98 -0
  283. package/dist/session/entityState.d.ts +1 -0
  284. package/dist/session/local.d.ts +214 -0
  285. package/dist/session/memory.d.ts +27 -0
  286. package/dist/session/protocol.d.ts +1155 -0
  287. package/dist/session/remote.d.ts +530 -0
  288. package/dist/session/replay.d.ts +114 -0
  289. package/dist/session/seed.d.ts +7 -0
  290. package/dist/session/share.d.ts +78 -0
  291. package/dist/session/socket.d.ts +8 -0
  292. package/dist/session/wire.d.ts +153 -0
  293. package/dist/session/worker.d.ts +227 -0
  294. package/dist/shared.d.ts +171 -0
  295. package/dist/sides.d.ts +75 -0
  296. package/dist/sight.d.ts +27 -0
  297. package/dist/simulate-oXBiw1Ff.js +167 -0
  298. package/dist/simulate-oXBiw1Ff.js.map +1 -0
  299. package/dist/simulate-worker.d.ts +1 -0
  300. package/dist/simulate-worker.js +28 -0
  301. package/dist/simulate-worker.js.map +1 -0
  302. package/dist/simulate.d.ts +154 -0
  303. package/dist/smart.d.ts +9 -0
  304. package/dist/spatial.d.ts +62 -0
  305. package/dist/spawning.d.ts +33 -0
  306. package/dist/stances.d.ts +76 -0
  307. package/dist/start.d.ts +71 -0
  308. package/dist/stats.d.ts +122 -0
  309. package/dist/summons.d.ts +63 -0
  310. package/dist/systems/abilities.d.ts +3 -0
  311. package/dist/systems/combat.d.ts +71 -0
  312. package/dist/systems/combatTold.d.ts +14 -0
  313. package/dist/systems/construction.d.ts +34 -0
  314. package/dist/systems/economy.d.ts +21 -0
  315. package/dist/systems/fog.d.ts +19 -0
  316. package/dist/systems/life.d.ts +3 -0
  317. package/dist/systems/movement.d.ts +105 -0
  318. package/dist/systems/orders.d.ts +7 -0
  319. package/dist/systems/production.d.ts +49 -0
  320. package/dist/systems/productionQueue.d.ts +40 -0
  321. package/dist/systems/victory.d.ts +14 -0
  322. package/dist/talk.d.ts +65 -0
  323. package/dist/tech.d.ts +62 -0
  324. package/dist/techTree.d.ts +38 -0
  325. package/dist/terrain.d.ts +173 -0
  326. package/dist/terrainSave.d.ts +29 -0
  327. package/dist/testing.d.ts +58 -0
  328. package/dist/testing.js +822 -0
  329. package/dist/testing.js.map +1 -0
  330. package/dist/tiles.d.ts +34 -0
  331. package/dist/timers.d.ts +146 -0
  332. package/dist/tomes.d.ts +48 -0
  333. package/dist/trade.d.ts +28 -0
  334. package/dist/transport.d.ts +76 -0
  335. package/dist/tunables.d.ts +45 -0
  336. package/dist/upkeep.d.ts +16 -0
  337. package/dist/veterancy.d.ts +80 -0
  338. package/dist/walls.d.ts +86 -0
  339. package/dist/world.d.ts +1118 -0
  340. package/package.json +80 -5
  341. package/README.md +0 -3
@@ -0,0 +1,822 @@
1
+ import { Et as Terrain, Qt as createMap, Ud as dist } from "./debugCommands-CzjrSm66.js";
2
+ import { i as createWorld, o as loadWorld } from "./game-DiJEN-Ks.js";
3
+ import { ct as saveWorld, it as encodeSave, rt as decodeSave } from "./coreComponents-syuh2fPG.js";
4
+ import { a as worldHash, i as worldFingerprint, n as firstDifference, o as worldState, s as withHeroes, t as checkDeterminism } from "./determinism-BCymQwiE.js";
5
+ import { t as LocalSession } from "./local-Dkovq42k.js";
6
+ import { S as checkBrain, t as Brain, wt as explainGoal } from "./brain-BvVdUhX8.js";
7
+ import { i as winRates, n as playGame, r as simulate, t as defineSimulation } from "./simulate-oXBiw1Ff.js";
8
+ //#region src/fixture.ts
9
+ var worker = {
10
+ id: "worker",
11
+ name: "Worker",
12
+ kind: "unit",
13
+ radius: .4,
14
+ stats: {
15
+ health: 100,
16
+ attackDamage: 5,
17
+ attackSpeed: 1,
18
+ attackRange: .5,
19
+ moveSpeed: 4
20
+ },
21
+ sight: 8,
22
+ attacks: [{
23
+ damagePoint: .3,
24
+ acquisitionRange: 0,
25
+ targets: ["unit", "building"]
26
+ }],
27
+ cost: { gold: 50 },
28
+ supply: 1,
29
+ buildTime: 10,
30
+ harvester: {
31
+ capacity: 10,
32
+ gatherTime: 1
33
+ },
34
+ builds: [
35
+ "hall",
36
+ "supply",
37
+ "barracks",
38
+ "tower",
39
+ "altar"
40
+ ]
41
+ };
42
+ var soldier = {
43
+ id: "soldier",
44
+ name: "Soldier",
45
+ kind: "unit",
46
+ radius: .45,
47
+ stats: {
48
+ health: 200,
49
+ attackDamage: 10,
50
+ attackSpeed: 1,
51
+ attackRange: .5,
52
+ armor: 10,
53
+ moveSpeed: 4
54
+ },
55
+ sight: 10,
56
+ attacks: [{
57
+ damagePoint: .3,
58
+ acquisitionRange: 8
59
+ }],
60
+ cost: { gold: 100 },
61
+ supply: 2,
62
+ buildTime: 10,
63
+ abilities: ["guard"]
64
+ };
65
+ var archer = {
66
+ id: "archer",
67
+ name: "Archer",
68
+ kind: "unit",
69
+ radius: .45,
70
+ stats: {
71
+ health: 100,
72
+ attackDamage: 10,
73
+ attackSpeed: 1,
74
+ attackRange: 6,
75
+ moveSpeed: 4
76
+ },
77
+ sight: 10,
78
+ attacks: [{
79
+ damagePoint: .3,
80
+ acquisitionRange: 8,
81
+ projectileSpeed: 20,
82
+ targets: ["ground", "air"]
83
+ }],
84
+ cost: {
85
+ gold: 100,
86
+ lumber: 20
87
+ },
88
+ supply: 2,
89
+ buildTime: 10
90
+ };
91
+ var hero = {
92
+ id: "hero",
93
+ name: "Hero",
94
+ kind: "unit",
95
+ radius: .5,
96
+ stats: {
97
+ health: 300,
98
+ mana: 100,
99
+ manaRegen: 1,
100
+ attackDamage: 20,
101
+ attackSpeed: 1,
102
+ attackRange: .5,
103
+ armor: 10,
104
+ moveSpeed: 4
105
+ },
106
+ sight: 12,
107
+ attacks: [{
108
+ damagePoint: .3,
109
+ acquisitionRange: 8
110
+ }],
111
+ hero: {
112
+ growth: { stats: {
113
+ health: 20,
114
+ mana: 10,
115
+ attackDamage: 2
116
+ } },
117
+ learns: ["heal", "guard"]
118
+ },
119
+ inventory: 6,
120
+ cost: {
121
+ gold: 400,
122
+ lumber: 100
123
+ },
124
+ supply: 5,
125
+ buildTime: 40
126
+ };
127
+ var creep = {
128
+ id: "creep",
129
+ name: "Creep",
130
+ kind: "unit",
131
+ radius: .45,
132
+ stats: {
133
+ health: 200,
134
+ attackDamage: 10,
135
+ attackSpeed: 1,
136
+ attackRange: .5,
137
+ moveSpeed: 3
138
+ },
139
+ sight: 8,
140
+ attacks: [{
141
+ damagePoint: .3,
142
+ acquisitionRange: 5
143
+ }],
144
+ level: 1,
145
+ bounty: [10, 10],
146
+ xp: 20
147
+ };
148
+ var hall = {
149
+ id: "hall",
150
+ name: "Hall",
151
+ kind: "building",
152
+ radius: 2,
153
+ footprint: {
154
+ w: 4,
155
+ d: 4
156
+ },
157
+ stats: {
158
+ health: 1500,
159
+ armor: 10
160
+ },
161
+ sight: 12,
162
+ cost: {
163
+ gold: 400,
164
+ lumber: 200
165
+ },
166
+ buildTime: 40,
167
+ supplyProvided: 10,
168
+ trains: ["worker"],
169
+ dropOff: true,
170
+ upgradesTo: "keep"
171
+ };
172
+ var keep = {
173
+ ...hall,
174
+ id: "keep",
175
+ name: "Keep",
176
+ stats: {
177
+ health: 2e3,
178
+ armor: 10
179
+ },
180
+ cost: {
181
+ gold: 300,
182
+ lumber: 200
183
+ },
184
+ provides: ["hall"],
185
+ upgradesTo: void 0
186
+ };
187
+ var supply = {
188
+ id: "supply",
189
+ name: "Supply",
190
+ kind: "building",
191
+ radius: 1,
192
+ footprint: {
193
+ w: 2,
194
+ d: 2
195
+ },
196
+ stats: {
197
+ health: 500,
198
+ armor: 10
199
+ },
200
+ sight: 6,
201
+ cost: { gold: 50 },
202
+ buildTime: 10,
203
+ supplyProvided: 10
204
+ };
205
+ var barracks = {
206
+ id: "barracks",
207
+ name: "Barracks",
208
+ kind: "building",
209
+ radius: 1.5,
210
+ footprint: {
211
+ w: 3,
212
+ d: 3
213
+ },
214
+ stats: {
215
+ health: 1e3,
216
+ armor: 10
217
+ },
218
+ sight: 9,
219
+ cost: {
220
+ gold: 150,
221
+ lumber: 50
222
+ },
223
+ buildTime: 20,
224
+ trains: ["soldier", "archer"],
225
+ researches: ["armour"]
226
+ };
227
+ var tower = {
228
+ id: "tower",
229
+ name: "Tower",
230
+ kind: "building",
231
+ radius: 1,
232
+ footprint: {
233
+ w: 2,
234
+ d: 2
235
+ },
236
+ stats: {
237
+ health: 500,
238
+ attackDamage: 20,
239
+ attackSpeed: 1,
240
+ attackRange: 8,
241
+ armor: 10
242
+ },
243
+ sight: 12,
244
+ attacks: [{
245
+ damagePoint: .3,
246
+ acquisitionRange: 8,
247
+ projectileSpeed: 20,
248
+ targets: ["ground", "air"]
249
+ }],
250
+ cost: {
251
+ gold: 100,
252
+ lumber: 50
253
+ },
254
+ buildTime: 20,
255
+ requires: ["barracks"]
256
+ };
257
+ var altar = {
258
+ id: "altar",
259
+ name: "Altar",
260
+ kind: "building",
261
+ radius: 1.5,
262
+ footprint: {
263
+ w: 3,
264
+ d: 3
265
+ },
266
+ stats: {
267
+ health: 1e3,
268
+ armor: 10
269
+ },
270
+ sight: 9,
271
+ cost: {
272
+ gold: 200,
273
+ lumber: 50
274
+ },
275
+ buildTime: 30,
276
+ trains: ["hero"],
277
+ revives: true
278
+ };
279
+ var mine = {
280
+ id: "mine",
281
+ name: "Mine",
282
+ kind: "resource",
283
+ radius: 2,
284
+ footprint: {
285
+ w: 4,
286
+ d: 4
287
+ },
288
+ stats: { health: 1 },
289
+ sight: 0,
290
+ invulnerable: true,
291
+ resource: {
292
+ kind: "gold",
293
+ amount: 1e4,
294
+ slots: 1,
295
+ entered: true
296
+ }
297
+ };
298
+ var tree = {
299
+ id: "tree",
300
+ name: "Tree",
301
+ kind: "resource",
302
+ radius: .5,
303
+ footprint: {
304
+ w: 1,
305
+ d: 1
306
+ },
307
+ stats: { health: 1 },
308
+ sight: 0,
309
+ invulnerable: true,
310
+ fellable: true,
311
+ resource: {
312
+ kind: "lumber",
313
+ amount: 50,
314
+ slots: 1,
315
+ gatherTime: 5
316
+ }
317
+ };
318
+ var armour = {
319
+ id: "armour",
320
+ name: "Armour",
321
+ description: "+10 armor for soldiers and archers",
322
+ cost: {
323
+ gold: 100,
324
+ lumber: 50
325
+ },
326
+ researchTime: 20,
327
+ maxLevel: 2,
328
+ effects: [{
329
+ units: ["soldier", "archer"],
330
+ stats: { armor: 10 }
331
+ }]
332
+ };
333
+ var guarded = {
334
+ id: "guarded",
335
+ name: "Guarded",
336
+ description: "+20 armor",
337
+ duration: 10,
338
+ stats: { armor: 20 }
339
+ };
340
+ var abilities = [
341
+ {
342
+ id: "heal",
343
+ name: "Heal",
344
+ description: "Heals a friendly unit for 100 or 200",
345
+ target: "unit",
346
+ targets: {
347
+ allies: true,
348
+ self: false
349
+ },
350
+ manaCost: 10,
351
+ cooldown: 5,
352
+ range: 6,
353
+ effects: [{
354
+ type: "heal",
355
+ amount: [100, 200]
356
+ }]
357
+ },
358
+ {
359
+ id: "guard",
360
+ name: "Guard",
361
+ description: "+20 armor for 10 seconds",
362
+ target: "none",
363
+ cooldown: 10,
364
+ effects: [{
365
+ type: "buff",
366
+ buff: "guarded",
367
+ on: "caster"
368
+ }]
369
+ },
370
+ {
371
+ id: "drink",
372
+ name: "Drink",
373
+ description: "Heals 100",
374
+ target: "none",
375
+ cooldown: 10,
376
+ effects: [{
377
+ type: "heal",
378
+ amount: 100,
379
+ on: "caster"
380
+ }]
381
+ }
382
+ ];
383
+ var items = [{
384
+ id: "sword",
385
+ name: "Sword",
386
+ description: "+10 attack damage",
387
+ tier: "basic",
388
+ cost: { gold: 100 },
389
+ bonus: { stats: { attackDamage: 10 } }
390
+ }, {
391
+ id: "potion",
392
+ name: "Potion",
393
+ description: "Heals 100 when drunk",
394
+ tier: "consumable",
395
+ cost: { gold: 50 },
396
+ charges: 1,
397
+ ability: "drink"
398
+ }];
399
+ /** A hall where a player starts, and five workers on the side of the closest mine */
400
+ function startingBase(world, player, at) {
401
+ const base = world.spawn("hall", player, at);
402
+ let closest;
403
+ for (const entity of world.entities.values()) {
404
+ if (entity.def.resource?.kind !== "gold" || dist(entity.pos, base.pos) > 20) continue;
405
+ if (!closest || dist(entity.pos, base.pos) < dist(closest, base.pos)) closest = entity.pos;
406
+ }
407
+ const towards = closest ? {
408
+ x: Math.sign(closest.x - at.x),
409
+ z: Math.sign(closest.z - at.z)
410
+ } : {
411
+ x: 1,
412
+ z: 0
413
+ };
414
+ for (let i = 0; i < 5; i++) world.spawn("worker", player, {
415
+ x: at.x + towards.x * 4 + (i - 2) * towards.z,
416
+ z: at.z + towards.z * 4 + (i - 2) * towards.x
417
+ });
418
+ }
419
+ /**
420
+ * The fixture game (see the top of this file): every role of the kit, with round numbers. Gold and lumber, 1000 of each
421
+ * to start with; a hall and five workers at each start; heroes on (`withHeroes`); no fog explored at the start. A new
422
+ * one each time, for a test to change
423
+ *
424
+ * @beta
425
+ */
426
+ function fixtureGame() {
427
+ return {
428
+ id: "fixture",
429
+ name: "Fixture",
430
+ version: "1.0.0",
431
+ units: [
432
+ worker,
433
+ soldier,
434
+ archer,
435
+ hero,
436
+ creep,
437
+ hall,
438
+ keep,
439
+ supply,
440
+ barracks,
441
+ tower,
442
+ altar,
443
+ mine,
444
+ tree
445
+ ].map((def) => structuredClone(def)),
446
+ upgrades: [structuredClone(armour)],
447
+ abilities: structuredClone(abilities),
448
+ buffs: [structuredClone(guarded)],
449
+ items: structuredClone(items),
450
+ resources: [{
451
+ id: "gold",
452
+ name: "Gold",
453
+ start: 1e3
454
+ }, {
455
+ id: "lumber",
456
+ name: "Lumber",
457
+ start: 1e3
458
+ }],
459
+ currency: "gold",
460
+ packs: [withHeroes()],
461
+ start: { spawn: startingBase }
462
+ };
463
+ }
464
+ /**
465
+ * A map of the fixture game, 64 cells a side: two players, starting at opposite corners (12, 12 and 52, 52), a gold
466
+ * mine and a row of trees by each start, and a camp of three creeps in the middle
467
+ *
468
+ * @beta
469
+ */
470
+ function fixtureMap() {
471
+ const map = createMap({
472
+ name: "Fixture",
473
+ width: 64,
474
+ depth: 64,
475
+ game: "fixture"
476
+ });
477
+ map.players[0].start = {
478
+ x: 12,
479
+ z: 12
480
+ };
481
+ map.players[1].start = {
482
+ x: 52,
483
+ z: 52
484
+ };
485
+ let id = 1;
486
+ const object = (type, x, z) => map.objects.push({
487
+ id: id++,
488
+ type,
489
+ owner: 0,
490
+ x,
491
+ z,
492
+ facing: 0,
493
+ scale: 1
494
+ });
495
+ object("mine", 12, 22);
496
+ object("mine", 52, 42);
497
+ for (let i = 0; i < 6; i++) {
498
+ object("tree", 22.5 + i, 4.5);
499
+ object("tree", 36.5 + i, 59.5);
500
+ }
501
+ map.camps.push({
502
+ id: id++,
503
+ x: 32,
504
+ z: 32,
505
+ units: [
506
+ "creep",
507
+ "creep",
508
+ "creep"
509
+ ]
510
+ });
511
+ return map;
512
+ }
513
+ //#endregion
514
+ //#region src/aiTesting.ts
515
+ /**
516
+ * Testing a computer player (AI plan, E3): what a game's tests of its brains are written with, in
517
+ * `@v12-engine/engine/testing` beside `testWorld` and `run`. A brain is tested as it plays, through the world it sits in:
518
+ *
519
+ * const world = await testWorld(myGame)
520
+ * world.computers.seat(ENEMY, { enemyBases: [home], brain: myBrain })
521
+ * const watch = watchComputer(world, ENEMY) // its invariants, every think
522
+ * run(world, 120)
523
+ * expectDecision(thinkOnce(world, ENEMY), 'ai.attack')
524
+ * watch.assert() // no rule broken
525
+ *
526
+ * `thinkOnce` has a seated brain think now and gives its report; `expectDecision` says a goal runs, or why not in
527
+ * words; `watchComputer` checks the invariants of `ai/checks.ts` after every think (a unit in one squad, gold spent
528
+ * once, finite numbers, commands about what it sees, no churn, nothing stuck) and keeps what it decided; `fairPlay` is
529
+ * the one about seeing; `recordDecisions` keeps every computer's decisions for a replay's side file; `checkComputerSave`
530
+ * is the seventh invariant: a game saved and loaded decides the same from then on. These take the world, which a test
531
+ * may: the brains under test never do.
532
+ */
533
+ /**
534
+ * The brain that plays a player, where one is seated (`world.computers.seat`): none where nobody is, or where what is
535
+ * seated is not a brain (`defineComputer`)
536
+ *
537
+ * @beta
538
+ */
539
+ function brainOf(world, player) {
540
+ const computer = world.computers.get(player)?.computer;
541
+ return computer instanceof Brain ? computer : void 0;
542
+ }
543
+ /** The brain at a player, or an error that says what is seated there instead */
544
+ function seated(world, player) {
545
+ const brain = brainOf(world, player);
546
+ if (brain) return brain;
547
+ const system = world.computers.get(player);
548
+ throw new Error(system ? `The computer player at ${player} is not a brain (defineBrain): it has no report` : `No computer player is seated at ${player}`);
549
+ }
550
+ /**
551
+ * Has the brain at a player think now, all of it (a think its budget slices over ticks is run to its end), over a new
552
+ * picture of the game, and gives its report: what a test reads after setting a scene. Its commands land at the next
553
+ * tick, as a think's do. A think the seat would have had is not skipped: this one is beside them
554
+ *
555
+ * @beta
556
+ */
557
+ function thinkOnce(world, player) {
558
+ const brain = seated(world, player);
559
+ do
560
+ brain.think();
561
+ while (brain.busy);
562
+ return brain.report();
563
+ }
564
+ /**
565
+ * Says that a goal runs, as of a report (`thinkOnce`, `Brain.report`): it is picked and holds what it claimed. Throws
566
+ * where it does not, with its row in words (`Brain.explain`): what each consideration answered and what kept it out.
567
+ * Gives the goal's row. With `picked: false`, says it does not run
568
+ *
569
+ * expectDecision(thinkOnce(world, ENEMY), 'ai.defend')
570
+ *
571
+ * @beta
572
+ */
573
+ function expectDecision(report, goal, options = {}) {
574
+ const wanted = options.picked ?? true;
575
+ const row = report.goals.find((each) => each.id === goal);
576
+ if (!row) throw new Error(`The brain ${report.brain} has no goal "${goal}": its goals are ${report.goals.map((each) => each.id).join(", ") || "none"}`);
577
+ if (row.picked === wanted) return row;
578
+ const seconds = (tick) => tick / report.tickRate;
579
+ throw new Error(`Expected ${goal} ${wanted ? "to run" : "not to run"} at ${report.time.toFixed(1)} s, and it ${wanted ? "does not" : "does"}. ${explainGoal(row, seconds, report.time)}${report.goal && report.goal !== goal ? ` The best goal is ${report.goal}.` : ""}`);
580
+ }
581
+ /**
582
+ * Follows the brain at a player from now on: after every think, the invariants of `ai/checks.ts` (a unit in one squad
583
+ * and one hold, gold spent once, finite numbers, commands about what it sees, no order sent again to a unit still at
584
+ * it, builders, tasks, holds and wants that end), with what it decided and sent. A broken rule is kept, not thrown,
585
+ * unless `onViolation` throws: `assert` at the end says them all
586
+ *
587
+ * @beta
588
+ */
589
+ function watchComputer(world, player, options = {}) {
590
+ const brain = seated(world, player);
591
+ const violations = [];
592
+ const decisions = [];
593
+ let thinks = 0;
594
+ let commands = 0;
595
+ const { stop: unchecked } = checkBrain(brain, {
596
+ ...options,
597
+ onViolation: (violation) => {
598
+ violations.push(violation);
599
+ options.onViolation?.(violation);
600
+ }
601
+ });
602
+ const observer = options.observe ? new LocalSession(world, player, { observer: true }) : void 0;
603
+ const unwatched = brain.watch({
604
+ sent: (command) => {
605
+ commands++;
606
+ options.sent?.(command, brain);
607
+ },
608
+ decided: (decision) => void decisions.push(decision),
609
+ thought: () => {
610
+ thinks++;
611
+ if (observer) options.observe(observer.snapshot(), brain);
612
+ }
613
+ });
614
+ return {
615
+ brain,
616
+ violations,
617
+ decisions,
618
+ get thinks() {
619
+ return thinks;
620
+ },
621
+ get commands() {
622
+ return commands;
623
+ },
624
+ assert() {
625
+ if (!violations.length) return;
626
+ const lines = violations.slice(0, 20).map((each) => ` ${each.invariant} at tick ${each.tick}: ${each.message}`);
627
+ const more = violations.length > 20 ? `\n and ${violations.length - 20} more` : "";
628
+ throw new Error(`The computer player at ${player} broke ${violations.length} rule${violations.length === 1 ? "" : "s"}:\n${lines.join("\n")}${more}`);
629
+ },
630
+ stop() {
631
+ unchecked();
632
+ unwatched();
633
+ observer?.dispose();
634
+ }
635
+ };
636
+ }
637
+ /**
638
+ * Follows the brain at a player from now on for fair play: that it never sends a command about an entity its snapshot
639
+ * did not have (a fog leak: its seat's session would drop the command, so a game shows nothing; this says it), and
640
+ * counts what the game refused
641
+ *
642
+ * @beta
643
+ */
644
+ function fairPlay(world, player) {
645
+ const watch = watchComputer(world, player, { invariants: ["commands"] });
646
+ const brain = watch.brain;
647
+ const refusedBefore = brain.stats.refused;
648
+ return {
649
+ get unfair() {
650
+ return watch.violations;
651
+ },
652
+ get refused() {
653
+ return brain.stats.refused - refusedBefore;
654
+ },
655
+ assert: () => watch.assert(),
656
+ stop: () => watch.stop()
657
+ };
658
+ }
659
+ /** How many recorders were made: each one's system a name of its own */
660
+ var recorders = 0;
661
+ /**
662
+ * Keeps the decisions of every brain seated at a world, from now on, those seated later included (looked for at each
663
+ * tick, by a system of its own that keeps nothing in a save)
664
+ *
665
+ * @beta
666
+ */
667
+ function recordDecisions(world) {
668
+ const decisions = [];
669
+ const watched = /* @__PURE__ */ new Map();
670
+ const look = () => {
671
+ for (const player of world.computers.list()) {
672
+ const brain = brainOf(world, player);
673
+ if (!brain || watched.has(brain)) continue;
674
+ watched.set(brain, brain.watch({ decided: (decision) => void decisions.push({
675
+ ...decision,
676
+ player: brain.playerId,
677
+ brain: brain.def.id
678
+ }) }));
679
+ }
680
+ };
681
+ look();
682
+ const name = `core.ai.recordDecisions.${++recorders}`;
683
+ world.addSystem({
684
+ name,
685
+ update: look
686
+ });
687
+ return {
688
+ decisions,
689
+ stop() {
690
+ world.removeSystem(name);
691
+ for (const unwatch of watched.values()) unwatch();
692
+ watched.clear();
693
+ }
694
+ };
695
+ }
696
+ /**
697
+ * The seventh invariant of a computer player: a game saved at tick `from` and loaded makes the same decisions from then
698
+ * on as the game it was saved from, under the same commands. Makes the world with `make` (its computers seated, as a
699
+ * game seats them), runs it to `from`, saves it as a file would keep it and loads that with `game`, then runs both to
700
+ * `ticks` and compares what every computer decided. What lost rng, tasks or memory in a restore shows as
701
+ *
702
+ * expect(await checkComputerSave(() => duel(), { from: 600, ticks: 2400, game: melee })).toBeNull()
703
+ *
704
+ * @beta
705
+ */
706
+ async function checkComputerSave(make, options) {
707
+ const saved = await make();
708
+ let loaded;
709
+ try {
710
+ while (saved.tick < options.from) saved.step();
711
+ loaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { game: options.game });
712
+ const before = recordDecisions(saved);
713
+ const after = recordDecisions(loaded);
714
+ while (saved.tick < options.ticks) {
715
+ saved.step();
716
+ loaded.step();
717
+ }
718
+ before.stop();
719
+ after.stop();
720
+ const a = before.decisions;
721
+ const b = after.decisions;
722
+ for (let i = 0; i < Math.max(a.length, b.length); i++) if (JSON.stringify(a[i]) !== JSON.stringify(b[i])) return {
723
+ index: i,
724
+ ...a[i] && { saved: a[i] },
725
+ ...b[i] && { loaded: b[i] }
726
+ };
727
+ return null;
728
+ } finally {
729
+ saved.dispose();
730
+ loaded?.dispose();
731
+ }
732
+ }
733
+ //#endregion
734
+ //#region src/testing.ts
735
+ /**
736
+ * Flat ground, `size` cells a side: 48 when left out
737
+ *
738
+ * @beta
739
+ */
740
+ var flatTerrain = (size = 48) => new Terrain(size, size, new Float32Array((size + 1) * (size + 1)));
741
+ /**
742
+ * The players of a test world, when a test says none: a neutral one, and two who are enemies
743
+ *
744
+ * @beta
745
+ */
746
+ var TEST_PLAYERS = [
747
+ {
748
+ id: 0,
749
+ name: "Neutral",
750
+ team: 0,
751
+ color: [
752
+ 1,
753
+ 1,
754
+ 0
755
+ ],
756
+ neutral: true
757
+ },
758
+ {
759
+ id: 1,
760
+ name: "Player",
761
+ team: 1,
762
+ color: [
763
+ 0,
764
+ 0,
765
+ 1
766
+ ]
767
+ },
768
+ {
769
+ id: 2,
770
+ name: "Enemy",
771
+ team: 2,
772
+ color: [
773
+ 1,
774
+ 0,
775
+ 0
776
+ ]
777
+ }
778
+ ];
779
+ /**
780
+ * A small world of a game for a test: flat ground, a neutral player and two enemies (`TEST_PLAYERS`), the same every
781
+ * time (seed 7). Each of them is the test's to say otherwise
782
+ *
783
+ * @beta
784
+ */
785
+ function testWorld(game, options = {}) {
786
+ return createWorld({
787
+ terrain: options.terrain ?? flatTerrain(options.size),
788
+ game,
789
+ seed: options.seed ?? 7,
790
+ players: options.players ?? TEST_PLAYERS.map((player) => ({ ...player })),
791
+ log: options.log
792
+ });
793
+ }
794
+ /**
795
+ * Steps the world for up to `seconds`, stopping early once `until` holds. Returns the time that went by in it
796
+ *
797
+ * @beta
798
+ */
799
+ function run(world, seconds, until) {
800
+ const ticks = Math.ceil(seconds * world.tickRate);
801
+ for (let i = 0; i < ticks; i++) {
802
+ world.step();
803
+ if (until?.()) return (i + 1) / world.tickRate;
804
+ }
805
+ return seconds;
806
+ }
807
+ /**
808
+ * Gives units an order, as their owner would: taken up at the next tick. `queue` adds it after what they are doing
809
+ *
810
+ * @beta
811
+ */
812
+ var order = (world, entities, init, queue = false) => world.issue({
813
+ type: "order",
814
+ player: entities[0].owner,
815
+ entities: entities.map((entity) => entity.id),
816
+ order: init,
817
+ queue
818
+ });
819
+ //#endregion
820
+ export { TEST_PLAYERS, brainOf, checkComputerSave, checkDeterminism, defineSimulation, expectDecision, fairPlay, firstDifference, fixtureGame, fixtureMap, flatTerrain, order, playGame, recordDecisions, run, simulate, testWorld, thinkOnce, watchComputer, winRates, worldFingerprint, worldHash, worldState };
821
+
822
+ //# sourceMappingURL=testing.js.map