@v12-engine/engine 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abilities/amounts.d.ts +28 -0
- package/dist/abilities/amounts.js +74 -0
- package/dist/abilities/amounts.js.map +1 -0
- package/dist/abilities/buffs.d.ts +106 -6
- package/dist/abilities/buffs.js +443 -0
- package/dist/abilities/buffs.js.map +1 -0
- package/dist/abilities/castTold.d.ts +2 -0
- package/dist/abilities/castTold.js +66 -0
- package/dist/abilities/castTold.js.map +1 -0
- package/dist/abilities/chance.d.ts +38 -0
- package/dist/abilities/chance.js +77 -0
- package/dist/abilities/chance.js.map +1 -0
- package/dist/abilities/charges.d.ts +18 -0
- package/dist/abilities/charges.js +101 -0
- package/dist/abilities/charges.js.map +1 -0
- package/dist/abilities/control.d.ts +28 -0
- package/dist/abilities/control.js +113 -0
- package/dist/abilities/control.js.map +1 -0
- package/dist/abilities/dispel.js +51 -0
- package/dist/abilities/dispel.js.map +1 -0
- package/dist/abilities/effectFields.d.ts +1 -1
- package/dist/abilities/effectFields.js +676 -0
- package/dist/abilities/effectFields.js.map +1 -0
- package/dist/abilities/effectIndex.d.ts +27 -0
- package/dist/abilities/effectIndex.js +64 -0
- package/dist/abilities/effectIndex.js.map +1 -0
- package/dist/abilities/effects/buff.d.ts +9 -3
- package/dist/abilities/effects/buff.js +84 -0
- package/dist/abilities/effects/buff.js.map +1 -0
- package/dist/abilities/effects/conditions.d.ts +2 -0
- package/dist/abilities/effects/conditions.js +41 -0
- package/dist/abilities/effects/conditions.js.map +1 -0
- package/dist/abilities/effects/core.js +54 -0
- package/dist/abilities/effects/core.js.map +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -1
- package/dist/abilities/effects/damage.js +43 -0
- package/dist/abilities/effects/damage.js.map +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -2
- package/dist/abilities/effects/heal.js +51 -0
- package/dist/abilities/effects/heal.js.map +1 -0
- package/dist/abilities/effects/missile.d.ts +13 -1
- package/dist/abilities/effects/missile.js +104 -0
- package/dist/abilities/effects/missile.js.map +1 -0
- package/dist/abilities/effects/morph.d.ts +5 -0
- package/dist/abilities/effects/morph.js +43 -0
- package/dist/abilities/effects/morph.js.map +1 -0
- package/dist/abilities/effects/moves.d.ts +16 -4
- package/dist/abilities/effects/moves.js +212 -0
- package/dist/abilities/effects/moves.js.map +1 -0
- package/dist/abilities/effects/passives.d.ts +19 -9
- package/dist/abilities/effects/passives.js +131 -0
- package/dist/abilities/effects/passives.js.map +1 -0
- package/dist/abilities/effects/proxy.d.ts +5 -0
- package/dist/abilities/effects/proxy.js +60 -0
- package/dist/abilities/effects/proxy.js.map +1 -0
- package/dist/abilities/effects/sight.d.ts +2 -2
- package/dist/abilities/effects/sight.js +39 -0
- package/dist/abilities/effects/sight.js.map +1 -0
- package/dist/abilities/effects/spawn.d.ts +5 -2
- package/dist/abilities/effects/spawn.js +40 -0
- package/dist/abilities/effects/spawn.js.map +1 -0
- package/dist/abilities/effects/timed.d.ts +2 -2
- package/dist/abilities/effects/timed.js +96 -0
- package/dist/abilities/effects/timed.js.map +1 -0
- package/dist/abilities/effects/trade.d.ts +1 -1
- package/dist/abilities/effects/trade.js +25 -0
- package/dist/abilities/effects/trade.js.map +1 -0
- package/dist/abilities/effects.d.ts +97 -23
- package/dist/abilities/effects.js +860 -0
- package/dist/abilities/effects.js.map +1 -0
- package/dist/abilities/land.d.ts +38 -4
- package/dist/abilities/land.js +189 -0
- package/dist/abilities/land.js.map +1 -0
- package/dist/abilities/recast.d.ts +45 -0
- package/dist/abilities/recast.js +118 -0
- package/dist/abilities/recast.js.map +1 -0
- package/dist/abilities/scaled.js +40 -0
- package/dist/abilities/scaled.js.map +1 -0
- package/dist/abilities/screen.d.ts +6 -0
- package/dist/abilities/screen.js +83 -0
- package/dist/abilities/screen.js.map +1 -0
- package/dist/abilities/shapes.d.ts +66 -0
- package/dist/abilities/shapes.js +122 -0
- package/dist/abilities/shapes.js.map +1 -0
- package/dist/abilities/text.d.ts +14 -2
- package/dist/abilities/text.js +204 -0
- package/dist/abilities/text.js.map +1 -0
- package/dist/abilities/triggers.d.ts +98 -0
- package/dist/abilities/triggers.js +351 -0
- package/dist/abilities/triggers.js.map +1 -0
- package/dist/abilityChanges.d.ts +131 -0
- package/dist/abilityChanges.js +345 -0
- package/dist/abilityChanges.js.map +1 -0
- package/dist/ai/area.d.ts +4 -1
- package/dist/ai/brain.d.ts +4 -1
- package/dist/ai/brain.js +844 -0
- package/dist/ai/brain.js.map +1 -0
- package/dist/ai/budget.js +74 -0
- package/dist/ai/budget.js.map +1 -0
- package/dist/ai/checks.d.ts +9 -1
- package/dist/ai/checks.js +242 -0
- package/dist/ai/checks.js.map +1 -0
- package/dist/ai/computer.d.ts +11 -4
- package/dist/ai/computer.js +251 -0
- package/dist/ai/computer.js.map +1 -0
- package/dist/ai/defence.d.ts +4 -0
- package/dist/ai/defence.js +430 -0
- package/dist/ai/defence.js.map +1 -0
- package/dist/ai/define.d.ts +3 -2
- package/dist/ai/define.js +31 -0
- package/dist/ai/define.js.map +1 -0
- package/dist/ai/economy.d.ts +10 -7
- package/dist/ai/economy.js +780 -0
- package/dist/ai/economy.js.map +1 -0
- package/dist/ai/geometry.js +38 -0
- package/dist/ai/geometry.js.map +1 -0
- package/dist/ai/goals.d.ts +1 -0
- package/dist/ai/goals.js +560 -0
- package/dist/ai/goals.js.map +1 -0
- package/dist/ai/knowledge.d.ts +72 -7
- package/dist/ai/knowledge.js +804 -0
- package/dist/ai/knowledge.js.map +1 -0
- package/dist/ai/lanes.d.ts +10 -2
- package/dist/ai/lanes.js +715 -0
- package/dist/ai/lanes.js.map +1 -0
- package/dist/ai/melee/build.js +264 -0
- package/dist/ai/melee/build.js.map +1 -0
- package/dist/ai/melee/goals.d.ts +7 -0
- package/dist/ai/melee/goals.js +720 -0
- package/dist/ai/melee/goals.js.map +1 -0
- package/dist/ai/melee/heroes.js +68 -0
- package/dist/ai/melee/heroes.js.map +1 -0
- package/dist/ai/melee/index.d.ts +1 -1
- package/dist/ai/melee/index.js +51 -0
- package/dist/ai/melee/index.js.map +1 -0
- package/dist/ai/melee/production.js +29 -0
- package/dist/ai/melee/production.js.map +1 -0
- package/dist/ai/melee/surrender.js +64 -0
- package/dist/ai/melee/surrender.js.map +1 -0
- package/dist/ai/micro.d.ts +9 -0
- package/dist/ai/micro.js +1316 -0
- package/dist/ai/micro.js.map +1 -0
- package/dist/ai/mission.d.ts +9 -2
- package/dist/ai/mission.js +538 -0
- package/dist/ai/mission.js.map +1 -0
- package/dist/ai/missionRules.d.ts +1 -1
- package/dist/ai/missionRules.js +26 -0
- package/dist/ai/missionRules.js.map +1 -0
- package/dist/ai/module.d.ts +6 -2
- package/dist/ai/module.js +37 -0
- package/dist/ai/module.js.map +1 -0
- package/dist/ai/options.d.ts +3 -3
- package/dist/ai/plans/build.d.ts +20 -1
- package/dist/ai/plans/build.js +608 -0
- package/dist/ai/plans/build.js.map +1 -0
- package/dist/ai/plans/placement.d.ts +4 -1
- package/dist/ai/plans/placement.js +295 -0
- package/dist/ai/plans/placement.js.map +1 -0
- package/dist/ai/plans/plans.d.ts +9 -0
- package/dist/ai/plans/plans.js +110 -0
- package/dist/ai/plans/plans.js.map +1 -0
- package/dist/ai/plans/production.d.ts +14 -2
- package/dist/ai/plans/production.js +434 -0
- package/dist/ai/plans/production.js.map +1 -0
- package/dist/ai/plans/purse.d.ts +6 -3
- package/dist/ai/plans/purse.js +139 -0
- package/dist/ai/plans/purse.js.map +1 -0
- package/dist/ai/plans/tech.d.ts +6 -0
- package/dist/ai/plans/tech.js +122 -0
- package/dist/ai/plans/tech.js.map +1 -0
- package/dist/ai/profiles.d.ts +4 -4
- package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
- package/dist/ai/profiles.js.map +1 -0
- package/dist/ai/reach.js +54 -0
- package/dist/ai/reach.js.map +1 -0
- package/dist/ai/report.d.ts +8 -0
- package/dist/ai/report.js +87 -0
- package/dist/ai/report.js.map +1 -0
- package/dist/ai/roles.d.ts +4 -0
- package/dist/ai/roles.js +207 -0
- package/dist/ai/roles.js.map +1 -0
- package/dist/ai/rules.d.ts +8 -2
- package/dist/ai/rules.js +416 -0
- package/dist/ai/rules.js.map +1 -0
- package/dist/ai/scouting.d.ts +6 -0
- package/dist/ai/scouting.js +324 -0
- package/dist/ai/scouting.js.map +1 -0
- package/dist/ai/settings.js +99 -0
- package/dist/ai/settings.js.map +1 -0
- package/dist/ai/squads.d.ts +21 -2
- package/dist/ai/squads.js +916 -0
- package/dist/ai/squads.js.map +1 -0
- package/dist/ai/strength.js +320 -0
- package/dist/ai/strength.js.map +1 -0
- package/dist/ai/task.d.ts +3 -1
- package/dist/ai/task.js +17 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tasks/attack.js +24 -0
- package/dist/ai/tasks/attack.js.map +1 -0
- package/dist/ai/tasks/capture.d.ts +3 -3
- package/dist/ai/tasks/capture.js +37 -0
- package/dist/ai/tasks/capture.js.map +1 -0
- package/dist/ai/tasks/creep.js +29 -0
- package/dist/ai/tasks/creep.js.map +1 -0
- package/dist/ai/tasks/defend.js +61 -0
- package/dist/ai/tasks/defend.js.map +1 -0
- package/dist/ai/tasks/drop.js +81 -0
- package/dist/ai/tasks/drop.js.map +1 -0
- package/dist/ai/tasks/escort.js +59 -0
- package/dist/ai/tasks/escort.js.map +1 -0
- package/dist/ai/tasks/gather.js +48 -0
- package/dist/ai/tasks/gather.js.map +1 -0
- package/dist/ai/tasks/harass.js +39 -0
- package/dist/ai/tasks/harass.js.map +1 -0
- package/dist/ai/tasks/hold.js +32 -0
- package/dist/ai/tasks/hold.js.map +1 -0
- package/dist/ai/tasks/index.js +34 -0
- package/dist/ai/tasks/index.js.map +1 -0
- package/dist/ai/tasks/move.js +26 -0
- package/dist/ai/tasks/move.js.map +1 -0
- package/dist/ai/tasks/patrol.js +59 -0
- package/dist/ai/tasks/patrol.js.map +1 -0
- package/dist/ai/tasks/retreat.js +28 -0
- package/dist/ai/tasks/retreat.js.map +1 -0
- package/dist/ai/tasks/scout.js +73 -0
- package/dist/ai/tasks/scout.js.map +1 -0
- package/dist/ai/tasks/shared.d.ts +1 -1
- package/dist/ai/tasks/shared.js +137 -0
- package/dist/ai/tasks/shared.js.map +1 -0
- package/dist/ai/team.d.ts +18 -1
- package/dist/ai/team.js +492 -0
- package/dist/ai/team.js.map +1 -0
- package/dist/ai/threat.d.ts +6 -0
- package/dist/ai/threat.js +206 -0
- package/dist/ai/threat.js.map +1 -0
- package/dist/ai/view.d.ts +21 -7
- package/dist/ai/view.js +677 -0
- package/dist/ai/view.js.map +1 -0
- package/dist/ai/waves.d.ts +6 -0
- package/dist/ai/waves.js +410 -0
- package/dist/ai/waves.js.map +1 -0
- package/dist/ai.js +54 -6239
- package/dist/aiTesting.d.ts +6 -3
- package/dist/aiTesting.js +229 -0
- package/dist/aiTesting.js.map +1 -0
- package/dist/areas.d.ts +4 -1
- package/dist/areas.js +295 -0
- package/dist/areas.js.map +1 -0
- package/dist/attacks.d.ts +3 -3
- package/dist/attacks.js +127 -0
- package/dist/attacks.js.map +1 -0
- package/dist/burning.d.ts +267 -0
- package/dist/burning.js +795 -0
- package/dist/burning.js.map +1 -0
- package/dist/bytes.js +21 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callings.d.ts +71 -0
- package/dist/callings.js +157 -0
- package/dist/callings.js.map +1 -0
- package/dist/cameraOrders.d.ts +78 -0
- package/dist/cameraOrders.js +114 -0
- package/dist/cameraOrders.js.map +1 -0
- package/dist/camps.d.ts +70 -4
- package/dist/camps.js +501 -0
- package/dist/camps.js.map +1 -0
- package/dist/capture.d.ts +15 -3
- package/dist/capture.js +304 -0
- package/dist/capture.js.map +1 -0
- package/dist/cellLayers.d.ts +78 -13
- package/dist/cellLayers.js +275 -0
- package/dist/cellLayers.js.map +1 -0
- package/dist/cellPatches.d.ts +24 -0
- package/dist/cellPatches.js +73 -0
- package/dist/cellPatches.js.map +1 -0
- package/dist/cinematics.d.ts +10 -5
- package/dist/cinematics.js +161 -0
- package/dist/cinematics.js.map +1 -0
- package/dist/clock.d.ts +2 -2
- package/dist/clock.js +78 -0
- package/dist/clock.js.map +1 -0
- package/dist/commands.d.ts +36 -4
- package/dist/commands.js +636 -0
- package/dist/commands.js.map +1 -0
- package/dist/components.d.ts +31 -10
- package/dist/components.js +74 -0
- package/dist/components.js.map +1 -0
- package/dist/computers.d.ts +4 -4
- package/dist/computers.js +194 -0
- package/dist/computers.js.map +1 -0
- package/dist/concealment.d.ts +25 -2
- package/dist/concealment.js +409 -0
- package/dist/concealment.js.map +1 -0
- package/dist/coreComponents.js +130 -0
- package/dist/coreComponents.js.map +1 -0
- package/dist/createGame.d.ts +306 -0
- package/dist/createGame.js +405 -0
- package/dist/createGame.js.map +1 -0
- package/dist/dashing.d.ts +18 -2
- package/dist/dashing.js +41 -0
- package/dist/dashing.js.map +1 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +5 -3
- package/dist/debug2.js +76 -0
- package/dist/debug2.js.map +1 -0
- package/dist/debugCommands.d.ts +6 -6
- package/dist/debugCommands.js +537 -0
- package/dist/debugCommands.js.map +1 -0
- package/dist/debugging.d.ts +1 -0
- package/dist/defaultSets.d.ts +183 -0
- package/dist/defaultSets.js +216 -0
- package/dist/defaultSets.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.js +78 -0
- package/dist/definitions.js.map +1 -0
- package/dist/defs.d.ts +1895 -165
- package/dist/defs.js +380 -0
- package/dist/defs.js.map +1 -0
- package/dist/denying.d.ts +4 -4
- package/dist/denying.js +106 -0
- package/dist/denying.js.map +1 -0
- package/dist/destructibles.d.ts +2 -2
- package/dist/destructibles.js +36 -0
- package/dist/destructibles.js.map +1 -0
- package/dist/determinism.d.ts +4 -4
- package/dist/determinism.js +247 -0
- package/dist/determinism.js.map +1 -0
- package/dist/dialog.d.ts +17 -2
- package/dist/dialog.js +108 -0
- package/dist/dialog.js.map +1 -0
- package/dist/effectRefs.js +28 -0
- package/dist/effectRefs.js.map +1 -0
- package/dist/effects.d.ts +27 -11
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/endings.d.ts +1 -1
- package/dist/endings.js +78 -0
- package/dist/endings.js.map +1 -0
- package/dist/engagement.d.ts +40 -6
- package/dist/engagement.js +530 -0
- package/dist/engagement.js.map +1 -0
- package/dist/engineEvents.d.ts +72 -9
- package/dist/engineEvents.js +520 -0
- package/dist/engineEvents.js.map +1 -0
- package/dist/entity.d.ts +275 -26
- package/dist/entity.js +441 -0
- package/dist/entity.js.map +1 -0
- package/dist/entityIndex.d.ts +10 -3
- package/dist/entityIndex.js +149 -0
- package/dist/entityIndex.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +11 -5
- package/dist/events.js +158 -0
- package/dist/events.js.map +1 -0
- package/dist/exactMath.js +273 -0
- package/dist/exactMath.js.map +1 -0
- package/dist/features.d.ts +1 -1
- package/dist/features.js +127 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +25 -5
- package/dist/fields.js +140 -0
- package/dist/fields.js.map +1 -0
- package/dist/fixture.d.ts +3 -3
- package/dist/fixture.js +512 -0
- package/dist/fixture.js.map +1 -0
- package/dist/fog.d.ts +26 -3
- package/dist/fog.js +333 -0
- package/dist/fog.js.map +1 -0
- package/dist/foliage.d.ts +476 -0
- package/dist/foliage.js +1478 -0
- package/dist/foliage.js.map +1 -0
- package/dist/foliageDebug.d.ts +57 -0
- package/dist/foliageDebug.js +172 -0
- package/dist/foliageDebug.js.map +1 -0
- package/dist/foliageRegrowth.d.ts +20 -0
- package/dist/foliageRegrowth.js +332 -0
- package/dist/foliageRegrowth.js.map +1 -0
- package/dist/formState.d.ts +67 -0
- package/dist/formState.js +65 -0
- package/dist/formState.js.map +1 -0
- package/dist/formation.d.ts +46 -8
- package/dist/formation.js +297 -0
- package/dist/formation.js.map +1 -0
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +146 -0
- package/dist/forms.js.map +1 -0
- package/dist/friendlyFire.d.ts +2 -2
- package/dist/friendlyFire.js +37 -0
- package/dist/friendlyFire.js.map +1 -0
- package/dist/game.d.ts +141 -48
- package/dist/game.js +834 -0
- package/dist/game.js.map +1 -0
- package/dist/gameData.d.ts +96 -22
- package/dist/gameData.js +1690 -0
- package/dist/gameData.js.map +1 -0
- package/dist/gameFiles.d.ts +3 -3
- package/dist/gameFiles.js +14 -0
- package/dist/gameFiles.js.map +1 -0
- package/dist/gates.js +92 -0
- package/dist/gates.js.map +1 -0
- package/dist/generate.d.ts +28 -1
- package/dist/generate.js +1062 -0
- package/dist/generate.js.map +1 -0
- package/dist/generateWorker.d.ts +7 -3
- package/dist/generateWorker.js +86 -0
- package/dist/generateWorker.js.map +1 -0
- package/dist/grid.d.ts +9 -0
- package/dist/grid.js +102 -0
- package/dist/grid.js.map +1 -0
- package/dist/ground.d.ts +17 -1
- package/dist/ground.js +375 -0
- package/dist/ground.js.map +1 -0
- package/dist/groundObjects.d.ts +70 -0
- package/dist/groundObjects.js +371 -0
- package/dist/groundObjects.js.map +1 -0
- package/dist/groundSpeed.d.ts +20 -3
- package/dist/groundSpeed.js +117 -0
- package/dist/groundSpeed.js.map +1 -0
- package/dist/hero.d.ts +126 -10
- package/dist/hero.js +432 -0
- package/dist/hero.js.map +1 -0
- package/dist/holds.d.ts +94 -0
- package/dist/holds.js +305 -0
- package/dist/holds.js.map +1 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.js +30 -0
- package/dist/home.js.map +1 -0
- package/dist/hooks.d.ts +339 -57
- package/dist/hooks.js +105 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hotReload.d.ts +6 -5
- package/dist/hotReload.js +145 -0
- package/dist/hotReload.js.map +1 -0
- package/dist/ids.d.ts +3 -3
- package/dist/ids.js +30 -0
- package/dist/ids.js.map +1 -0
- package/dist/idsFile.d.ts +36 -0
- package/dist/idsFile.js +134 -0
- package/dist/idsFile.js.map +1 -0
- package/dist/index.d.ts +105 -68
- package/dist/index.js +194 -4701
- package/dist/inspect.d.ts +29 -2
- package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
- package/dist/inspect.js.map +1 -0
- package/dist/inventory.d.ts +14 -1
- package/dist/inventory.js +84 -0
- package/dist/inventory.js.map +1 -0
- package/dist/items.d.ts +136 -8
- package/dist/items.js +585 -0
- package/dist/items.js.map +1 -0
- package/dist/lanes.d.ts +12 -3
- package/dist/lanes.js +496 -0
- package/dist/lanes.js.map +1 -0
- package/dist/life.d.ts +6 -2
- package/dist/life.js +287 -0
- package/dist/life.js.map +1 -0
- package/dist/log.d.ts +26 -3
- package/dist/log.js +192 -0
- package/dist/log.js.map +1 -0
- package/dist/manaBurn.d.ts +2 -2
- package/dist/manaBurn.js +75 -0
- package/dist/manaBurn.js.map +1 -0
- package/dist/map/file.d.ts +56 -3
- package/dist/map/file.js +264 -0
- package/dist/map/file.js.map +1 -0
- package/dist/map/images.js +61 -0
- package/dist/map/images.js.map +1 -0
- package/dist/map/look.d.ts +1 -1
- package/dist/map/look.js +30 -0
- package/dist/map/look.js.map +1 -0
- package/dist/map/pathProfile.js +183 -0
- package/dist/map/pathProfile.js.map +1 -0
- package/dist/map/resize.d.ts +4 -0
- package/dist/map/resize.js +136 -0
- package/dist/map/resize.js.map +1 -0
- package/dist/map/schema.js +257 -0
- package/dist/map/schema.js.map +1 -0
- package/dist/map/terrain.js +214 -0
- package/dist/map/terrain.js.map +1 -0
- package/dist/map/types.d.ts +92 -13
- package/dist/map/types.js +251 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mapCheck/cells.js +94 -0
- package/dist/mapCheck/cells.js.map +1 -0
- package/dist/mapCheck/rules/foliage.d.ts +9 -0
- package/dist/mapCheck/rules/foliage.js +83 -0
- package/dist/mapCheck/rules/foliage.js.map +1 -0
- package/dist/mapCheck/rules/names.js +39 -0
- package/dist/mapCheck/rules/names.js.map +1 -0
- package/dist/mapCheck/rules/objects.d.ts +1 -1
- package/dist/mapCheck/rules/objects.js +56 -0
- package/dist/mapCheck/rules/objects.js.map +1 -0
- package/dist/mapCheck/rules/paths.js +32 -0
- package/dist/mapCheck/rules/paths.js.map +1 -0
- package/dist/mapCheck/rules/players.js +20 -0
- package/dist/mapCheck/rules/players.js.map +1 -0
- package/dist/mapCheck/rules/races.js +56 -0
- package/dist/mapCheck/rules/races.js.map +1 -0
- package/dist/mapCheck/rules/random.js +47 -0
- package/dist/mapCheck/rules/random.js.map +1 -0
- package/dist/mapCheck/rules/regions.js +30 -0
- package/dist/mapCheck/rules/regions.js.map +1 -0
- package/dist/mapCheck/rules/targets.js +31 -0
- package/dist/mapCheck/rules/targets.js.map +1 -0
- package/dist/mapCheck/rules/walking.js +45 -0
- package/dist/mapCheck/rules/walking.js.map +1 -0
- package/dist/mapCheck.d.ts +2 -2
- package/dist/mapCheck.js +63 -0
- package/dist/mapCheck.js.map +1 -0
- package/dist/mapFields.d.ts +25 -2
- package/dist/mapFields.js +134 -0
- package/dist/mapFields.js.map +1 -0
- package/dist/mapFile.js +176 -0
- package/dist/mapFile.js.map +1 -0
- package/dist/mapMeasure.d.ts +8 -0
- package/dist/mapMeasure.js +283 -0
- package/dist/mapMeasure.js.map +1 -0
- package/dist/mapMerge.d.ts +1 -0
- package/dist/mapMerge.js +172 -0
- package/dist/mapMerge.js.map +1 -0
- package/dist/mapObjectives.js +138 -0
- package/dist/mapObjectives.js.map +1 -0
- package/dist/mapObjects.js +80 -0
- package/dist/mapObjects.js.map +1 -0
- package/dist/math.d.ts +37 -7
- package/dist/math.js +155 -0
- package/dist/math.js.map +1 -0
- package/dist/messages.d.ts +71 -4
- package/dist/messages.js +29 -0
- package/dist/messages.js.map +1 -0
- package/dist/missionRules.d.ts +10 -2
- package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
- package/dist/missionRules.js.map +1 -0
- package/dist/mods.d.ts +39 -20
- package/dist/mods.js +271 -0
- package/dist/mods.js.map +1 -0
- package/dist/moves.d.ts +87 -0
- package/dist/moves.js +539 -0
- package/dist/moves.js.map +1 -0
- package/dist/names.d.ts +7 -0
- package/dist/names.js +122 -0
- package/dist/names.js.map +1 -0
- package/dist/navigation/agentParams.js +14 -0
- package/dist/navigation/agentParams.js.map +1 -0
- package/dist/navigation/air.d.ts +7 -3
- package/dist/navigation/air.js +401 -0
- package/dist/navigation/air.js.map +1 -0
- package/dist/navigation/builds.d.ts +34 -2
- package/dist/navigation/builds.js +287 -0
- package/dist/navigation/builds.js.map +1 -0
- package/dist/navigation/groundAreas.d.ts +59 -1
- package/dist/navigation/groundAreas.js +407 -0
- package/dist/navigation/groundAreas.js.map +1 -0
- package/dist/navigation/navigation.d.ts +98 -9
- package/dist/navigation/recast.d.ts +194 -18
- package/dist/navigation/recast.js +1379 -0
- package/dist/navigation/recast.js.map +1 -0
- package/dist/navigation/sidePaths.d.ts +8 -3
- package/dist/navigation/sidePaths.js +241 -0
- package/dist/navigation/sidePaths.js.map +1 -0
- package/dist/navigation/sized.js +243 -0
- package/dist/navigation/sized.js.map +1 -0
- package/dist/nearest.js +32 -0
- package/dist/nearest.js.map +1 -0
- package/dist/noise.js +59 -0
- package/dist/noise.js.map +1 -0
- package/dist/objectives.d.ts +12 -3
- package/dist/objectives.js +144 -0
- package/dist/objectives.js.map +1 -0
- package/dist/orders/basic.d.ts +5 -5
- package/dist/orders/basic.js +417 -0
- package/dist/orders/basic.js.map +1 -0
- package/dist/orders/build.js +278 -0
- package/dist/orders/build.js.map +1 -0
- package/dist/orders/cast.d.ts +13 -3
- package/dist/orders/cast.js +558 -0
- package/dist/orders/cast.js.map +1 -0
- package/dist/orders/facts.js +16 -0
- package/dist/orders/facts.js.map +1 -0
- package/dist/orders/harvest.d.ts +21 -5
- package/dist/orders/harvest.js +540 -0
- package/dist/orders/harvest.js.map +1 -0
- package/dist/orders/idle.d.ts +3 -1
- package/dist/orders/idle.js +234 -0
- package/dist/orders/idle.js.map +1 -0
- package/dist/orders/items.js +92 -0
- package/dist/orders/items.js.map +1 -0
- package/dist/orders/queue.js +108 -0
- package/dist/orders/queue.js.map +1 -0
- package/dist/orders/waiting.d.ts +39 -0
- package/dist/orders/waiting.js +149 -0
- package/dist/orders/waiting.js.map +1 -0
- package/dist/pack.schema.js +13 -0
- package/dist/pack.schema.js.map +1 -0
- package/dist/pack.schema.json +7622 -841
- package/dist/packs/director/index.d.ts +13 -5
- package/dist/packs/director/index.js +204 -0
- package/dist/packs/director/index.js.map +1 -0
- package/dist/packs/heroes/campaign.d.ts +3 -2
- package/dist/packs/heroes/campaign.js +241 -0
- package/dist/packs/heroes/campaign.js.map +1 -0
- package/dist/packs/heroes/carry.d.ts +6 -0
- package/dist/packs/heroes/carry.js +112 -0
- package/dist/packs/heroes/carry.js.map +1 -0
- package/dist/packs/heroes/commands.js +115 -0
- package/dist/packs/heroes/commands.js.map +1 -0
- package/dist/packs/heroes/fallen.d.ts +43 -0
- package/dist/packs/heroes/fallen.js +61 -0
- package/dist/packs/heroes/fallen.js.map +1 -0
- package/dist/packs/heroes/hire.js +60 -0
- package/dist/packs/heroes/hire.js.map +1 -0
- package/dist/packs/heroes/index.d.ts +7 -6
- package/dist/packs/heroes/index.js +130 -0
- package/dist/packs/heroes/index.js.map +1 -0
- package/dist/packs/heroes/loop.d.ts +95 -0
- package/dist/packs/heroes/loop.js +250 -0
- package/dist/packs/heroes/loop.js.map +1 -0
- package/dist/packs/heroes/making.d.ts +6 -3
- package/dist/packs/heroes/making.js +55 -0
- package/dist/packs/heroes/making.js.map +1 -0
- package/dist/packs/heroes/respawn.d.ts +3 -3
- package/dist/packs/heroes/respawn.js +87 -0
- package/dist/packs/heroes/respawn.js.map +1 -0
- package/dist/packs/heroes/sets.d.ts +32 -0
- package/dist/packs/heroes/sets.js +51 -0
- package/dist/packs/heroes/sets.js.map +1 -0
- package/dist/packs/heroes/spells.d.ts +16 -0
- package/dist/packs/heroes/spells.js +269 -0
- package/dist/packs/heroes/spells.js.map +1 -0
- package/dist/packs/items/defaults.d.ts +43 -0
- package/dist/packs/items/defaults.js +1504 -0
- package/dist/packs/items/defaults.js.map +1 -0
- package/dist/packs/items/index.d.ts +27 -0
- package/dist/packs/items/index.js +214 -0
- package/dist/packs/items/index.js.map +1 -0
- package/dist/packs/moba/index.d.ts +3 -3
- package/dist/packs/moba/index.js +174 -0
- package/dist/packs/moba/index.js.map +1 -0
- package/dist/packs/pack.d.ts +15 -15
- package/dist/packs/pack.js +14 -0
- package/dist/packs/pack.js.map +1 -0
- package/dist/packs.d.ts +15 -7
- package/dist/packs.js +222 -0
- package/dist/packs.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +109 -0
- package/dist/paths.js.map +1 -0
- package/dist/plain.js +57 -0
- package/dist/plain.js.map +1 -0
- package/dist/player.d.ts +33 -10
- package/dist/player.js +159 -0
- package/dist/player.js.map +1 -0
- package/dist/portals.d.ts +1 -1
- package/dist/portals.js +194 -0
- package/dist/portals.js.map +1 -0
- package/dist/prefabs.d.ts +25 -2
- package/dist/prefabs.js +239 -0
- package/dist/prefabs.js.map +1 -0
- package/dist/presetBuildings.js +58 -0
- package/dist/presetBuildings.js.map +1 -0
- package/dist/presetFoliage.d.ts +27 -0
- package/dist/presetFoliage.js +98 -0
- package/dist/presetFoliage.js.map +1 -0
- package/dist/presetGround.js +65 -0
- package/dist/presetGround.js.map +1 -0
- package/dist/proxies.d.ts +12 -0
- package/dist/proxies.js +79 -0
- package/dist/proxies.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +88 -0
- package/dist/query.js.map +1 -0
- package/dist/races.d.ts +15 -14
- package/dist/races.js +172 -0
- package/dist/races.js.map +1 -0
- package/dist/randomGroups.js +91 -0
- package/dist/randomGroups.js.map +1 -0
- package/dist/registry.d.ts +117 -53
- package/dist/registry.js +323 -0
- package/dist/registry.js.map +1 -0
- package/dist/remains.d.ts +11 -9
- package/dist/remains.js +188 -0
- package/dist/remains.js.map +1 -0
- package/dist/replication.d.ts +12 -7
- package/dist/replication.js +100 -0
- package/dist/replication.js.map +1 -0
- package/dist/rng.d.ts +2 -0
- package/dist/rng.js +40 -0
- package/dist/rng.js.map +1 -0
- package/dist/rules.d.ts +186 -99
- package/dist/rules.js +179 -0
- package/dist/rules.js.map +1 -0
- package/dist/rulesCheck.d.ts +5 -4
- package/dist/rulesCheck.js +693 -0
- package/dist/rulesCheck.js.map +1 -0
- package/dist/runes.d.ts +2 -2
- package/dist/runes.js +80 -0
- package/dist/runes.js.map +1 -0
- package/dist/save.d.ts +37 -12
- package/dist/save.js +532 -0
- package/dist/save.js.map +1 -0
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +99 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.js +156 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/score.d.ts +19 -19
- package/dist/score.js +709 -0
- package/dist/score.js.map +1 -0
- package/dist/sequences.d.ts +10 -6
- package/dist/sequences.js +206 -0
- package/dist/sequences.js.map +1 -0
- package/dist/server/doorman.js +154 -0
- package/dist/server/doorman.js.map +1 -0
- package/dist/server/gameServer.d.ts +16 -1
- package/dist/server/gameServer.js +643 -0
- package/dist/server/gameServer.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/lobby.js +199 -0
- package/dist/server/lobby.js.map +1 -0
- package/dist/server/log.js +18 -0
- package/dist/server/log.js.map +1 -0
- package/dist/server/match.js +267 -0
- package/dist/server/match.js.map +1 -0
- package/dist/server/mode.d.ts +18 -9
- package/dist/server/mode.js +220 -0
- package/dist/server/mode.js.map +1 -0
- package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
- package/dist/server/navigation-worker.js.map +1 -0
- package/dist/server/navigation.js +39 -0
- package/dist/server/navigation.js.map +1 -0
- package/dist/server/ops.d.ts +4 -0
- package/dist/server/ops.js +137 -0
- package/dist/server/ops.js.map +1 -0
- package/dist/server/packs.d.ts +3 -3
- package/dist/server/packs.js +32 -0
- package/dist/server/packs.js.map +1 -0
- package/dist/server/ratings.d.ts +5 -0
- package/dist/server/ratings.js +104 -0
- package/dist/server/ratings.js.map +1 -0
- package/dist/server/relay.d.ts +12 -2
- package/dist/server/relay.js +144 -0
- package/dist/server/relay.js.map +1 -0
- package/dist/server/rooms.d.ts +9 -2
- package/dist/server/rooms.js +442 -0
- package/dist/server/rooms.js.map +1 -0
- package/dist/server/seat.js +116 -0
- package/dist/server/seat.js.map +1 -0
- package/dist/server/seatSettings.d.ts +3 -3
- package/dist/server/seatSettings.js +63 -0
- package/dist/server/seatSettings.js.map +1 -0
- package/dist/server/secret.js +13 -0
- package/dist/server/secret.js.map +1 -0
- package/dist/server/start.d.ts +13 -6
- package/dist/server/start.js +76 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/websocket.d.ts +9 -1
- package/dist/server/websocket.js +306 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/server.js +15 -2861
- package/dist/session/can.js +26 -0
- package/dist/session/can.js.map +1 -0
- package/dist/session/commandReplay.d.ts +8 -2
- package/dist/session/commandReplay.js +293 -0
- package/dist/session/commandReplay.js.map +1 -0
- package/dist/session/debug.js +151 -0
- package/dist/session/debug.js.map +1 -0
- package/dist/session/delay.js +62 -0
- package/dist/session/delay.js.map +1 -0
- package/dist/session/delta.d.ts +14 -1
- package/dist/session/delta.js +407 -0
- package/dist/session/delta.js.map +1 -0
- package/dist/session/entityState.js +415 -0
- package/dist/session/entityState.js.map +1 -0
- package/dist/session/local.d.ts +47 -5
- package/dist/session/local.js +670 -0
- package/dist/session/local.js.map +1 -0
- package/dist/session/memory.d.ts +20 -2
- package/dist/session/memory.js +131 -0
- package/dist/session/memory.js.map +1 -0
- package/dist/session/protocol.d.ts +325 -31
- package/dist/session/protocol.js +55 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/remote.d.ts +74 -12
- package/dist/session/remote.js +1394 -0
- package/dist/session/remote.js.map +1 -0
- package/dist/session/replay.d.ts +11 -2
- package/dist/session/replay.js +160 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/seed.js +12 -0
- package/dist/session/seed.js.map +1 -0
- package/dist/session/share.d.ts +5 -1
- package/dist/session/share.js +94 -0
- package/dist/session/share.js.map +1 -0
- package/dist/session/socket.d.ts +1 -1
- package/dist/session/socket.js +29 -0
- package/dist/session/socket.js.map +1 -0
- package/dist/session/wire.d.ts +5 -0
- package/dist/session/wire.js +84 -0
- package/dist/session/wire.js.map +1 -0
- package/dist/session/worker.d.ts +77 -12
- package/dist/session/worker.js +499 -0
- package/dist/session/worker.js.map +1 -0
- package/dist/shared.d.ts +31 -5
- package/dist/shared.js +166 -0
- package/dist/shared.js.map +1 -0
- package/dist/sides.d.ts +9 -3
- package/dist/sides.js +149 -0
- package/dist/sides.js.map +1 -0
- package/dist/sight.js +85 -0
- package/dist/sight.js.map +1 -0
- package/dist/simulate-worker.js +1 -1
- package/dist/simulate.d.ts +12 -8
- package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
- package/dist/simulate.js.map +1 -0
- package/dist/smart.js +77 -0
- package/dist/smart.js.map +1 -0
- package/dist/spatial.d.ts +32 -16
- package/dist/spatial.js +234 -0
- package/dist/spatial.js.map +1 -0
- package/dist/spawning.d.ts +1 -0
- package/dist/spawning.js +224 -0
- package/dist/spawning.js.map +1 -0
- package/dist/stances.d.ts +6 -3
- package/dist/stances.js +169 -0
- package/dist/stances.js.map +1 -0
- package/dist/start.d.ts +10 -10
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/stats.d.ts +42 -16
- package/dist/stats.js +290 -0
- package/dist/stats.js.map +1 -0
- package/dist/summoned.d.ts +52 -0
- package/dist/summoned.js +38 -0
- package/dist/summoned.js.map +1 -0
- package/dist/summons.d.ts +10 -13
- package/dist/summons.js +271 -0
- package/dist/summons.js.map +1 -0
- package/dist/systems/abilities.js +224 -0
- package/dist/systems/abilities.js.map +1 -0
- package/dist/systems/combat.d.ts +35 -1
- package/dist/systems/combat.js +677 -0
- package/dist/systems/combat.js.map +1 -0
- package/dist/systems/combatTold.d.ts +3 -1
- package/dist/systems/combatTold.js +85 -0
- package/dist/systems/combatTold.js.map +1 -0
- package/dist/systems/construction.js +80 -0
- package/dist/systems/construction.js.map +1 -0
- package/dist/systems/economy.d.ts +0 -6
- package/dist/systems/economy.js +128 -0
- package/dist/systems/economy.js.map +1 -0
- package/dist/systems/fog.d.ts +1 -1
- package/dist/systems/fog.js +120 -0
- package/dist/systems/fog.js.map +1 -0
- package/dist/systems/life.js +32 -0
- package/dist/systems/life.js.map +1 -0
- package/dist/systems/movement.d.ts +24 -12
- package/dist/systems/movement.js +1247 -0
- package/dist/systems/movement.js.map +1 -0
- package/dist/systems/orders.js +64 -0
- package/dist/systems/orders.js.map +1 -0
- package/dist/systems/production.js +322 -0
- package/dist/systems/production.js.map +1 -0
- package/dist/systems/productionQueue.js +120 -0
- package/dist/systems/productionQueue.js.map +1 -0
- package/dist/systems/victory.d.ts +1 -1
- package/dist/systems/victory.js +56 -0
- package/dist/systems/victory.js.map +1 -0
- package/dist/talk.d.ts +6 -6
- package/dist/talk.js +153 -0
- package/dist/talk.js.map +1 -0
- package/dist/targeting.d.ts +142 -0
- package/dist/targeting.js +49 -0
- package/dist/targeting.js.map +1 -0
- package/dist/tech.d.ts +20 -3
- package/dist/tech.js +239 -0
- package/dist/tech.js.map +1 -0
- package/dist/techTree.d.ts +7 -0
- package/dist/techTree.js +90 -0
- package/dist/techTree.js.map +1 -0
- package/dist/terrain.d.ts +59 -7
- package/dist/terrain.js +389 -0
- package/dist/terrain.js.map +1 -0
- package/dist/terrainSave.d.ts +6 -0
- package/dist/terrainSave.js +74 -0
- package/dist/terrainSave.js.map +1 -0
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +13 -739
- package/dist/testing.js.map +1 -1
- package/dist/tiles.d.ts +1 -1
- package/dist/tiles.js +43 -0
- package/dist/tiles.js.map +1 -0
- package/dist/timers.d.ts +29 -4
- package/dist/timers.js +242 -0
- package/dist/timers.js.map +1 -0
- package/dist/tomes.d.ts +4 -4
- package/dist/tomes.js +94 -0
- package/dist/tomes.js.map +1 -0
- package/dist/trade.js +103 -0
- package/dist/trade.js.map +1 -0
- package/dist/transport.d.ts +6 -1
- package/dist/transport.js +281 -0
- package/dist/transport.js.map +1 -0
- package/dist/tunables.d.ts +10 -3
- package/dist/tunables.js +56 -0
- package/dist/tunables.js.map +1 -0
- package/dist/unitResources.d.ts +67 -0
- package/dist/unitResources.js +266 -0
- package/dist/unitResources.js.map +1 -0
- package/dist/upkeep.d.ts +6 -1
- package/dist/upkeep.js +26 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/veterancy.d.ts +8 -3
- package/dist/veterancy.js +131 -0
- package/dist/veterancy.js.map +1 -0
- package/dist/vision.d.ts +36 -0
- package/dist/vision.js +133 -0
- package/dist/vision.js.map +1 -0
- package/dist/walls.d.ts +1 -1
- package/dist/walls.js +278 -0
- package/dist/walls.js.map +1 -0
- package/dist/world.d.ts +606 -88
- package/dist/world.js +1263 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
- package/dist/ai.js.map +0 -1
- package/dist/attributes.d.ts +0 -66
- package/dist/brain-BvVdUhX8.js +0 -7659
- package/dist/brain-BvVdUhX8.js.map +0 -1
- package/dist/builds-C6LfgvEU.js +0 -460
- package/dist/builds-C6LfgvEU.js.map +0 -1
- package/dist/coreComponents-syuh2fPG.js +0 -5149
- package/dist/coreComponents-syuh2fPG.js.map +0 -1
- package/dist/debugCommands-CzjrSm66.js +0 -14739
- package/dist/debugCommands-CzjrSm66.js.map +0 -1
- package/dist/determinism-BCymQwiE.js +0 -518
- package/dist/determinism-BCymQwiE.js.map +0 -1
- package/dist/game-DiJEN-Ks.js +0 -5800
- package/dist/game-DiJEN-Ks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect-D9dWHmZ0.js.map +0 -1
- package/dist/local-Dkovq42k.js +0 -1379
- package/dist/local-Dkovq42k.js.map +0 -1
- package/dist/missionRules-C-bGxm0Q.js.map +0 -1
- package/dist/navigation-worker.js.map +0 -1
- package/dist/packs-g5thvmGn.js +0 -3199
- package/dist/packs-g5thvmGn.js.map +0 -1
- package/dist/profiles-B3NS9jwk.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/simulate-oXBiw1Ff.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goals.js","names":[],"sources":["../../../src/ai/melee/goals.ts"],"sourcesContent":["import { baseStats } from '#engine/defs'\nimport type { MeleeSurrenderOptions } from './surrender'\nimport { Defence } from '../defence'\nimport { Team } from '../team'\nimport { Waves } from '../waves'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModule, type AiModuleDef, defineModule, moduleKey } from '#engine/ai/module'\nimport { consider, curve, defineGoal, type Claimed, type GoalDef } from '#engine/ai/goals'\nimport type { EnemyBase } from '#engine/ai/knowledge'\nimport { flagOf } from '#engine/ai/profiles'\nimport type { Squad, SquadOptions } from '#engine/ai/squads'\nimport type { Base, UnitSet } from '#engine/ai/view'\nimport { heroOfState } from '#engine/hero'\nimport { where } from '../geometry'\n\n/*\n * The melee player's army (AI plan, D3): what its fighters do when nothing is raiding home, as goals on the brain's\n * picker (B1), each scoring itself from what it sees and claiming the units it needs, so that several run at once\n * on different units. Beside them on the picker are the kit's: `defend` (the defence's, C4), `help` (the team's,\n * C5) and `scout` (the scouting's, C3); the fall back home from a lost fight is the squads' (C1), and with waves given\n * as data (D2) the waves module sends those and `attack` stands aside. The goals here:\n *\n * - **attack** (0.8): the wave of its own. Its time comes `firstAttack` seconds in and every `attackEvery` after, or\n * sooner when their army as last seen is weak against what it has ready (No Mercy) or its team asks it to come\n * along; it goes once enough fighters stand idle (`waveSize`, two more each wave) **and it is worth going**: a\n * wave that would lose against their army as last seen (`goOdds`) waits and trains on, up to `waitAtMost`. The\n * wave is a squad (`wave`) sent at the nearest of their buildings it knows, held while it is out; idle fighters at\n * home make up what it lost (`reinforce`); once it razed what it went for, it goes on to the next while it is strong\n * enough (`pressOn`), rather than walking home to wait for the clock; not strong enough, it walks home rather than\n * stand idle where it razed it. A wave that falls back puts the next one off.\n * - **creep** (0.5): a camp of creeps near home taken by the hero and a few, between waves, for the hero's levels.\n * - **raid** (0.6): their workers hit where their army is not. Their workers as last seen are clustered by their\n * bases; a base with workers and no army seen near it lately gets a small, fast party (`size`) sent round their\n * army (`avoid`), which goes for the workers first and falls back early (`retreatAt`). The economy is what a\n * raid hurts: a mine with no workers brings in nothing.\n * - **harass** (0.5): before the first wave, the hero and a few at their main, for the same reason, while their army\n * is not seen there.\n * - **expand** (0.7): a few guards at a base past home that has no tower yet, so that a raid on it is met where it\n * lands and not from across the map; only fighters to spare past a wave go.\n *\n * The weights are what each is worth at its best against the others; a personality's `weights` scale them\n * (`harasser` raids and harasses more, `turtle` less). Every number is an option (`MeleeArmyOptions`, data: the seat's\n * `AiOptions.army` goes over the brain's), every goal can be left out (`false`). What the army remembers (the next\n * wave's time and size, how many went, the last raid) is plain data in the brain's memory, under `melee.army`\n */\n\n/**\n * How the melee player's army goes about its own waves and the goals beside them (`AiSettings.army` over the melee\n * brain's `army(options)`). Data: a save keeps the seat's\n *\n * @beta\n */\nexport interface MeleeArmyOptions {\n\t/** Seconds before its first wave: 150 when left out */\n\tfirstAttack?: number\n\t/** Seconds between two waves: 45 when left out */\n\tattackEvery?: number\n\t/** Units in its first wave, each after bringing two more: 6 when left out */\n\twaveSize?: number\n\t/**\n\t * The odds (`Strength.odds`) of what it has ready against their army as last seen (the last minute) under which a\n\t * wave whose time has come waits and trains on rather than go: 0.4 when left out; `false` never waits\n\t */\n\tgoOdds?: number | false\n\t/**\n\t * Seconds a wave waits past its time at the most, outmatched or short of its size: then it goes with what it has,\n\t * half the wave at the least, where that would hold against what is remembered to reach the target. Twice\n\t * `attackEvery` when left out. A wave that could never reach its size (the supply capped) still comes\n\t */\n\twaitAtMost?: number\n\t/** Whether a wave that razed what it went for goes on to the next of their buildings it knows, while it is strong enough: yes when left out */\n\tpressOn?: boolean\n\t/**\n\t * Where a wave of its own goes among their buildings it knows of: the `nearest`, or the `weakest` (the one the least\n\t * of their strength is remembered to reach: an expansion before a main with towers; the nearest among those alike).\n\t * `weakest` when left out\n\t */\n\ttarget?: 'nearest' | 'weakest'\n\t/**\n\t * Whether a wave of theirs that died at its gate is answered at once with what is ready (half a wave at the least),\n\t * their base being empty of it: yes when left out. `counterAfter` is how many of their fighters must have fallen\n\t * near its bases in the last twenty seconds (3 when left out)\n\t */\n\tcounter?: boolean\n\t/** How many of their fighters must have fallen near its bases in the last twenty seconds for the counter: 3 when left out */\n\tcounterAfter?: number\n\t/** The odds against their army as last seen a wave needs to go on: 0.5 when left out */\n\tpressOdds?: number\n\t/** Whether idle fighters at home join a wave that is out, making up what it lost: yes when left out */\n\treinforce?: boolean\n\t/**\n\t * A strike while their army is away (FJ1): every sighting of their army within `awayFor` seconds (60) stands far\n\t * from what a wave would go for (their base, out raiding or creeping or at a base of mine), and what is ready (half\n\t * a wave at the least) would hold against what is remembered to reach it at these odds (`odds`, 0.6): the wave goes\n\t * before its time. `false` for none\n\t */\n\tstrike?: false | { awayFor?: number; odds?: number }\n\t/** Units more in each wave than the one before: 2 when left out */\n\twaveGrowth?: number\n\t/** The most units a wave of its own asks for: 24 when left out */\n\twaveMax?: number\n\t/**\n\t * Raids on their workers where their army is not (the `raid` goal): how many go (`size`, 3, the fastest), the odds\n\t * against what is remembered at the base they need (`odds`, 0.6), seconds between raids (`every`, 60), seconds\n\t * their army must not have been seen near the base (`armyAwayFor`, 45), how long ago their workers were seen at\n\t * the most (`workersSeenFor`, 120), the odds the raiders fall back at (`retreatAt`, 0.5). `false` for no raids\n\t */\n\traid?: false | { size?: number; odds?: number; every?: number; armyAwayFor?: number; workersSeenFor?: number; retreatAt?: number }\n\t/**\n\t * Harassing their main before the first wave (the `harass` goal): the party (`size`, 3: the hero and the fastest),\n\t * the odds it needs at their base (`odds`, 0.6), seconds between (`every`, 90), the odds it falls back at\n\t * (`retreatAt`, 0.5). `false` for none\n\t */\n\tharass?: false | { size?: number; odds?: number; every?: number; retreatAt?: number }\n\t/**\n\t * Guards at a base past home that has no tower yet (the `expand` goal): how many (`guards`, 2), and how many\n\t * fighters past a wave must stand idle for any to go (`spare`, 0). `false` for none\n\t */\n\texpand?: false | { guards?: number; spare?: number }\n\t/**\n\t * Creeping (the `creep` goal): seconds between camps (`every`, 40), seconds into the game before the first\n\t * (`from`, 30), how far from home a camp may be (`reach`, 70), the fewest in a party (`party`, 3). `false` for none\n\t */\n\tcreep?: false | { every?: number; from?: number; reach?: number; party?: number }\n\t/**\n\t * When it gives up (the `melee.surrender` module, `MeleeSurrenderOptions`): once it has no hall, no worker and no\n\t * army that could win the game back, for half a minute, when left out; a condition of the game's own (`when`), and\n\t * how long it holds first (`after`). `false` plays to the last\n\t */\n\tsurrender?: false | MeleeSurrenderOptions\n}\n\n/**\n * What the army module remembers between thinks, as a save keeps it (`BrainMemory.modules['melee.army']`)\n *\n * @beta\n */\nexport interface MeleeArmyMemory {\n\t/** The version of the memory's format: 1 so far */\n\tv: 1\n\t/** Units the next wave of its own asks for */\n\twaveSize: number\n\t/** Seconds into the game the next wave's time comes */\n\tnextAttack: number\n\t/** Seconds into the game it may go creeping again */\n\tnextCreeping: number\n\t/** Waves sent */\n\tattacks: number\n\t/** The tick the wave it last said it falls back with turned at: said once a retreat */\n\tsaidRetreat?: number\n\t/** Seconds into the game the wave began waiting past its time, short of its size or outmatched (`goOdds`): none while it is not */\n\twaiting?: number\n\t/** The tick the last raid was sent at */\n\traided?: number\n\t/** The tick the last harassing party was sent at */\n\tharassed?: number\n}\n\n/**\n * The army module, with the army it runs (`MeleeArmy`): what the tests and the debug tools reach (`meleeArmyOf`)\n *\n * @beta\n */\nexport interface MeleeArmyModule extends AiModule {\n\t/** The army the module runs */\n\tarmy: MeleeArmy\n}\n\n/**\n * What finds the melee army's module with its shape (`ai.module(MELEE_ARMY)`)\n *\n * @beta\n */\nexport const MELEE_ARMY = moduleKey<MeleeArmyModule>('melee.army')\n\n/**\n * The melee brain's army (`MeleeArmy`) of a brain: its waves, numbers and memory, for the tests and the debug tools.\n * Throws for a brain without the `melee.army` module\n *\n * @beta\n */\nexport function meleeArmyOf(ai: Brain): MeleeArmy {\n\tconst module = ai.module(MELEE_ARMY)\n\tif (!module?.army) throw new Error(`The brain \"${ai.def.id}\" has no melee.army module`)\n\treturn module.army\n}\n\n/** How near a base what is at it is: their workers at one of their bases, my fighters at one of mine */\nconst AT_BASE = 30\n/** How near a base their army seen counts as there */\nconst ARMY_NEAR = 36\n/** How near a base a guard stands to guard it */\nconst GUARDING = 16\n/** The fewest raiders or harassers a party is sent with */\nconst PARTY_LEAST = 2\n/** Why a wave that razed what it went for and does not go on walks home (its `retreat`'s `why`) */\nconst RAZED = 'razed'\n\n/**\n * The melee player's army: its waves of its own and the goals beside them (the file's comment), its numbers from its\n * options (`firstAttack`, `attackEvery`, `waveSize`) and the defence's radius, its memory. Made for a brain by\n * the `army()` module; reached as `ai.module(MELEE_ARMY)?.army` (`meleeArmyOf(ai)`)\n *\n * @beta\n */\nexport class MeleeArmy {\n\t/** What the army remembers between thinks: wave size, next times and counts */\n\treadonly memory: MeleeArmyMemory\n\t/** Seconds into the game the first wave is due */\n\treadonly firstAttack: number\n\t/** Seconds between one wave's time and the next */\n\treadonly attackEvery: number\n\t/** How far from a base, in cells, the army defends */\n\treadonly defendRadius: number\n\n\tconstructor(\n\t\t/** The brain it is the army of */\n\t\treadonly ai: Brain,\n\t\t/** How it goes: the module's options, the brain's settings over them (`ai.settings.army`) */\n\t\treadonly options: MeleeArmyOptions\n\t) {\n\t\t// its numbers are its settings' (D1, B2): the difficulty, the personality, the seat's own\n\t\tthis.firstAttack = options.firstAttack ?? 150\n\t\tthis.attackEvery = options.attackEvery ?? 45\n\t\tthis.defendRadius = ai.area(Defence).radius\n\t\tthis.memory = {\n\t\t\tv: 1,\n\t\t\twaveSize: options.waveSize ?? 6,\n\t\t\tnextAttack: this.firstAttack,\n\t\t\tnextCreeping: (options.creep && options.creep.from) || 30,\n\t\t\tattacks: 0\n\t\t}\n\t}\n\n\tprivate get time(): number {\n\t\treturn this.ai.time\n\t}\n\n\t/** Its fighters: what is gathering (a ghoul at the trees) is at work, not in the army */\n\tprivate armyOf(units: UnitSet): UnitSet {\n\t\treturn units.fighters().where((entity) => entity.own?.order !== 'harvest')\n\t}\n\n\t/** The fighters no goal holds and with nothing to do: what a wave or a party is made of. Once a think */\n\tready(): UnitSet {\n\t\treturn this.ai.cache('melee.ready', () => this.readyOf(this.ai.goals.pool()))\n\t}\n\n\tprivate readyOf(units: UnitSet): UnitSet {\n\t\treturn this.armyOf(units).where((unit) => !unit.own?.order)\n\t}\n\n\t/** Their army as last seen within so many seconds, summed by type: a force to weigh odds against */\n\tprivate theirs(seconds: number): Record<string, number> {\n\t\treturn this.ai.cache(`melee.theirs.${seconds}`, () => {\n\t\t\tconst theirs: Record<string, number> = {}\n\t\t\tfor (const army of this.ai.knowledge.enemy.armySeen(seconds))\n\t\t\t\tfor (const [type, count] of Object.entries(army.types)) theirs[type] = (theirs[type] ?? 0) + count\n\t\t\treturn theirs\n\t\t})\n\t}\n\n\t/** The odds of a force of mine against their army as last seen within so many seconds: 1 where none was seen */\n\tprivate oddsAgainstTheirs(mine: UnitSet, seconds: number): number {\n\t\tif (!mine.length) return 0\n\t\tconst theirs = this.theirs(seconds)\n\t\tif (!Object.keys(theirs).length) return 1\n\t\treturn this.ai.view.strength.odds(mine, theirs)\n\t}\n\n\t/** The odds of a force of mine against what is remembered to reach a place (towers, their army seen near it), by the square law */\n\tprivate oddsAt(mine: Iterable<EntityState>, at: Vec2): number {\n\t\tconst { view } = this.ai\n\t\tconst strength = view.strength.sum([...mine])\n\t\tif (strength <= 0) return 0\n\t\tconst theirs = view.threat.at(at, { remembered: true }).enemy\n\t\tif (theirs <= 0) return 1\n\t\treturn (strength * strength) / (strength * strength + theirs * theirs)\n\t}\n\n\t/** Whether its team asks it to join an attack together it has not answered, while its waves wait for the team's (`together`) */\n\tprivate invited(): boolean {\n\t\tconst team = this.ai.area(Team)\n\t\tconst plan = team.together ? team.plan : undefined\n\t\treturn !!plan && plan.by !== this.ai.playerId && this.ai.tick < plan.at && !plan.declined.includes(this.ai.playerId)\n\t}\n\n\t/**\n\t * Whether it has no mercy (No Mercy, a flag of its profile): the enemy's army as last seen (the last minute) weak\n\t * against what it has ready, at the odds the flag says (0.75 for `true`), and it goes before its time\n\t */\n\tprivate merciless(): boolean {\n\t\tconst flag = flagOf(this.ai, 'noMercy')\n\t\tif (!flag) return false\n\t\tconst odds = typeof flag === 'number' ? flag : 0.75\n\t\tconst ready = this.ready()\n\t\tif (!ready.length) return false\n\t\treturn this.oddsAgainstTheirs(ready, 60) >= odds\n\t}\n\n\t/**\n\t * Whether the wave is worth sending now: what is ready would not lose outright against their army as last seen\n\t * (`goOdds`), or it has waited long enough (`waitAtMost`). Nothing seen of their army: worth it\n\t */\n\tprivate worthGoing(): boolean {\n\t\tconst goOdds = this.options.goOdds ?? 0.4\n\t\tif (goOdds === false) return true\n\t\tif (this.oddsAgainstTheirs(this.ready(), 60) >= goOdds) return true\n\t\treturn this.waitedEnough()\n\t}\n\n\t/**\n\t * Whether a wave of theirs just died at its gate (so many of their fighters fallen near its bases in the last twenty\n\t * seconds): their base is empty of it, and what is ready goes at once\n\t */\n\tprivate counterAttack(): boolean {\n\t\tif (this.options.counter === false) return false\n\t\treturn this.ai.cache('melee.counter', () => {\n\t\t\tconst { view, knowledge, registry } = this.ai\n\t\t\tconst bases = view.bases()\n\t\t\tlet fallen = 0\n\t\t\tfor (const death of knowledge.events.deaths(20)) {\n\t\t\t\tif (view.player(death.owner)?.relation !== 'enemy' || !registry.units.has(death.type)) continue\n\t\t\t\tconst def = registry.unit(death.type)\n\t\t\t\tif (def.kind !== 'unit' || !def.attacks?.length || def.harvester) continue\n\t\t\t\tif (bases.some((base) => distSq(base.at, death.at) < AT_BASE * AT_BASE)) fallen++\n\t\t\t}\n\t\t\treturn fallen >= (this.options.counterAfter ?? 3)\n\t\t})\n\t}\n\n\t/**\n\t * Whether their army is away from what a wave would go for (`strike`): at least one sighting of it within `awayFor`\n\t * seconds (nothing seen says nothing of where it is), every one far from the target and from every base of mine and\n\t * every building of my allies' (an army at my gate is the defence's, at an ally's the team's: not a reason to trade\n\t * bases), and what is ready (half a wave at the least) would hold against what is remembered to reach the target\n\t * (its towers). Once a think\n\t */\n\tprivate armyAway(): boolean {\n\t\tconst strike = this.options.strike\n\t\tif (strike === false) return false\n\t\treturn this.ai.cache('melee.strike', () => {\n\t\t\tconst { view, knowledge } = this.ai\n\t\t\tif (this.ai.area(Waves).active || this.out('wave')) return false\n\t\t\tconst ready = this.ready()\n\t\t\tif (ready.length < Math.max(PARTY_LEAST, Math.ceil(this.memory.waveSize / 2))) return false\n\t\t\tconst sightings = knowledge.enemy.armySeen(strike?.awayFor ?? 60).filter((army) => view.player(army.owner)?.relation === 'enemy')\n\t\t\tif (!sightings.length) return false\n\t\t\tconst target = this.targetFor(ready.centre())\n\t\t\tif (!target) return false\n\t\t\tconst far = ARMY_NEAR * 2\n\t\t\tif (sightings.some((army) => distSq(army.at, target) < far * far)) return false\n\t\t\t// an army at my gate is the defence's, at an ally's the team's: not a reason to trade bases\n\t\t\tconst home = this.defendRadius + ARMY_NEAR\n\t\t\tconst ours = [...view.bases().map((base) => base.at), ...view.allies.buildings()]\n\t\t\tif (sightings.some((army) => ours.some((at) => distSq(army.at, at) < home * home))) return false\n\t\t\treturn this.oddsAt(ready, target) >= (strike?.odds ?? 0.6)\n\t\t})\n\t}\n\n\t/** Whether the wave has waited past its time as long as it will (`waitAtMost`): it goes with what it has then */\n\tprivate waitedEnough(): boolean {\n\t\tconst { waiting } = this.memory\n\t\treturn waiting !== undefined && this.time - waiting >= (this.options.waitAtMost ?? this.attackEvery * 2)\n\t}\n\n\t/**\n\t * Whether the wave is ready: as many as it asks for stand idle; or half of them, once it has waited long enough and\n\t * they would hold against what is remembered to reach the target (half a wave is not fed to the towers)\n\t */\n\tprivate waveReady(): boolean {\n\t\tconst ready = this.ready()\n\t\tconst { waveSize } = this.memory\n\t\tif (ready.length >= waveSize) return true\n\t\tif (!(this.waitedEnough() || this.counterAttack() || this.armyAway()) || ready.length < Math.max(PARTY_LEAST, Math.ceil(waveSize / 2)))\n\t\t\treturn false\n\t\tconst goOdds = this.options.goOdds ?? 0.4\n\t\tif (goOdds === false) return true\n\t\tconst target = this.targetFor(ready.centre())\n\t\treturn !!target && this.oddsAt(ready, target) >= goOdds\n\t}\n\n\t/**\n\t * Where a wave goes: of the rival's buildings it knows of (in sight or remembered, not a creep's), the nearest, or\n\t * (`target: 'weakest'`) the one the least of their strength is remembered to reach (an expansion before a main with\n\t * towers), the nearest among those alike; else a base it was told of\n\t */\n\tprivate targetFor(from: Vec2 | undefined): Vec2 | undefined {\n\t\tconst { view } = this.ai\n\t\tconst known = view.enemies.known().buildings()\n\t\tconst bases = this.ai.options.enemyBases ?? []\n\t\tif (!known.length || !from) return bases.length ? bases[this.memory.attacks % bases.length] : undefined\n\t\tif ((this.options.target ?? 'weakest') === 'nearest') {\n\t\t\tconst near = known.nearest(from)!\n\t\t\treturn { x: near.x, z: near.z }\n\t\t}\n\t\tlet best: { at: Vec2; threat: number; distance: number } | undefined\n\t\tfor (const building of known) {\n\t\t\tconst threat = view.threat.at(building, { remembered: true }).enemy\n\t\t\tconst distance = distSq(from, building)\n\t\t\t// alike within a tenth: the nearer; else the least threatened\n\t\t\tconst alike = best && Math.abs(threat - best.threat) <= Math.max(threat, best.threat) * 0.1\n\t\t\tif (!best || (alike ? distance < best.distance : threat < best.threat)) best = { at: { x: building.x, z: building.z }, threat, distance }\n\t\t}\n\t\treturn best!.at\n\t}\n\n\t/**\n\t * A way of its own for a wave (Random Paths, a flag of its profile): by the brain's numbers, straight, or by a place a\n\t * third of the way's length to one side or the other of its middle. None for straight, or without the flag\n\t */\n\tprivate wayOf(squad: Squad, target: Vec2): Vec2 | undefined {\n\t\tif (!flagOf(this.ai, 'randomPaths')) return undefined\n\t\tconst from = squad.centre()\n\t\tif (!from) return undefined\n\t\tconst side = this.ai.rng.int(-1, 1)\n\t\tif (side === 0) return undefined\n\t\tconst dx = target.x - from.x\n\t\tconst dz = target.z - from.z\n\t\tconst { width, depth } = this.ai.session.terrain\n\t\tconst x = (from.x + target.x) / 2 - (dz / 3) * side\n\t\tconst z = (from.z + target.z) / 2 + (dx / 3) * side\n\t\treturn { x: Math.min(width - 2, Math.max(2, x)), z: Math.min(depth - 2, Math.max(2, z)) }\n\t}\n\n\t/**\n\t * How the squads it sends out behave: they fall back from a fight away from home at the odds a wave used to (the\n\t * profile's `retreatOdds`, or Groups Flee), fight on to the last near home, and a wave is made up from home\n\t * (`reinforce`); the seat's say goes over it\n\t */\n\tprivate get outward(): SquadOptions {\n\t\treturn {\n\t\t\tretreatAt: 0.3,\n\t\t\thome: this.defendRadius + 6,\n\t\t\treinforce: this.options.reinforce ?? true,\n\t\t\t...this.ai.squads.defaults\n\t\t}\n\t}\n\n\t/** A party's options: as a wave's, but it falls back sooner and nobody comes after it */\n\tprivate party(retreatAt: number): SquadOptions {\n\t\treturn { ...this.outward, retreatAt, reinforce: false }\n\t}\n\n\t/** Sends a wave: its squad to attack the target, the next wave set, said where it says things */\n\tprivate launch(squad: Squad, target: Vec2, together: boolean): void {\n\t\tconst { ai, memory } = this\n\t\tconst known = ai.view.enemies.known().buildings()\n\t\tconst size = squad.length\n\t\tconst early = this.time < memory.nextAttack\n\t\tconst counter = early && this.counterAttack()\n\t\tconst struck = early && !counter && this.armyAway()\n\t\tconst via = this.wayOf(squad, target)\n\t\tsquad.attack(target, via ? { via } : {})\n\t\tai.knowledge.own.attackSent(target, size)\n\t\tmemory.attacks++\n\t\tmemory.waveSize = Math.min(memory.waveSize + (this.options.waveGrowth ?? 2), this.options.waveMax ?? 24)\n\t\tmemory.waiting = undefined\n\t\t// a slip (its profile's `mistakes`): the next wave sooner than it should, by up to its share of the wait\n\t\tconst mistakes = ai.profile.mistakes ?? 0\n\t\tmemory.nextAttack = this.time + this.attackEvery * (mistakes > 0 ? 1 - mistakes * ai.rng.next() : 1)\n\t\tai.area(Team).say('attacking')\n\t\tai.decide(\n\t\t\t`sends wave ${memory.attacks} of ${size} at ${where(target)}${together ? ', together with its team' : known.length ? ', a building of theirs it knows' : ', a base it was told of'}${counter ? ', answering their wave that fell at its gate' : struck ? ', their army away' : ''}; the next is ${memory.waveSize} strong at ${Math.round(memory.nextAttack)} s`,\n\t\t\t{ kind: 'army', goal: 'attack' }\n\t\t)\n\t}\n\n\t/**\n\t * The squad a goal of its sent out (`wave`, `creep`, `raid`, `harass`, `expand`), while it is on its errand: on its\n\t * way, fighting, falling back, or (a wave) done with its target, to go on or to be sent home. None once its task is\n\t * over, or before it was sent\n\t */\n\tprivate out(name: string): Squad | undefined {\n\t\tconst squad = this.ai.squads.named(name)\n\t\tif (!squad) return undefined\n\t\tif (!squad.idle) return squad\n\t\treturn name === 'wave' && squad.done === 'cleared' ? squad : undefined\n\t}\n\n\t/**\n\t * Whether a wave that razed what it went for goes on: it may, it is still a few, it is strong enough against their\n\t * army as last seen and against what is remembered to reach the next target (its towers), and it knows of more of theirs\n\t */\n\tprivate mayPressOn(squad: Squad): boolean {\n\t\tif (!(this.options.pressOn ?? true) || squad.length < PARTY_LEAST) return false\n\t\tconst odds = this.options.pressOdds ?? 0.5\n\t\tif (this.oddsAgainstTheirs(squad.units(), 60) < odds) return false\n\t\tif (!this.ai.view.enemies.known().buildings().length) return false\n\t\tconst target = this.targetFor(squad.centre())\n\t\treturn !!target && this.oddsAt(squad.units(), target) >= odds\n\t}\n\n\t/** The camp its ready units and hero can take near home, when it is time to go creeping */\n\tprivate campToTake(ready: Iterable<EntityState>) {\n\t\tconst creep = this.options.creep\n\t\tif (creep === false) return undefined\n\t\tif (this.time < this.memory.nextCreeping || this.memory.nextAttack - this.time < 40) return undefined\n\t\tconst party = [...ready]\n\t\tconst hero = party.find((unit) => heroOfState(unit))\n\t\tconst home = this.ai.view.home()\n\t\tif (!hero || !home || party.length < (creep?.party ?? 3)) return undefined\n\t\t// what the group can take on grows with its size and with the hero\n\t\tconst strength = party.length * 1.2 + (heroOfState(hero)?.level ?? 1)\n\t\tconst reach = creep?.reach ?? 70\n\t\tconst camps = this.ai.view.camps().filter((camp) => !camp.cleared && camp.level <= strength && distSq(camp, home) < reach * reach)\n\t\tlet best: (typeof camps)[number] | undefined\n\t\tlet bestDistance = Infinity\n\t\tfor (const camp of camps) {\n\t\t\tconst d = distSq(home, camp)\n\t\t\tif (d < bestDistance) {\n\t\t\t\tbestDistance = d\n\t\t\t\tbest = camp\n\t\t\t}\n\t\t}\n\t\treturn best\n\t}\n\n\t// ---- the raid\n\n\t/** Where a raid would go: the base of theirs with the most workers seen lately and no army seen near it, with how many */\n\tprivate raidTarget(): { at: Vec2; workers: number } | undefined {\n\t\treturn this.ai.cache('melee.raid', () => {\n\t\t\tconst raid = this.options.raid\n\t\t\t// with waves given (D2), the fighters are the waves': no party of its own is sent\n\t\t\tif (raid === false || this.ai.area(Waves).active) return undefined\n\t\t\tconst { enemy } = this.ai.knowledge\n\t\t\tconst workers = enemy.workersSeen(raid?.workersSeenFor ?? 120).filter((worker) => worker.died === undefined)\n\t\t\tif (!workers.length) return undefined\n\t\t\tconst armies = enemy.armySeen(raid?.armyAwayFor ?? 45)\n\t\t\tconst home = this.ai.view.home()\n\t\t\tlet best: { at: Vec2; workers: number; distance: number } | undefined\n\t\t\tfor (const base of enemy.bases()) {\n\t\t\t\tif (base.gone || armies.some((army) => distSq(army.at, base.at) < ARMY_NEAR * ARMY_NEAR)) continue\n\t\t\t\tconst count = workers.filter((worker) => distSq(worker.at, base.at) < AT_BASE * AT_BASE).length\n\t\t\t\tif (!count) continue\n\t\t\t\tconst distance = home ? distSq(home, base.at) : 0\n\t\t\t\tif (!best || count > best.workers || (count === best.workers && distance < best.distance))\n\t\t\t\t\tbest = { at: { x: base.at.x, z: base.at.z }, workers: count, distance }\n\t\t\t}\n\t\t\treturn best && { at: best.at, workers: best.workers }\n\t\t})\n\t}\n\n\t/** The fastest fighters of some, no heroes among them, up to so many: a party; none where fewer than two */\n\tprivate fastest(units: UnitSet, count: number): EntityState[] {\n\t\tconst { registry, view } = this.ai\n\t\tconst speed = (unit: EntityState) => baseStats(view.def(unit), registry).moveSpeed\n\t\tconst chosen = units\n\t\t\t.filter((unit) => !heroOfState(unit))\n\t\t\t.sort((a, b) => speed(b) - speed(a) || a.id - b.id)\n\t\t\t.slice(0, count)\n\t\treturn chosen.length >= Math.min(count, PARTY_LEAST) ? chosen : []\n\t}\n\n\t/** The raiders of what may go: the fastest few, where a raid is on and they would not die at the base */\n\tprivate raiders(available: UnitSet): EntityState[] {\n\t\tconst raid = this.options.raid\n\t\tif (raid === false) return []\n\t\tconst target = this.raidTarget()\n\t\tif (!target) return []\n\t\tconst chosen = this.fastest(this.readyOf(available), raid?.size ?? 3)\n\t\treturn chosen.length && this.oddsAt(chosen, target.at) >= (raid?.odds ?? 0.6) ? chosen : []\n\t}\n\n\t// ---- harassing\n\n\t/** Their main as known: the first base of theirs with a hall, nearest home */\n\tprivate theirMain(): EnemyBase | undefined {\n\t\treturn this.ai.cache('melee.theirMain', () => {\n\t\t\tif (this.ai.area(Waves).active) return undefined\n\t\t\tconst home = this.ai.view.home()\n\t\t\tconst mains = this.ai.knowledge.enemy.bases().filter((base) => base.hall && !base.gone && !base.expansion)\n\t\t\tlet best: EnemyBase | undefined\n\t\t\tlet bestDistance = Infinity\n\t\t\tfor (const base of mains) {\n\t\t\t\tconst d = home ? distSq(home, base.at) : 0\n\t\t\t\tif (d < bestDistance) {\n\t\t\t\t\tbestDistance = d\n\t\t\t\t\tbest = base\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best\n\t\t})\n\t}\n\n\t/** The party that harasses: the hero and the fastest few, where their army was not seen at their main lately and the party would hold */\n\tprivate harassers(available: UnitSet): EntityState[] {\n\t\tconst harass = this.options.harass\n\t\tif (harass === false) return []\n\t\tconst main = this.theirMain()\n\t\tif (!main) return []\n\t\tif (this.ai.knowledge.enemy.armySeen(60).some((army) => distSq(army.at, main.at) < ARMY_NEAR * ARMY_NEAR)) return []\n\t\tconst ready = this.readyOf(available)\n\t\tconst heroes = ready.filter((unit) => !!heroOfState(unit))\n\t\tconst size = harass?.size ?? 3\n\t\tconst chosen = [...heroes.slice(0, 1), ...this.fastest(ready, Math.max(0, size - Math.min(1, heroes.length)))]\n\t\tif (!chosen.length || (!heroes.length && chosen.length < Math.min(size, PARTY_LEAST))) return []\n\t\treturn this.oddsAt(chosen, main.at) >= (harass?.odds ?? 0.6) ? chosen : []\n\t}\n\n\t// ---- the expansion's guards\n\n\t/** Whether a base of mine still wants guards: past home, with no finished tower among its buildings */\n\tprivate wantsGuards(base: Base): boolean {\n\t\treturn !base.buildings.withRole('tower').finished().length\n\t}\n\n\t/** The bases past home that want guards and have none: no fighters of mine standing by them. Once a think */\n\tprivate unguarded(): Base[] {\n\t\treturn this.ai.cache('melee.unguarded', () => {\n\t\t\tif (this.ai.area(Waves).active) return []\n\t\t\tconst { view } = this.ai\n\t\t\tconst fighters = this.armyOf(view.mine)\n\t\t\treturn view\n\t\t\t\t.bases()\n\t\t\t\t.slice(1)\n\t\t\t\t.filter((base) => this.wantsGuards(base) && !fighters.near(base.at, GUARDING).length)\n\t\t})\n\t}\n\n\t/** The base the expand squad guards, where it still wants guards */\n\tprivate guarded(): Base | undefined {\n\t\tconst squad = this.ai.squads.named('expand')\n\t\tconst at = squad?.current?.kind === 'defend' ? (squad.current.data.at as Vec2 | undefined) : undefined\n\t\tif (!at) return undefined\n\t\tconst base = this.ai.view.bases().find((each) => distSq(each.at, at) < GUARDING * GUARDING)\n\t\treturn base && this.wantsGuards(base) ? base : undefined\n\t}\n\n\t/** The guards for the first base wanting them: the fighters nearest it, so many, from what stands idle past a wave */\n\tprivate guards(available: UnitSet): EntityState[] {\n\t\tconst expand = this.options.expand\n\t\tif (expand === false) return []\n\t\tconst base = this.unguarded()[0]\n\t\tif (!base) return []\n\t\tconst ready = this.readyOf(available)\n\t\tconst guards = expand?.guards ?? 2\n\t\tif (ready.length < guards + this.memory.waveSize + (expand?.spare ?? 0)) return []\n\t\treturn ready.items\n\t\t\t.slice()\n\t\t\t.sort((a, b) => distSq(a, base.at) - distSq(b, base.at) || a.id - b.id)\n\t\t\t.slice(0, guards)\n\t}\n\n\t// ---- the goals\n\n\t/** The goals, for the picker: attack, creep, raid, harass, expand (each unless left out) */\n\tgoals(): GoalDef[] {\n\t\tconst { options } = this\n\t\tconst goals: GoalDef[] = [this.attackGoal()]\n\t\tif (options.creep !== false) goals.push(this.creepGoal())\n\t\tif (options.raid !== false) goals.push(this.raidGoal())\n\t\tif (options.harass !== false) goals.push(this.harassGoal())\n\t\tif (options.expand !== false) goals.push(this.expandGoal())\n\t\treturn goals\n\t}\n\n\tprivate attackGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'attack',\n\t\t\tweight: 0.8,\n\t\t\tconsiderations: [\n\t\t\t\t// seconds past the time set for the next wave; and once the wave is out, as long as it is. Asked to join an\n\t\t\t\t// attack together by its team, or merciless, its time has come too\n\t\t\t\tconsider(\n\t\t\t\t\t'its time has come',\n\t\t\t\t\t// with waves given (D2), the waves module sends them: this goal stands aside\n\t\t\t\t\t() =>\n\t\t\t\t\t\tthis.ai.area(Waves).active\n\t\t\t\t\t\t\t? -1\n\t\t\t\t\t\t\t: this.out('wave')\n\t\t\t\t\t\t\t\t? 1\n\t\t\t\t\t\t\t\t: this.invited() || this.merciless() || this.counterAttack() || this.armyAway()\n\t\t\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t\t\t: this.time - this.memory.nextAttack,\n\t\t\t\t\tcurve.step(0)\n\t\t\t\t),\n\t\t\t\t// as many as it asks for; or half of them, once it has waited long enough (the supply may cap the army)\n\t\t\t\tconsider('the wave is ready', () => (this.out('wave') || this.waveReady() ? 1 : this.ready().length / this.memory.waveSize), curve.step(1)),\n\t\t\t\t// outmatched by their army as last seen, it waits and trains on, for a while\n\t\t\t\tconsider('worth going', () => (this.out('wave') ? 1 : this.worthGoing() ? 1 : 0), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.readyOf(available) },\n\t\t\trun: (_ai, claimed) => this.attack(claimed)\n\t\t})\n\t}\n\n\t/** The attack goal's turn: the wave out watched (its fall back, its wait for the team, its next target), or sent */\n\tprivate attack(claimed: Claimed): void {\n\t\tconst { ai, memory } = this\n\t\tconst team = ai.area(Team)\n\t\tconst out = ai.squads.named('wave')\n\t\tif (!claimed.first && out) {\n\t\t\t// a wave that falls back from a lost fight puts the next one off, as from when it turned; one walking home from\n\t\t\t// what it razed does not\n\t\t\tif (out.current?.kind === 'retreat' && out.current.data.why === RAZED) return\n\t\t\tif (out.current?.kind === 'retreat') {\n\t\t\t\tmemory.nextAttack = Math.max(memory.nextAttack, out.current.since / ai.session.tickRate + this.attackEvery)\n\t\t\t\tif (memory.saidRetreat !== out.current.since) {\n\t\t\t\t\tmemory.saidRetreat = out.current.since\n\t\t\t\t\tteam.say('retreating')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// a wave waiting for the team's attack together goes at its time, or on its own once the plan is gone\n\t\t\tif (out.current?.kind === 'defend' && out.current.data.waiting) {\n\t\t\t\tconst plan = team.plan\n\t\t\t\tif (plan && plan.joined.includes(ai.playerId) && ai.tick < plan.at) return\n\t\t\t\tconst target = plan?.target ?? this.targetFor(out.centre())\n\t\t\t\tif (target) this.launch(out, target, !!plan)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// a wave that razed what it went for goes on to the next of theirs it knows, while it is strong enough; else it\n\t\t\t// walks home, rather than stand idle where it razed it\n\t\t\tif (out.idle && out.done === 'cleared') {\n\t\t\t\tconst target = this.mayPressOn(out) && this.targetFor(out.centre())\n\t\t\t\tif (target) {\n\t\t\t\t\tout.attack(target)\n\t\t\t\t\tai.knowledge.own.attackSent(target, out.length)\n\t\t\t\t\tai.decide(`wave ${memory.attacks} of ${out.length} goes on to ${where(target)}: what it went for is razed`, {\n\t\t\t\t\t\tkind: 'army',\n\t\t\t\t\t\tgoal: 'attack'\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tout.retreat(undefined, RAZED)\n\t\t\t\t\tai.decide(`wave ${memory.attacks} of ${out.length} goes home: what it went for is razed`, { kind: 'army', goal: 'attack' })\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tif (!claimed.first) return\n\t\tconst wave = claimed.units\n\t\tconst target = this.targetFor(wave.centre())\n\t\tif (!target) return\n\t\tconst squad = claimed.squad('wave', wave, this.outward)\n\t\tif (team.together) {\n\t\t\t// the team's plan: proposed where there is none, joined where there is; the wave holds home till its time\n\t\t\tconst plan = team.plan && ai.tick < team.plan.at ? team.plan : undefined\n\t\t\tif (plan) team.join()\n\t\t\telse team.propose(target)\n\t\t\tsquad.defend(wave.centre() ?? target, 12)\n\t\t\tsquad.current!.data.waiting = true\n\t\t\tconst at = (team.plan?.at ?? ai.tick) / ai.session.tickRate\n\t\t\tai.decide(`wave ${memory.attacks + 1} of ${wave.length} waits to attack together at ${Math.round(at)} s`, { kind: 'army', goal: 'attack' })\n\t\t\treturn\n\t\t}\n\t\tthis.launch(squad, target, false)\n\t}\n\n\tprivate creepGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'creep',\n\t\t\tweight: 0.5,\n\t\t\tconsiderations: [consider('a camp to take', () => (this.out('creep') ? 1 : this.campToTake(this.ready()) ? 1 : 0), curve.step(1))],\n\t\t\tclaims: { units: (_ai, available) => this.readyOf(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst camp = this.campToTake(claimed.units)\n\t\t\t\tif (!camp) return\n\t\t\t\tthis.memory.nextCreeping = this.time + ((this.options.creep && this.options.creep.every) || 40)\n\t\t\t\tclaimed.squad('creep', claimed.units, this.outward).creep(camp)\n\t\t\t\tai.decide(`goes creeping at ${where(camp)} with ${claimed.units.length}`, { kind: 'army', goal: 'creep' })\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate raidGoal(): GoalDef {\n\t\tconst raid = this.options.raid || {}\n\t\tconst every = raid.every ?? 60\n\t\treturn defineGoal({\n\t\t\tid: 'raid',\n\t\t\tweight: 0.6,\n\t\t\tcommitment: 20,\n\t\t\tcooldown: every,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('their workers seen where their army is not', () => (this.out('raid') ? 1 : (this.raidTarget()?.workers ?? 0)), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'seconds since the last raid',\n\t\t\t\t\t() => (this.out('raid') || this.memory.raided === undefined ? every : (this.ai.tick - this.memory.raided) / this.ai.session.tickRate),\n\t\t\t\t\tcurve.step(every)\n\t\t\t\t),\n\t\t\t\tconsider('raiders to spare', () => (this.out('raid') ? 1 : this.raiders(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.raiders(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst target = this.raidTarget()\n\t\t\t\tif (!target) return\n\t\t\t\tthis.memory.raided = ai.tick\n\t\t\t\tclaimed.squad('raid', claimed.units, this.party(raid.retreatAt ?? 0.5)).harass(target.at)\n\t\t\t\tai.decide(`raids their workers at ${where(target.at)} with ${claimed.units.length}: ${target.workers} seen there, their army elsewhere`, {\n\t\t\t\t\tkind: 'army',\n\t\t\t\t\tgoal: 'raid'\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate harassGoal(): GoalDef {\n\t\tconst harass = this.options.harass || {}\n\t\tconst every = harass.every ?? 90\n\t\treturn defineGoal({\n\t\t\tid: 'harass',\n\t\t\tweight: 0.5,\n\t\t\tcommitment: 30,\n\t\t\tcooldown: every,\n\t\t\tconsiderations: [\n\t\t\t\tconsider(\n\t\t\t\t\t'before the first wave',\n\t\t\t\t\t() => (this.out('harass') ? 1 : this.memory.attacks === 0 && this.time < this.memory.nextAttack ? 1 : 0),\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t),\n\t\t\t\tconsider('their main known', () => (this.out('harass') ? 1 : this.theirMain() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'seconds since the last',\n\t\t\t\t\t() => (this.out('harass') || this.memory.harassed === undefined ? every : (this.ai.tick - this.memory.harassed) / this.ai.session.tickRate),\n\t\t\t\t\tcurve.step(every)\n\t\t\t\t),\n\t\t\t\tconsider('a party to send', () => (this.out('harass') ? 1 : this.harassers(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.harassers(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst main = this.theirMain()\n\t\t\t\tif (!main) return\n\t\t\t\tthis.memory.harassed = ai.tick\n\t\t\t\tclaimed.squad('harass', claimed.units, this.party(harass.retreatAt ?? 0.5)).harass(main.at)\n\t\t\t\tai.decide(`harasses their main at ${where(main.at)} with ${claimed.units.length} before its first wave`, { kind: 'army', goal: 'harass' })\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate expandGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: 'expand',\n\t\t\tweight: 0.7,\n\t\t\tcommitment: 30,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('a new base to hold', () => (this.guarded() ? 1 : this.unguarded().length), curve.step(1)),\n\t\t\t\tconsider('guards to spare', () => (this.guarded() ? 1 : this.guards(this.ai.goals.pool()).length), curve.step(1))\n\t\t\t],\n\t\t\tclaims: { units: (_ai, available) => this.guards(available) },\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tif (!claimed.first) return\n\t\t\t\tconst base = this.unguarded()[0]\n\t\t\t\tif (!base) return\n\t\t\t\tclaimed.squad('expand', claimed.units, { ...this.outward, reinforce: false }).defend(base.at, GUARDING)\n\t\t\t\tai.decide(`leaves ${claimed.units.length} to guard its base at ${where(base.at)}: no tower there yet`, { kind: 'army', goal: 'expand' })\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---- the think, the memory, the report\n\n\t/** Once a think, before the picker: whether the wave began waiting past its time, short of its size or outmatched */\n\tthink(): void {\n\t\tconst { memory } = this\n\t\tif (this.ai.area(Waves).active || this.out('wave')) return\n\t\tif (this.time < memory.nextAttack) {\n\t\t\tmemory.waiting = undefined\n\t\t\treturn\n\t\t}\n\t\tif (memory.waiting !== undefined) return\n\t\tconst ready = this.ready().length\n\t\tconst short = ready < memory.waveSize\n\t\tif (!short && this.worthGoing()) return\n\t\tmemory.waiting = this.time\n\t\tthis.ai.decide(\n\t\t\t`wave ${memory.attacks + 1} waits: ${short ? `${ready} of ${memory.waveSize} ready` : `outmatched by their army as last seen (odds ${this.oddsAgainstTheirs(this.ready(), 60).toFixed(2)})`}`,\n\t\t\t{ kind: 'army', goal: 'attack' }\n\t\t)\n\t}\n\n\t/** What it remembers, for a save: a copy */\n\tsave(): MeleeArmyMemory {\n\t\treturn { ...this.memory }\n\t}\n\n\t/** Takes back what `save` gave */\n\trestore(data: unknown): void {\n\t\tconst given = (data ?? {}) as Partial<MeleeArmyMemory>\n\t\tconst { memory } = this\n\t\t// into the same object: what reads the memory (the goals) holds on to it\n\t\tmemory.waveSize = given.waveSize ?? memory.waveSize\n\t\tmemory.nextAttack = given.nextAttack ?? memory.nextAttack\n\t\tmemory.nextCreeping = given.nextCreeping ?? memory.nextCreeping\n\t\tmemory.attacks = given.attacks ?? memory.attacks\n\t\tfor (const key of ['saidRetreat', 'waiting', 'raided', 'harassed'] as const) {\n\t\t\tif (given[key] !== undefined) memory[key] = given[key]\n\t\t\telse delete memory[key]\n\t\t}\n\t}\n\n\t/** What it is thinking, for the debug tools: how hard it plays, its next wave, its roles */\n\tinspect(): Record<string, unknown> {\n\t\tconst { ai, memory } = this\n\t\tconst { view } = ai\n\t\tconst first = (role: string) => view.typesOf(role)[0]?.id\n\t\treturn {\n\t\t\tdifficulty: ai.profile.difficulty ?? 'normal',\n\t\t\tpersonality: ai.profile.personality ?? 'balanced',\n\t\t\tnextAttack: Math.max(0, Math.round(memory.nextAttack - this.time)),\n\t\t\twaveSize: memory.waveSize,\n\t\t\tattacks: memory.attacks,\n\t\t\t...(memory.waiting !== undefined && { waiting: Math.round(this.time - memory.waiting) }),\n\t\t\troles: {\n\t\t\t\tworker: first('worker'),\n\t\t\t\thall: first('hall'),\n\t\t\t\tfarm: [...view.typesOf('supply')].sort((a, b) => (a.cost?.[ai.purse.money] ?? 0) - (b.cost?.[ai.purse.money] ?? 0))[0]?.id,\n\t\t\t\tbarracks: view.typesOf('barracks').map((def) => def.id),\n\t\t\t\taltars: view.typesOf('altar').map((def) => def.id)\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * The melee brain's army module: the goals of the army put on the picker (attack, creep, raid, harass, expand), the\n * wave's wait counted. Before the picker (`goals`), after the building and the production, as the old turn had it. With how the army goes where the seat says nothing (`MeleeArmyOptions`)\n *\n * @beta\n */\nexport const army = (options: MeleeArmyOptions = {}): AiModuleDef =>\n\tdefineModule({ id: 'melee.army', make: (ai: Brain): MeleeArmyModule => {\n\t\tconst army = new MeleeArmy(ai, { ...options, ...ai.settings.army })\n\t\tai.goals.add(...army.goals())\n\t\treturn {\n\t\t\tid: 'melee.army',\n\t\t\tversion: 1,\n\t\t\tphase: 'decide',\n\t\t\tarmy,\n\t\t\tthink: () => army.think(),\n\t\t\tsave: () => army.save(),\n\t\t\trestore: (data) => army.restore(data),\n\t\t\tinspect: () => army.inspect()\n\t\t}\n\t} })\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { availableToPlayer } from "../../shared.js";
|
|
2
|
+
import { queueOf } from "../../systems/productionQueue.js";
|
|
3
|
+
import { defineModule } from "../module.js";
|
|
4
|
+
import { an } from "../geometry.js";
|
|
5
|
+
import { Economy } from "../economy.js";
|
|
6
|
+
import { Micro } from "../micro.js";
|
|
7
|
+
//#region src/ai/melee/heroes.ts
|
|
8
|
+
/** The reservation's name in the purse */
|
|
9
|
+
var HERO = "melee.hero";
|
|
10
|
+
/**
|
|
11
|
+
* The melee brain's heroes module: a fallen hero revived, the next trained while it wants more, their price held in the
|
|
12
|
+
* purse meanwhile. After the economy, before the building, as the old turn had it; `steps.heroes` and
|
|
13
|
+
* `steps.buildOrder` honoured
|
|
14
|
+
*
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
var heroes = (options = {}) => defineModule({
|
|
18
|
+
id: "melee.heroes",
|
|
19
|
+
make: (ai) => ({
|
|
20
|
+
id: "melee.heroes",
|
|
21
|
+
phase: "plan",
|
|
22
|
+
after: ["economy"],
|
|
23
|
+
before: ["melee.build", "melee.production"],
|
|
24
|
+
think: () => {
|
|
25
|
+
if (ai.plans.following || ai.area(Economy).waiting) return;
|
|
26
|
+
run(ai, {
|
|
27
|
+
...options,
|
|
28
|
+
...ai.settings.heroes
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
/** The turn: revives, or trains the next */
|
|
34
|
+
function run(ai, options) {
|
|
35
|
+
const { registry, view } = ai;
|
|
36
|
+
const { me } = view;
|
|
37
|
+
const priority = options.priority ?? 35;
|
|
38
|
+
const idle = view.typesOf("altar").flatMap((type) => view.mine.ofType(type.id).finished().items).find((altar) => !queueOf(altar).length);
|
|
39
|
+
if (!idle) return;
|
|
40
|
+
const fallen = me.heroes.find((hero) => !hero.alive && hero.reviving === void 0);
|
|
41
|
+
if (fallen) {
|
|
42
|
+
const price = fallen.reviveCost ?? {};
|
|
43
|
+
if (ai.purse.spend(price)) {
|
|
44
|
+
ai.send({
|
|
45
|
+
type: "revive",
|
|
46
|
+
building: idle.id,
|
|
47
|
+
hero: fallen.id
|
|
48
|
+
});
|
|
49
|
+
ai.decide(`revives its ${fallen.type}`, { kind: "hero" });
|
|
50
|
+
} else ai.purse.reserve(HERO, price, priority);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const most = options.most ?? 2;
|
|
54
|
+
const wanted = ai.time > (options.secondFrom ?? 240) ? most : Math.min(1, most);
|
|
55
|
+
if (me.heroes.length >= wanted) return;
|
|
56
|
+
const candidates = (view.def(idle).trains ?? []).map((id) => registry.unit(id)).filter((def) => def.hero && availableToPlayer(def, {
|
|
57
|
+
race: me.race,
|
|
58
|
+
availability: me.availability
|
|
59
|
+
}, def.id));
|
|
60
|
+
const next = ai.area(Micro).nextHero(candidates, me.heroes.map((hero) => hero.type));
|
|
61
|
+
if (!next) return;
|
|
62
|
+
if (ai.plans.production.train(idle, next)) ai.decide(`trains ${an(next.id)}: hero ${me.heroes.length + 1} of ${wanted}`, { kind: "hero" });
|
|
63
|
+
else if (next.cost) ai.purse.reserve(HERO, next.cost, priority);
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { heroes };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=heroes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heroes.js","names":[],"sources":["../../../src/ai/melee/heroes.ts"],"sourcesContent":["import { availableToPlayer } from '#engine/shared'\nimport { Economy } from '../economy'\nimport { Micro } from '../micro'\nimport { queueOf } from '#engine/systems/productionQueue'\nimport { type Brain } from '#engine/ai/brain'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\nimport { an } from '../geometry'\n\n/*\n * The melee player's heroes (AI plan, D3; the part of its turn that was `runHeroes`): a fallen hero revived at an idle\n * altar, and the next hero trained while it wants more (one until the game is under way, then as many as its profile\n * says), which one the micro says (`ai.micro.nextHero`: the plan's order, a chance of none). What a hero costs is\n * held in the purse while it is short (`priority`), so that the soldiers wait for it and the hall and the barracks do\n * not. Nothing while the game's build order is followed, nor while the economy waits for what the money is gathered\n * at. What each hero learns is the micro's\n */\n\n/**\n * How the melee brain makes its heroes (`heroes()` of the melee brain): how many once the game is under way (the\n * profile's `heroes`), from when, and how important their price is to the purse\n *\n * @beta\n */\nexport interface MeleeHeroesOptions {\n\t/** Heroes it has once the game is under way (`secondFrom`): one before. 2 when left out */\n\tmost?: number\n\t/** Seconds into the game from which it wants every hero it may have: one before. 240 when left out */\n\tsecondFrom?: number\n\t/**\n\t * How important a hero's price is to the purse while it is short (`Purse.reserve`): the hall, supply, the barracks,\n\t * the altar, the answer to their army and another hall go before it (their wants are more important); a workshop,\n\t * the next tier, a second barracks and the soldiers wait for it. 35 when left out\n\t */\n\tpriority?: number\n}\n\n/** The reservation's name in the purse */\nconst HERO = 'melee.hero'\n\n/**\n * The melee brain's heroes module: a fallen hero revived, the next trained while it wants more, their price held in the\n * purse meanwhile. After the economy, before the building, as the old turn had it; `steps.heroes` and\n * `steps.buildOrder` honoured\n *\n * @beta\n */\nexport const heroes = (options: MeleeHeroesOptions = {}): AiModuleDef =>\n\tdefineModule({ id: 'melee.heroes', make: (ai: Brain) => ({\n\t\tid: 'melee.heroes',\n\t\tphase: 'plan',\n\t\tafter: ['economy'],\n\t\tbefore: ['melee.build', 'melee.production'],\n\t\tthink: () => {\n\t\t\t// what the game says to make first holds back what the computer would make of itself, heroes too\n\t\t\tif (ai.plans.following || ai.area(Economy).waiting) return\n\t\t\trun(ai, { ...options, ...ai.settings.heroes })\n\t\t}\n\t}) })\n\n/** The turn: revives, or trains the next */\nfunction run(ai: Brain, options: MeleeHeroesOptions): void {\n\tconst { registry, view } = ai\n\tconst { me } = view\n\tconst priority = options.priority ?? 35\n\tconst altars = view.typesOf('altar').flatMap((type) => view.mine.ofType(type.id).finished().items)\n\tconst idle = altars.find((altar) => !queueOf(altar).length)\n\tif (!idle) return\n\t// what a hero costs is held in the purse while it is short: nothing that can wait is bought meanwhile\n\tconst fallen = me.heroes.find((hero) => !hero.alive && hero.reviving === undefined)\n\tif (fallen) {\n\t\tconst price = fallen.reviveCost ?? {}\n\t\tif (ai.purse.spend(price)) {\n\t\t\tai.send({ type: 'revive', building: idle.id, hero: fallen.id })\n\t\t\tai.decide(`revives its ${fallen.type}`, { kind: 'hero' })\n\t\t} else ai.purse.reserve(HERO, price, priority)\n\t\treturn\n\t}\n\t// the second hero can wait until there is an army\n\tconst most = options.most ?? 2\n\tconst wanted = ai.time > (options.secondFrom ?? 240) ? most : Math.min(1, most)\n\tif (me.heroes.length >= wanted) return\n\tconst candidates = (view.def(idle).trains ?? [])\n\t\t.map((id) => registry.unit(id))\n\t\t.filter((def) => def.hero && availableToPlayer(def, { race: me.race, availability: me.availability }, def.id))\n\tconst next = ai.area(Micro).nextHero(\n\t\tcandidates,\n\t\tme.heroes.map((hero) => hero.type)\n\t)\n\tif (!next) return\n\tif (ai.plans.production.train(idle, next)) ai.decide(`trains ${an(next.id)}: hero ${me.heroes.length + 1} of ${wanted}`, { kind: 'hero' })\n\telse if (next.cost) ai.purse.reserve(HERO, next.cost, priority)\n}\n"],"mappings":";;;;;;;;AAqCA,IAAM,OAAO;;;;;;;;AASb,IAAa,UAAU,UAA8B,CAAC,MACrD,aAAa;CAAE,IAAI;CAAgB,OAAO,QAAe;EACxD,IAAI;EACJ,OAAO;EACP,OAAO,CAAC,SAAS;EACjB,QAAQ,CAAC,eAAe,kBAAkB;EAC1C,aAAa;GAEZ,IAAI,GAAG,MAAM,aAAa,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS;GACpD,IAAI,IAAI;IAAE,GAAG;IAAS,GAAG,GAAG,SAAS;GAAO,CAAC;EAC9C;CACD;AAAG,CAAC;;AAGL,SAAS,IAAI,IAAW,SAAmC;CAC1D,MAAM,EAAE,UAAU,SAAS;CAC3B,MAAM,EAAE,OAAO;CACf,MAAM,WAAW,QAAQ,YAAY;CAErC,MAAM,OADS,KAAK,QAAQ,OAAO,CAAC,CAAC,SAAS,SAAS,KAAK,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,KAC/E,CAAA,CAAO,MAAM,UAAU,CAAC,QAAQ,KAAK,CAAC,CAAC,MAAM;CAC1D,IAAI,CAAC,MAAM;CAEX,MAAM,SAAS,GAAG,OAAO,MAAM,SAAS,CAAC,KAAK,SAAS,KAAK,aAAa,KAAA,CAAS;CAClF,IAAI,QAAQ;EACX,MAAM,QAAQ,OAAO,cAAc,CAAC;EACpC,IAAI,GAAG,MAAM,MAAM,KAAK,GAAG;GAC1B,GAAG,KAAK;IAAE,MAAM;IAAU,UAAU,KAAK;IAAI,MAAM,OAAO;GAAG,CAAC;GAC9D,GAAG,OAAO,eAAe,OAAO,QAAQ,EAAE,MAAM,OAAO,CAAC;EACzD,OAAO,GAAG,MAAM,QAAQ,MAAM,OAAO,QAAQ;EAC7C;CACD;CAEA,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,SAAS,GAAG,QAAQ,QAAQ,cAAc,OAAO,OAAO,KAAK,IAAI,GAAG,IAAI;CAC9E,IAAI,GAAG,OAAO,UAAU,QAAQ;CAChC,MAAM,cAAc,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,EAAA,CAC5C,KAAK,OAAO,SAAS,KAAK,EAAE,CAAC,CAAC,CAC9B,QAAQ,QAAQ,IAAI,QAAQ,kBAAkB,KAAK;EAAE,MAAM,GAAG;EAAM,cAAc,GAAG;CAAa,GAAG,IAAI,EAAE,CAAC;CAC9G,MAAM,OAAO,GAAG,KAAK,KAAK,CAAC,CAAC,SAC3B,YACA,GAAG,OAAO,KAAK,SAAS,KAAK,IAAI,CAClC;CACA,IAAI,CAAC,MAAM;CACX,IAAI,GAAG,MAAM,WAAW,MAAM,MAAM,IAAI,GAAG,GAAG,OAAO,UAAU,GAAG,KAAK,EAAE,EAAE,SAAS,GAAG,OAAO,SAAS,EAAE,MAAM,UAAU,EAAE,MAAM,OAAO,CAAC;MACpI,IAAI,KAAK,MAAM,GAAG,MAAM,QAAQ,MAAM,KAAK,MAAM,QAAQ;AAC/D"}
|
package/dist/ai/melee/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { type DefinedBrain } from '#engine/ai/define';
|
|
|
4
4
|
* lists it first. It thinks as its profile says (the difficulty's `every`), unless the
|
|
5
5
|
* seat's options say how often. The file's comment lists its modules
|
|
6
6
|
*
|
|
7
|
-
* @
|
|
7
|
+
* @public
|
|
8
8
|
*/
|
|
9
9
|
export declare const meleeBrain: DefinedBrain;
|
|
10
10
|
export { build as meleeBuild, MELEE_LADDER, type MeleeBuildOptions, type MeleeWant } from './build';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { defineModule } from "../module.js";
|
|
2
|
+
import { goals } from "../goals.js";
|
|
3
|
+
import { rules, words } from "../rules.js";
|
|
4
|
+
import { squads } from "../squads.js";
|
|
5
|
+
import { defence } from "../defence.js";
|
|
6
|
+
import { team } from "../team.js";
|
|
7
|
+
import { defineBrain } from "../define.js";
|
|
8
|
+
import { economy } from "../economy.js";
|
|
9
|
+
import { micro } from "../micro.js";
|
|
10
|
+
import { scouting } from "../scouting.js";
|
|
11
|
+
import { waves } from "../waves.js";
|
|
12
|
+
import { MELEE_LADDER, build } from "./build.js";
|
|
13
|
+
import { MELEE_ARMY, MeleeArmy, army, meleeArmyOf } from "./goals.js";
|
|
14
|
+
import { heroes } from "./heroes.js";
|
|
15
|
+
import { production } from "./production.js";
|
|
16
|
+
import { surrender } from "./surrender.js";
|
|
17
|
+
//#region src/ai/melee/index.ts
|
|
18
|
+
/**
|
|
19
|
+
* The engine's melee computer player as a brain: what `world.computers.seat` seats where no brain is named and the game
|
|
20
|
+
* lists it first. It thinks as its profile says (the difficulty's `every`), unless the
|
|
21
|
+
* seat's options say how often. The file's comment lists its modules
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
var meleeBrain = defineBrain({
|
|
26
|
+
id: "core.melee",
|
|
27
|
+
modules: [
|
|
28
|
+
defineModule({
|
|
29
|
+
id: "rules",
|
|
30
|
+
make: (ai) => rules(ai.def.rules ?? [])(ai)
|
|
31
|
+
}),
|
|
32
|
+
words(),
|
|
33
|
+
defence(),
|
|
34
|
+
team(),
|
|
35
|
+
economy({ expansions: 1 }),
|
|
36
|
+
heroes(),
|
|
37
|
+
build(),
|
|
38
|
+
production(),
|
|
39
|
+
army(),
|
|
40
|
+
surrender(),
|
|
41
|
+
goals(),
|
|
42
|
+
scouting(),
|
|
43
|
+
waves(),
|
|
44
|
+
squads(),
|
|
45
|
+
micro()
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
//#endregion
|
|
49
|
+
export { MELEE_ARMY, MELEE_LADDER, MeleeArmy, army as meleeArmy, meleeArmyOf, meleeBrain, build as meleeBuild, heroes as meleeHeroes, production as meleeProduction, surrender as meleeSurrender };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/ai/melee/index.ts"],"sourcesContent":["import type { Brain } from '#engine/ai/brain'\nimport { type AiModule, defineModule } from '#engine/ai/module'\nimport { defineBrain, type DefinedBrain } from '#engine/ai/define'\nimport { defence } from '#engine/ai/defence'\nimport { economy } from '#engine/ai/economy'\nimport { goals } from '#engine/ai/goals'\nimport { micro } from '#engine/ai/micro'\nimport { rules, words } from '#engine/ai/rules'\nimport { scouting } from '#engine/ai/scouting'\nimport { squads } from '#engine/ai/squads'\nimport { team } from '#engine/ai/team'\nimport { waves } from '#engine/ai/waves'\nimport { build } from './build'\nimport { army } from './goals'\nimport { heroes } from './heroes'\nimport { production } from './production'\nimport { surrender } from './surrender'\n\n/*\n * The melee brain (AI plan, D3): the engine's own computer player for a game like a melee, assembled from the kit\n * and nothing else (a test holds this folder to the public API). What a game played as melee lists first in\n * `Rules.brains`, so that `world.computers.seat` with no brain seats it. One module a file, in\n * the order a think runs them:\n *\n * - `rules` (the brain's own, `meleeBrain.with({ rules })`) and `words` (attack, defend, retreat, hold, pause: B2)\n * - `defence` (C4) and `team` (C5): the raids counted and the team's board read, before the goals are picked\n * - `economy` (C4): the workers, base by base\n * - `melee.heroes`, `melee.build`, `melee.production` (D3, over B3): the heroes, the ladder of wants, what is trained\n * - `melee.army` (D3, over B1): the army's goals (attack, creep, raid, harass, expand) put on the picker\n * - `melee.surrender` (RV92): it gives up once it cannot come back (no hall, no worker, no army that could win)\n * - `goals` (B1): the picker, which runs every goal with what it claims: the army's, the defence's `defend`, the\n * team's `help`, the scouting's `scout`, and a game's own (`meleeBrain.with({ goals })`, `AiOptions.goals`)\n * - `scouting` (C3): nothing in its think, its goal is on the picker\n * - `waves` (D2): the waves given as data, where there are any\n * - `squads` (C1): every squad's task seen to, orders sent once and watched, regroups, retreats, reinforcements\n * - `micro` (C2): the fights of the squads: whom to hit, kiting, fleeing, spells, items, the heroes' skills\n *\n * A variant is `meleeBrain.with({ goals, rules, modules, without, ...anything of BrainDef })`; a part is left out by\n * its module's id (`without: ['melee.heroes']`); a part done another way is a module of one's own beside the rest.\n * How it plays is the seat's options and its profile (`AiOptions`, D1)\n */\n\n/**\n * The engine's melee computer player as a brain: what `world.computers.seat` seats where no brain is named and the game\n * lists it first. It thinks as its profile says (the difficulty's `every`), unless the\n * seat's options say how often. The file's comment lists its modules\n *\n * @public\n */\nexport const meleeBrain: DefinedBrain = defineBrain({\n\tid: 'core.melee',\n\tmodules: [\n\t\t// the brain's own rules (`with({ rules })`) first: what a rule takes is not given orders by the rest\n\t\tdefineModule({ id: 'rules', make: (ai: Brain) => (rules(ai.def.rules ?? []) as (ai: Brain) => AiModule)(ai) }),\n\t\twords(),\n\t\tdefence(),\n\t\tteam(),\n\t\t// one hall past its first, where the difficulty and the personality say nothing\n\t\teconomy({ expansions: 1 }),\n\t\theroes(),\n\t\tbuild(),\n\t\tproduction(),\n\t\tarmy(),\n\t\tsurrender(),\n\t\tgoals(),\n\t\tscouting(),\n\t\twaves(),\n\t\tsquads(),\n\t\tmicro()\n\t]\n})\n\nexport { build as meleeBuild, MELEE_LADDER, type MeleeBuildOptions, type MeleeWant } from './build'\nexport { army as meleeArmy, MeleeArmy, type MeleeArmyMemory, type MeleeArmyModule, type MeleeArmyOptions, meleeArmyOf, MELEE_ARMY } from './goals'\nexport { heroes as meleeHeroes, type MeleeHeroesOptions } from './heroes'\nexport { production as meleeProduction } from './production'\nexport { surrender as meleeSurrender, type MeleeSurrenderOptions } from './surrender'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiDA,IAAa,aAA2B,YAAY;CACnD,IAAI;CACJ,SAAS;EAER,aAAa;GAAE,IAAI;GAAS,OAAO,OAAe,MAAM,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAA6B,EAAE;EAAE,CAAC;EAC7G,MAAM;EACN,QAAQ;EACR,KAAK;EAEL,QAAQ,EAAE,YAAY,EAAE,CAAC;EACzB,OAAO;EACP,MAAM;EACN,WAAW;EACX,KAAK;EACL,UAAU;EACV,MAAM;EACN,SAAS;EACT,MAAM;EACN,OAAO;EACP,MAAM;CACP;AACD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineModule } from "../module.js";
|
|
2
|
+
import { Economy } from "../economy.js";
|
|
3
|
+
//#region src/ai/melee/production.ts
|
|
4
|
+
/**
|
|
5
|
+
* The melee brain's production module: the production plan thought, after the building and before the picker, as the
|
|
6
|
+
* old turn had it; `steps.production` honoured
|
|
7
|
+
*
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
var production = () => defineModule({
|
|
11
|
+
id: "melee.production",
|
|
12
|
+
make: (ai) => ({
|
|
13
|
+
id: "melee.production",
|
|
14
|
+
phase: "plan",
|
|
15
|
+
after: [
|
|
16
|
+
"economy",
|
|
17
|
+
"melee.heroes",
|
|
18
|
+
"melee.build"
|
|
19
|
+
],
|
|
20
|
+
think: () => {
|
|
21
|
+
if (ai.area(Economy).waiting) return;
|
|
22
|
+
ai.plans.production.think();
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
//#endregion
|
|
27
|
+
export { production };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=production.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"production.js","names":[],"sources":["../../../src/ai/melee/production.ts"],"sourcesContent":["import { type Brain } from '#engine/ai/brain'\nimport { Economy } from '../economy'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\n\n/*\n * What the melee player trains and researches (AI plan, D3; the part of its turn that was `runProduction`): the\n * brain's production plan (B3), thought in its place among the melee modules: towards the composition (even shares of\n * what it can train, what answers the rivals' armies seen pulling them about: riflemen against flyers), the units\n * wanted outright (a wave's group, the game's build order), supply kept ahead, and research of what its army uses\n * most with money to spare. Nothing while the economy waits for what the money is gathered at. The kit's own\n * `production()` module is the same think without the melee player's gate and `steps`\n */\n\n/**\n * The melee brain's production module: the production plan thought, after the building and before the picker, as the\n * old turn had it; `steps.production` honoured\n *\n * @beta\n */\nexport const production = (): AiModuleDef =>\n\tdefineModule({ id: 'melee.production', make: (ai: Brain) => ({\n\t\tid: 'melee.production',\n\t\tphase: 'plan',\n\t\tafter: ['economy', 'melee.heroes', 'melee.build'],\n\t\tthink: () => {\n\t\t\tif (ai.area(Economy).waiting) return\n\t\t\tai.plans.production.think()\n\t\t}\n\t}) })\n"],"mappings":";;;;;;;;;AAmBA,IAAa,mBACZ,aAAa;CAAE,IAAI;CAAoB,OAAO,QAAe;EAC5D,IAAI;EACJ,OAAO;EACP,OAAO;GAAC;GAAW;GAAgB;EAAa;EAChD,aAAa;GACZ,IAAI,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS;GAC9B,GAAG,MAAM,WAAW,MAAM;EAC3B;CACD;AAAG,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { defineModule } from "../module.js";
|
|
2
|
+
import { evaluate } from "../rules.js";
|
|
3
|
+
//#region src/ai/melee/surrender.ts
|
|
4
|
+
var AFTER = 30;
|
|
5
|
+
/** The odds of its fighters against their army as last seen under which they cannot win the game back */
|
|
6
|
+
var HOPELESS_ODDS = .2;
|
|
7
|
+
/** How long ago their army was seen, for those odds */
|
|
8
|
+
var ARMY_SEEN = 120;
|
|
9
|
+
/** The default: nothing to rebuild with, and nothing to fight with */
|
|
10
|
+
function beaten(ai) {
|
|
11
|
+
const { mine } = ai.view;
|
|
12
|
+
if (mine.withRole("hall").length || mine.workers().length) return false;
|
|
13
|
+
const fighters = mine.fighters();
|
|
14
|
+
if (!fighters.length) return true;
|
|
15
|
+
const theirs = {};
|
|
16
|
+
for (const army of ai.knowledge.enemy.armySeen(ARMY_SEEN)) for (const [type, count] of Object.entries(army.types)) theirs[type] = (theirs[type] ?? 0) + count;
|
|
17
|
+
if (!Object.keys(theirs).length) return false;
|
|
18
|
+
return ai.view.strength.odds(fighters, theirs) < HOPELESS_ODDS;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The melee brain's surrender module (`melee.surrender`): gives up once it cannot come back (see
|
|
22
|
+
* `MeleeSurrenderOptions`), the engine's `surrender` command sent once. Its options under the settings' (`army.surrender`)
|
|
23
|
+
*
|
|
24
|
+
* @beta
|
|
25
|
+
*/
|
|
26
|
+
var surrender = (options = {}) => defineModule({
|
|
27
|
+
id: "melee.surrender",
|
|
28
|
+
make: (ai) => {
|
|
29
|
+
let memory = {};
|
|
30
|
+
return {
|
|
31
|
+
id: "melee.surrender",
|
|
32
|
+
phase: "decide",
|
|
33
|
+
think: () => {
|
|
34
|
+
const given = ai.settings.army?.surrender;
|
|
35
|
+
if (given === false || memory.done || ai.view.me.defeated) return;
|
|
36
|
+
const { when, after = AFTER } = {
|
|
37
|
+
...options,
|
|
38
|
+
...given
|
|
39
|
+
};
|
|
40
|
+
if (!(when === void 0 ? beaten(ai) : evaluate(when, ai))) {
|
|
41
|
+
memory.since = void 0;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
memory.since ??= ai.tick;
|
|
45
|
+
if (ai.tick - memory.since < after * ai.session.tickRate) return;
|
|
46
|
+
memory.done = true;
|
|
47
|
+
ai.decide(`gives up: it cannot come back (${Math.round((ai.tick - memory.since) / ai.session.tickRate)} s)`, { kind: "army" });
|
|
48
|
+
ai.send({ type: "surrender" });
|
|
49
|
+
},
|
|
50
|
+
save: () => memory.since === void 0 && !memory.done ? void 0 : { ...memory },
|
|
51
|
+
restore: (data) => {
|
|
52
|
+
memory = { ...data };
|
|
53
|
+
},
|
|
54
|
+
inspect: () => ({
|
|
55
|
+
since: memory.since,
|
|
56
|
+
done: !!memory.done
|
|
57
|
+
})
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//#endregion
|
|
62
|
+
export { surrender };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=surrender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surrender.js","names":[],"sources":["../../../src/ai/melee/surrender.ts"],"sourcesContent":["import { type Brain } from '#engine/ai/brain'\nimport { type AiModuleDef, defineModule } from '#engine/ai/module'\nimport { type AiCondition, evaluate } from '#engine/ai/rules'\n\n/*\n * The melee player gives up (RV92): once it cannot come back, it sends the engine's `surrender` command, as a person\n * would, rather than keep a game going with a farm and a tower nobody finds. Cannot come back is, by default: no hall\n * and no worker of its own (nothing to gather with nor to train a worker at), and what fighters it has outmatched by\n * their army as last seen (odds under 0.2), for half a minute on end. A game's own condition goes in its place\n * (`settings.army.surrender.when`, as data or a function), and `surrender: false` keeps it playing to the last (a\n * mission's computer, whose defeat is the story's to say)\n */\n\n/**\n * When the melee player gives up (`MeleeArmyOptions.surrender`): the condition, and how long it holds first\n *\n * @beta\n */\nexport interface MeleeSurrenderOptions {\n\t/**\n\t * When it cannot come back, as a condition (data or a function of the brain). By default: no hall and no worker of\n\t * its own, and its fighters (none at all, or) outmatched by their army as last seen in the last two minutes, odds\n\t * under 0.2\n\t */\n\twhen?: AiCondition\n\t/** Seconds the condition holds on end before it gives up: 30 when left out */\n\tafter?: number\n}\n\n/** What the module remembers, as a save keeps it: since when it is beaten, and whether it gave up */\ninterface SurrenderMemory {\n\tsince?: number\n\tdone?: boolean\n}\n\nconst AFTER = 30\n/** The odds of its fighters against their army as last seen under which they cannot win the game back */\nconst HOPELESS_ODDS = 0.2\n/** How long ago their army was seen, for those odds */\nconst ARMY_SEEN = 120\n\n/** The default: nothing to rebuild with, and nothing to fight with */\nfunction beaten(ai: Brain): boolean {\n\tconst { mine } = ai.view\n\tif (mine.withRole('hall').length || mine.workers().length) return false\n\tconst fighters = mine.fighters()\n\tif (!fighters.length) return true\n\tconst theirs: Record<string, number> = {}\n\tfor (const army of ai.knowledge.enemy.armySeen(ARMY_SEEN))\n\t\tfor (const [type, count] of Object.entries(army.types)) theirs[type] = (theirs[type] ?? 0) + count\n\tif (!Object.keys(theirs).length) return false\n\treturn ai.view.strength.odds(fighters, theirs) < HOPELESS_ODDS\n}\n\n/**\n * The melee brain's surrender module (`melee.surrender`): gives up once it cannot come back (see\n * `MeleeSurrenderOptions`), the engine's `surrender` command sent once. Its options under the settings' (`army.surrender`)\n *\n * @beta\n */\nexport const surrender = (options: MeleeSurrenderOptions = {}): AiModuleDef =>\n\tdefineModule({ id: 'melee.surrender', make: (ai: Brain) => {\n\t\tlet memory: SurrenderMemory = {}\n\t\treturn {\n\t\t\tid: 'melee.surrender',\n\t\t\tphase: 'decide',\n\t\t\tthink: () => {\n\t\t\t\tconst given = ai.settings.army?.surrender\n\t\t\t\tif (given === false || memory.done || ai.view.me.defeated) return\n\t\t\t\tconst { when, after = AFTER } = { ...options, ...given }\n\t\t\t\tif (!(when === undefined ? beaten(ai) : evaluate(when, ai))) {\n\t\t\t\t\tmemory.since = undefined\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tmemory.since ??= ai.tick\n\t\t\t\tif (ai.tick - memory.since < after * ai.session.tickRate) return\n\t\t\t\tmemory.done = true\n\t\t\t\tai.decide(`gives up: it cannot come back (${Math.round((ai.tick - memory.since) / ai.session.tickRate)} s)`, { kind: 'army' })\n\t\t\t\tai.send({ type: 'surrender' })\n\t\t\t},\n\t\t\tsave: () => (memory.since === undefined && !memory.done ? undefined : { ...memory }),\n\t\t\trestore: (data) => {\n\t\t\t\tmemory = { ...(data as SurrenderMemory) }\n\t\t\t},\n\t\t\tinspect: () => ({ since: memory.since, done: !!memory.done })\n\t\t}\n\t} })\n"],"mappings":";;;AAmCA,IAAM,QAAQ;;AAEd,IAAM,gBAAgB;;AAEtB,IAAM,YAAY;;AAGlB,SAAS,OAAO,IAAoB;CACnC,MAAM,EAAE,SAAS,GAAG;CACpB,IAAI,KAAK,SAAS,MAAM,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,QAAQ,OAAO;CAClE,MAAM,WAAW,KAAK,SAAS;CAC/B,IAAI,CAAC,SAAS,QAAQ,OAAO;CAC7B,MAAM,SAAiC,CAAC;CACxC,KAAK,MAAM,QAAQ,GAAG,UAAU,MAAM,SAAS,SAAS,GACvD,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,KAAK,GAAG,OAAO,SAAS,OAAO,SAAS,KAAK;CAC9F,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,QAAQ,OAAO;CACxC,OAAO,GAAG,KAAK,SAAS,KAAK,UAAU,MAAM,IAAI;AAClD;;;;;;;AAQA,IAAa,aAAa,UAAiC,CAAC,MAC3D,aAAa;CAAE,IAAI;CAAmB,OAAO,OAAc;EAC1D,IAAI,SAA0B,CAAC;EAC/B,OAAO;GACN,IAAI;GACJ,OAAO;GACP,aAAa;IACZ,MAAM,QAAQ,GAAG,SAAS,MAAM;IAChC,IAAI,UAAU,SAAS,OAAO,QAAQ,GAAG,KAAK,GAAG,UAAU;IAC3D,MAAM,EAAE,MAAM,QAAQ,UAAU;KAAE,GAAG;KAAS,GAAG;IAAM;IACvD,IAAI,EAAE,SAAS,KAAA,IAAY,OAAO,EAAE,IAAI,SAAS,MAAM,EAAE,IAAI;KAC5D,OAAO,QAAQ,KAAA;KACf;IACD;IACA,OAAO,UAAU,GAAG;IACpB,IAAI,GAAG,OAAO,OAAO,QAAQ,QAAQ,GAAG,QAAQ,UAAU;IAC1D,OAAO,OAAO;IACd,GAAG,OAAO,kCAAkC,KAAK,OAAO,GAAG,OAAO,OAAO,SAAS,GAAG,QAAQ,QAAQ,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;IAC7H,GAAG,KAAK,EAAE,MAAM,YAAY,CAAC;GAC9B;GACA,YAAa,OAAO,UAAU,KAAA,KAAa,CAAC,OAAO,OAAO,KAAA,IAAY,EAAE,GAAG,OAAO;GAClF,UAAU,SAAS;IAClB,SAAS,EAAE,GAAI,KAAyB;GACzC;GACA,gBAAgB;IAAE,OAAO,OAAO;IAAO,MAAM,CAAC,CAAC,OAAO;GAAK;EAC5D;CACD;AAAE,CAAC"}
|
package/dist/ai/micro.d.ts
CHANGED
|
@@ -14,8 +14,11 @@ import { UnitSet } from './view';
|
|
|
14
14
|
* @beta
|
|
15
15
|
*/
|
|
16
16
|
export interface AbilityAiView {
|
|
17
|
+
/** The picture of the game the computer player has, as its seat sees it */
|
|
17
18
|
snapshot: Snapshot;
|
|
19
|
+
/** The registry of the game's definitions, for looking up unit types, abilities and buffs */
|
|
18
20
|
registry: Registry;
|
|
21
|
+
/** The player whose computer is weighing the ability */
|
|
19
22
|
playerId: PlayerId;
|
|
20
23
|
/** Enemy units it sees, near enough to the caster to matter */
|
|
21
24
|
enemies: EntityState[];
|
|
@@ -56,6 +59,7 @@ export type TargetPicker = (ai: Brain, squad: Squad, foes: UnitSet) => EntitySta
|
|
|
56
59
|
export type SpellAim = (ai: Brain, caster: EntityState, foes: readonly EntityState[], friends: readonly EntityState[], level: number) => {
|
|
57
60
|
point: Vec2;
|
|
58
61
|
target?: number;
|
|
62
|
+
to?: Vec2;
|
|
59
63
|
} | null | undefined;
|
|
60
64
|
/**
|
|
61
65
|
* A hero the brain means to have (`MicroOptions.heroes`): which, what it learns in what order, what it buys
|
|
@@ -174,6 +178,7 @@ export interface MicroOptions {
|
|
|
174
178
|
* @beta
|
|
175
179
|
*/
|
|
176
180
|
export interface MicroMemory {
|
|
181
|
+
/** The version of the memory's format: 1 so far */
|
|
177
182
|
v: 1;
|
|
178
183
|
/** Whom each squad hits, by squad name: the foe and since when */
|
|
179
184
|
focus: Record<string, {
|
|
@@ -216,6 +221,7 @@ export interface MicroMemory {
|
|
|
216
221
|
* @beta
|
|
217
222
|
*/
|
|
218
223
|
export interface MicroReport {
|
|
224
|
+
/** The fights, one for each squad in one, with its foes, its odds, whom it hits and its units that kited or shot a building this think */
|
|
219
225
|
fights: {
|
|
220
226
|
squad: string;
|
|
221
227
|
foes: number;
|
|
@@ -231,6 +237,7 @@ export interface MicroReport {
|
|
|
231
237
|
/** Its siege units told to shoot a building this think */
|
|
232
238
|
siege: number[];
|
|
233
239
|
}[];
|
|
240
|
+
/** The units that fled, each with its id, type, health, where to, since when and why */
|
|
234
241
|
fleeing: {
|
|
235
242
|
unit: number;
|
|
236
243
|
type: string;
|
|
@@ -239,12 +246,14 @@ export interface MicroReport {
|
|
|
239
246
|
since: number;
|
|
240
247
|
why: 'hurt' | 'injured';
|
|
241
248
|
}[];
|
|
249
|
+
/** The heroes, each with its id, type, level and the ability it learns next */
|
|
242
250
|
heroes: {
|
|
243
251
|
id: number;
|
|
244
252
|
type: string;
|
|
245
253
|
level: number;
|
|
246
254
|
next?: string;
|
|
247
255
|
}[];
|
|
256
|
+
/** The heroes on their way to buy, each with the hero's id, the item, the shop's id and since when */
|
|
248
257
|
shopping: {
|
|
249
258
|
hero: number;
|
|
250
259
|
item: string;
|