@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
package/dist/ai/team.js
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import { distSq } from "../math.js";
|
|
2
|
+
import { defineModule } from "./module.js";
|
|
3
|
+
import { consider, curve, defineGoal } from "./goals.js";
|
|
4
|
+
import { pair, point, where } from "./geometry.js";
|
|
5
|
+
import { Defence } from "./defence.js";
|
|
6
|
+
//#region src/ai/team.ts
|
|
7
|
+
/** How near the place of a request the enemies seen there are counted in its strength */
|
|
8
|
+
var SEEN_NEAR = 16;
|
|
9
|
+
/** The most units sent to a call with no enemy seen there: enough to look and to hold a little */
|
|
10
|
+
var HELP_UNSEEN = 3;
|
|
11
|
+
/** Seconds a plan waits past its time for the waves of those that joined, before it is over */
|
|
12
|
+
var PLAN_OVER = 30;
|
|
13
|
+
/**
|
|
14
|
+
* The id of the help goal
|
|
15
|
+
*
|
|
16
|
+
* @beta
|
|
17
|
+
*/
|
|
18
|
+
var HELP = "help";
|
|
19
|
+
/**
|
|
20
|
+
* The id of the goal that does what an ally's ping asks (`push`, `hold`): `pinged`
|
|
21
|
+
*
|
|
22
|
+
* @beta
|
|
23
|
+
*/
|
|
24
|
+
var PINGED = "pinged";
|
|
25
|
+
/** What is sent at a ping, by what it asks: the squad's name */
|
|
26
|
+
var PING_SQUADS = {
|
|
27
|
+
attack: "push",
|
|
28
|
+
defend: "hold"
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* An empty board
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
var emptyTeam = () => ({
|
|
36
|
+
v: 1,
|
|
37
|
+
requests: [],
|
|
38
|
+
known: {},
|
|
39
|
+
next: 1
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* A brain's team play (`ai.team`): the team's board (`board`: requests, the plan of an attack together, what each
|
|
43
|
+
* computer knows), the `help` goal, and what it says. The board is the world's (`core.ai.teams`) where the seat hands
|
|
44
|
+
* it over (`BrainContext.team`), else its own: a brain made by hand plays alone
|
|
45
|
+
*
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
48
|
+
var Team = class Team {
|
|
49
|
+
ai;
|
|
50
|
+
shared;
|
|
51
|
+
/** What finds it on a brain (`ai.area(Team)`): made the first time a module asks for it */
|
|
52
|
+
static id = "team";
|
|
53
|
+
/** Makes the team play of a brain; what `ai.area(Team)` calls the first time a module asks for it */
|
|
54
|
+
static make(ai) {
|
|
55
|
+
return new Team(ai, ai.teamBoard);
|
|
56
|
+
}
|
|
57
|
+
/** Its id among the brain's areas: what its memory and its report are kept under */
|
|
58
|
+
id = "team";
|
|
59
|
+
/** What the log says where a save's memory of it is of a shape it does not read */
|
|
60
|
+
afresh = "the save remembers the computer player’s team play in a shape this brain does not read: it starts afresh";
|
|
61
|
+
/** Whether a `team()` module is in the brain */
|
|
62
|
+
enabled = false;
|
|
63
|
+
memory = {
|
|
64
|
+
v: 1,
|
|
65
|
+
heard: -1,
|
|
66
|
+
said: {}
|
|
67
|
+
};
|
|
68
|
+
moduleOptions = {};
|
|
69
|
+
own = emptyTeam();
|
|
70
|
+
/** The help goal: added to the brain's picker by the module, where it defends users */
|
|
71
|
+
goal;
|
|
72
|
+
/** The goal that does what an ally's ping asks (`answerPings`): added with the help goal */
|
|
73
|
+
pingGoal;
|
|
74
|
+
constructor(ai, shared) {
|
|
75
|
+
this.ai = ai;
|
|
76
|
+
this.shared = shared;
|
|
77
|
+
this.goal = this.makeGoal();
|
|
78
|
+
this.pingGoal = this.makePingGoal();
|
|
79
|
+
}
|
|
80
|
+
/** Puts the `team()` module's options under the brain's settings, and the help goal on the picker */
|
|
81
|
+
configure(options) {
|
|
82
|
+
this.moduleOptions = options;
|
|
83
|
+
if (!this.enabled && (this.options.defendUsers ?? true)) this.ai.goals.add(this.goal);
|
|
84
|
+
if (!this.enabled && (this.options.answerPings ?? true)) this.ai.goals.add(this.pingGoal);
|
|
85
|
+
this.enabled = true;
|
|
86
|
+
}
|
|
87
|
+
/** How it plays with its team: the module's options, the brain's settings over them (`ai.settings.team`) */
|
|
88
|
+
get options() {
|
|
89
|
+
return this.ai.cache("team.options", () => ({
|
|
90
|
+
...this.moduleOptions,
|
|
91
|
+
...this.ai.settings.team
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
/** Whether its waves wait for the team's plan (`together`) */
|
|
95
|
+
get together() {
|
|
96
|
+
return this.enabled && !!this.options.together;
|
|
97
|
+
}
|
|
98
|
+
/** The team's board: the world's, shared by the team's computers, or its own where the seat gave none */
|
|
99
|
+
get board() {
|
|
100
|
+
return this.shared?.() ?? this.own;
|
|
101
|
+
}
|
|
102
|
+
/** Its team's number */
|
|
103
|
+
get team() {
|
|
104
|
+
return this.ai.view.me.team;
|
|
105
|
+
}
|
|
106
|
+
/** The computers of its team, as seen on the board lately (each writes itself as it thinks), itself among them */
|
|
107
|
+
computers() {
|
|
108
|
+
const { board, ai } = this;
|
|
109
|
+
const recent = ai.tick - 10 * ai.session.tickRate;
|
|
110
|
+
return Object.entries(board.known).filter(([, known]) => known.tick >= recent).map(([id]) => Number(id)).sort((a, b) => a - b);
|
|
111
|
+
}
|
|
112
|
+
/** The requests on the board, those of a kind where given: those still standing */
|
|
113
|
+
requests(kind) {
|
|
114
|
+
const { tick } = this.ai;
|
|
115
|
+
return this.board.requests.filter((each) => each.until > tick && (kind === void 0 || each.kind === kind));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Asks the team for something at a place: a request on the board, or the one of the same asker, kind and place made
|
|
119
|
+
* to stand longer, with the strength seen now. Gives back the request
|
|
120
|
+
*/
|
|
121
|
+
request(kind, at, strength, by, from = this.ai.playerId, seconds) {
|
|
122
|
+
const { ai, board } = this;
|
|
123
|
+
const until = ai.tick + Math.round((seconds ?? this.options.requestFor ?? 30) * ai.session.tickRate);
|
|
124
|
+
const same = board.requests.find((each) => each.from === from && each.kind === kind && each.until > ai.tick && distSq(each.at, at) <= 256);
|
|
125
|
+
if (same) {
|
|
126
|
+
same.until = Math.max(same.until, until);
|
|
127
|
+
same.strength = Math.max(same.strength, strength);
|
|
128
|
+
return same;
|
|
129
|
+
}
|
|
130
|
+
const request = {
|
|
131
|
+
id: board.next++,
|
|
132
|
+
kind,
|
|
133
|
+
from,
|
|
134
|
+
at: point(at),
|
|
135
|
+
strength,
|
|
136
|
+
until,
|
|
137
|
+
by,
|
|
138
|
+
answered: []
|
|
139
|
+
};
|
|
140
|
+
board.requests.push(request);
|
|
141
|
+
ai.decide(`asks for ${kind} at ${where(at)}${from === ai.playerId ? "" : ` for player ${from}`} (${by}, strength ${Math.round(strength)})`, { kind: "team" });
|
|
142
|
+
return request;
|
|
143
|
+
}
|
|
144
|
+
/** The enemy's bases the team knows, every computer's put together: one a place, the latest seen */
|
|
145
|
+
enemyBases() {
|
|
146
|
+
const merged = [];
|
|
147
|
+
const known = this.board.known;
|
|
148
|
+
for (const id of Object.keys(known).sort((a, b) => Number(a) - Number(b))) for (const base of known[id].bases) {
|
|
149
|
+
const same = merged.find((each) => each.owner === base.owner && distSq(each.at, base.at) < 256);
|
|
150
|
+
if (same) same.last = Math.max(same.last, base.last);
|
|
151
|
+
else merged.push({
|
|
152
|
+
...base,
|
|
153
|
+
at: point(base.at)
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return merged;
|
|
157
|
+
}
|
|
158
|
+
/** The plan of an attack together, while it stands */
|
|
159
|
+
get plan() {
|
|
160
|
+
const plan = this.board.plan;
|
|
161
|
+
return plan && this.ai.tick <= plan.at + PLAN_OVER * this.ai.session.tickRate ? plan : void 0;
|
|
162
|
+
}
|
|
163
|
+
/** Proposes an attack together: a target, the waves to go `gatherFor` seconds from now. Joined by the proposer */
|
|
164
|
+
propose(target) {
|
|
165
|
+
const { ai } = this;
|
|
166
|
+
const plan = {
|
|
167
|
+
target: point(target),
|
|
168
|
+
at: ai.tick + Math.round((this.options.gatherFor ?? 20) * ai.session.tickRate),
|
|
169
|
+
by: ai.playerId,
|
|
170
|
+
joined: [ai.playerId],
|
|
171
|
+
declined: [],
|
|
172
|
+
since: ai.tick
|
|
173
|
+
};
|
|
174
|
+
this.board.plan = plan;
|
|
175
|
+
ai.decide(`proposes an attack together on ${where(target)} in ${this.options.gatherFor ?? 20} s`, { kind: "team" });
|
|
176
|
+
return plan;
|
|
177
|
+
}
|
|
178
|
+
/** Joins the plan standing: its wave goes with the others' */
|
|
179
|
+
join() {
|
|
180
|
+
const plan = this.plan;
|
|
181
|
+
if (!plan || plan.joined.includes(this.ai.playerId)) return;
|
|
182
|
+
plan.joined.push(this.ai.playerId);
|
|
183
|
+
plan.declined = plan.declined.filter((each) => each !== this.ai.playerId);
|
|
184
|
+
this.ai.decide(`joins player ${plan.by}'s attack on ${where(plan.target)}`, { kind: "team" });
|
|
185
|
+
}
|
|
186
|
+
/** Says no to the plan standing: its wave goes on its own time */
|
|
187
|
+
decline() {
|
|
188
|
+
const plan = this.plan;
|
|
189
|
+
if (!plan || plan.declined.includes(this.ai.playerId) || plan.joined.includes(this.ai.playerId)) return;
|
|
190
|
+
plan.declined.push(this.ai.playerId);
|
|
191
|
+
this.ai.decide(`declines player ${plan.by}'s attack on ${where(plan.target)}: its wave is not ready`, { kind: "team" });
|
|
192
|
+
}
|
|
193
|
+
/** Says a line of the game's to its side (`say`, `lines`), no more than once in ten seconds a line */
|
|
194
|
+
say(line) {
|
|
195
|
+
const { ai } = this;
|
|
196
|
+
const options = this.options;
|
|
197
|
+
const text = options.lines?.[line];
|
|
198
|
+
if (!this.enabled || !options.say || !text) return;
|
|
199
|
+
const last = this.memory.said[line];
|
|
200
|
+
if (last !== void 0 && ai.tick - last < 10 * ai.session.tickRate) return;
|
|
201
|
+
this.memory.said[line] = ai.tick;
|
|
202
|
+
ai.send({
|
|
203
|
+
type: "chat",
|
|
204
|
+
text,
|
|
205
|
+
to: "allies"
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* The think, once a think: the board brought up to date (what is over dropped, itself and what it knows written),
|
|
210
|
+
* the people heard (pings, damage to allies), its own raids asked help for, the plan answered
|
|
211
|
+
*/
|
|
212
|
+
think() {
|
|
213
|
+
const { ai, board } = this;
|
|
214
|
+
const tick = ai.tick;
|
|
215
|
+
board.requests = board.requests.filter((each) => each.until > tick);
|
|
216
|
+
if (board.plan && tick > board.plan.at + PLAN_OVER * ai.session.tickRate) delete board.plan;
|
|
217
|
+
if (ai.def.knowledge !== false) board.known[ai.playerId] = {
|
|
218
|
+
tick,
|
|
219
|
+
bases: ai.knowledge.enemy.bases().filter((base) => !base.gone).map((base) => ({
|
|
220
|
+
owner: base.owner,
|
|
221
|
+
at: point(base.at),
|
|
222
|
+
last: base.last
|
|
223
|
+
}))
|
|
224
|
+
};
|
|
225
|
+
else board.known[ai.playerId] = {
|
|
226
|
+
tick,
|
|
227
|
+
bases: []
|
|
228
|
+
};
|
|
229
|
+
const heardFrom = this.memory.heard;
|
|
230
|
+
this.memory.heard = tick;
|
|
231
|
+
if (ai.def.knowledge !== false && heardFrom >= 0) this.hear(heardFrom);
|
|
232
|
+
if (this.options.answerPings ?? true) this.fallBack();
|
|
233
|
+
if ((this.options.askForHelp ?? true) && ai.area(Defence).enabled) for (const raid of ai.area(Defence).raids()) {
|
|
234
|
+
if (raid.strength * ai.area(Defence).margin <= this.homeStrength()) continue;
|
|
235
|
+
this.request("help", raid.base.at, raid.strength, "raid");
|
|
236
|
+
}
|
|
237
|
+
const plan = this.plan;
|
|
238
|
+
if (plan && plan.by !== ai.playerId && !plan.joined.includes(ai.playerId) && plan.since < heardFrom) this.decline();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* An ally's ping to fall back (`rally`), not answered yet: its squads out (waves, raids, harassers, a push; not what
|
|
242
|
+
* defends, helps or looks) come home, and it says so. What that ally pinged to push or hold before is not done any
|
|
243
|
+
* more (`pinged`): the latest ping of a person's is what it asks
|
|
244
|
+
*/
|
|
245
|
+
fallBack() {
|
|
246
|
+
const { ai } = this;
|
|
247
|
+
const home = ai.view.home();
|
|
248
|
+
if (!home) return;
|
|
249
|
+
for (const request of this.requests("rally")) {
|
|
250
|
+
if (request.by !== "ping" || request.from === ai.playerId || request.answered.includes(ai.playerId)) continue;
|
|
251
|
+
request.answered.push(ai.playerId);
|
|
252
|
+
const out = ai.squads.all().squads.filter((squad) => squad.alive && squad.length && (![
|
|
253
|
+
"defend",
|
|
254
|
+
"help",
|
|
255
|
+
"pinged",
|
|
256
|
+
"scout"
|
|
257
|
+
].includes(squad.owner ?? "") || squad.name === PING_SQUADS.attack) && squad.current?.kind !== "retreat");
|
|
258
|
+
for (const squad of out) squad.retreat(home, `player ${request.from} asks to fall back`);
|
|
259
|
+
ai.decide(`falls back home at player ${request.from}'s ping: ${out.length ? out.map((squad) => squad.name).join(", ") : "nothing out"}`, { kind: "team" });
|
|
260
|
+
if (out.length) this.say("retreating");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The ping of an ally's it does now: the latest standing `attack` or `defend` of another's, in reach of home, and
|
|
265
|
+
* not before a `rally` of theirs since (a retreat asked after a push is what they want now)
|
|
266
|
+
*/
|
|
267
|
+
pinged() {
|
|
268
|
+
const { ai } = this;
|
|
269
|
+
return ai.cache("team.pinged", () => {
|
|
270
|
+
const home = ai.view.home();
|
|
271
|
+
if (!home) return void 0;
|
|
272
|
+
const rallies = this.requests("rally").filter((each) => each.by === "ping");
|
|
273
|
+
const candidates = [...this.requests("attack"), ...this.requests("defend")].filter((each) => each.by === "ping" && each.from !== ai.playerId && distSq(each.at, home) <= 6400 && !rallies.some((rally) => rally.from === each.from && rally.id > each.id));
|
|
274
|
+
candidates.sort((a, b) => b.id - a.id);
|
|
275
|
+
return candidates[0];
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The goal that does what an ally's ping asks: a squad to fight there (`push`), or to hold the place (`hold`). One at
|
|
280
|
+
* a time: a later ping takes the units of the one before
|
|
281
|
+
*/
|
|
282
|
+
makePingGoal() {
|
|
283
|
+
const sent = (available, request) => this.helpers(available, {
|
|
284
|
+
at: request.at,
|
|
285
|
+
strength: this.seenAt(request.at)
|
|
286
|
+
});
|
|
287
|
+
return defineGoal({
|
|
288
|
+
id: PINGED,
|
|
289
|
+
weight: .75,
|
|
290
|
+
considerations: [consider("an ally pings to push or hold", () => this.pinged() ? 1 : 0, curve.step(1)), consider("enough to send", (ai) => {
|
|
291
|
+
const request = this.pinged();
|
|
292
|
+
return request ? sent(ai.goals.pool(), request).length : 0;
|
|
293
|
+
}, curve.step(1))],
|
|
294
|
+
claims: { units: (_ai, available) => {
|
|
295
|
+
const request = this.pinged();
|
|
296
|
+
return request ? sent(available, request) : [];
|
|
297
|
+
} },
|
|
298
|
+
commitment: 10,
|
|
299
|
+
run: (ai, claimed) => {
|
|
300
|
+
const request = this.pinged();
|
|
301
|
+
if (!request || request.kind !== "attack" && request.kind !== "defend") return;
|
|
302
|
+
const name = PING_SQUADS[request.kind];
|
|
303
|
+
const there = ai.squads.named(name);
|
|
304
|
+
const at = there?.current?.data.at;
|
|
305
|
+
if (there && at && distSq(at, request.at) <= 256 && there.done === void 0) return;
|
|
306
|
+
const squad = claimed.squad(name, claimed.units);
|
|
307
|
+
if (request.kind === "attack") squad.attack(request.at);
|
|
308
|
+
else squad.defend(request.at, SEEN_NEAR);
|
|
309
|
+
if (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId);
|
|
310
|
+
ai.decide(`${request.kind === "attack" ? "pushes" : "holds"} at ${where(request.at)} with ${claimed.units.length}, at player ${request.from}'s ping`, {
|
|
311
|
+
kind: "team",
|
|
312
|
+
goal: PINGED
|
|
313
|
+
});
|
|
314
|
+
if (request.kind === "attack") this.say("attacking");
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
/** Its fighters at home nothing holds: what it meets a raid with before it asks */
|
|
319
|
+
homeStrength() {
|
|
320
|
+
const { ai } = this;
|
|
321
|
+
return ai.goals.pool().fighters().strength();
|
|
322
|
+
}
|
|
323
|
+
/** What was heard since the last think: the people's pings at a place, damage done to an ally where it was seen */
|
|
324
|
+
hear(since) {
|
|
325
|
+
const { ai } = this;
|
|
326
|
+
const { view } = ai;
|
|
327
|
+
const ally = (player) => player !== ai.playerId && view.player(player)?.relation === "ally";
|
|
328
|
+
for (const ping of ai.knowledge.events.pings()) {
|
|
329
|
+
if (ping.tick <= since || !ally(ping.player)) continue;
|
|
330
|
+
const meaning = ai.session.registry.settings.talk.pings.meanings?.[ping.kind];
|
|
331
|
+
if (meaning && meaning !== "ignore") this.request(meaning, ping.at, meaning === "help" ? this.seenAt(ping.at) : 0, "ping", ping.player);
|
|
332
|
+
else ai.decide(`hears player ${ping.player}'s ${ping.kind} at ${where(ping.at)}`, { kind: "team" });
|
|
333
|
+
}
|
|
334
|
+
for (const hit of ai.knowledge.events.damage()) {
|
|
335
|
+
if (hit.tick <= since || !ally(hit.owner)) continue;
|
|
336
|
+
const strength = this.seenAt(hit.at);
|
|
337
|
+
if (strength > 0) this.request("help", hit.at, strength, "damage", hit.owner);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/** The strength of the enemies in sight near a place */
|
|
341
|
+
seenAt(at) {
|
|
342
|
+
return this.ai.view.enemies.units().alive().near(at, SEEN_NEAR).strength();
|
|
343
|
+
}
|
|
344
|
+
/** The request it would answer now: the strongest standing of another, in reach of home, it can send enough to */
|
|
345
|
+
calling() {
|
|
346
|
+
const { ai } = this;
|
|
347
|
+
return ai.cache("team.calling", () => {
|
|
348
|
+
const home = ai.view.home();
|
|
349
|
+
if (!home) return void 0;
|
|
350
|
+
const candidates = this.requests("help").filter((each) => each.from !== ai.playerId && distSq(each.at, home) <= 6400);
|
|
351
|
+
candidates.sort((a, b) => b.strength - a.strength || a.id - b.id);
|
|
352
|
+
return candidates[0];
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
/** How much stronger than a call what is sent to it is: from the odds asked, by the square law (one in two: as strong) */
|
|
356
|
+
get margin() {
|
|
357
|
+
const odds = Math.min(.95, Math.max(.05, this.options.helpOdds ?? .5));
|
|
358
|
+
return Math.sqrt(odds / (1 - odds));
|
|
359
|
+
}
|
|
360
|
+
/** Who it sends to a call: its idle fighters nothing holds, the nearest first, as many as make the odds asked */
|
|
361
|
+
helpers(available, request) {
|
|
362
|
+
const { ai } = this;
|
|
363
|
+
const need = request.strength * this.margin;
|
|
364
|
+
const idle = available.fighters().idle().items.slice().sort((a, b) => distSq(a, request.at) - distSq(b, request.at) || a.id - b.id);
|
|
365
|
+
const chosen = [];
|
|
366
|
+
let got = 0;
|
|
367
|
+
for (const unit of idle) {
|
|
368
|
+
if (request.strength > 0 ? got >= need : chosen.length >= HELP_UNSEEN) break;
|
|
369
|
+
chosen.push(unit);
|
|
370
|
+
got += ai.view.strength.of(unit);
|
|
371
|
+
}
|
|
372
|
+
if (request.strength > 0 && got < need) return available.where(() => false);
|
|
373
|
+
return available.where((unit) => chosen.includes(unit));
|
|
374
|
+
}
|
|
375
|
+
/** The help goal: a call of an ally's standing, and enough to send to it */
|
|
376
|
+
makeGoal() {
|
|
377
|
+
return defineGoal({
|
|
378
|
+
id: HELP,
|
|
379
|
+
weight: .7,
|
|
380
|
+
considerations: [consider("an ally calls for help", () => this.calling() ? 1 : 0, curve.step(1)), consider("enough to send", (ai) => {
|
|
381
|
+
const request = this.calling();
|
|
382
|
+
return request ? this.helpers(ai.goals.pool(), request).length : 0;
|
|
383
|
+
}, curve.step(1))],
|
|
384
|
+
claims: { units: (_ai, available) => {
|
|
385
|
+
const request = this.calling();
|
|
386
|
+
return request ? this.helpers(available, request) : [];
|
|
387
|
+
} },
|
|
388
|
+
commitment: 10,
|
|
389
|
+
run: (ai, claimed) => {
|
|
390
|
+
const request = this.calling();
|
|
391
|
+
if (!request) return;
|
|
392
|
+
const squad = ai.squads.named("help");
|
|
393
|
+
const at = squad?.current?.data.at;
|
|
394
|
+
if (squad && at && distSq(at, request.at) <= 256 && squad.done === void 0) {
|
|
395
|
+
const more = this.helpers(ai.goals.pool(), {
|
|
396
|
+
...request,
|
|
397
|
+
strength: Math.max(0, request.strength * this.margin - squad.strength()) / this.margin
|
|
398
|
+
});
|
|
399
|
+
if (request.strength > 0 && more.length) squad.add(more, "more seen there");
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
claimed.squad("help", claimed.units).defend(request.at, SEEN_NEAR);
|
|
403
|
+
if (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId);
|
|
404
|
+
ai.decide(`answers player ${request.from}'s call for help at ${where(request.at)} with ${claimed.units.length}`, {
|
|
405
|
+
kind: "team",
|
|
406
|
+
goal: HELP
|
|
407
|
+
});
|
|
408
|
+
this.say("helping");
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
/** Team play as the report shows it */
|
|
413
|
+
report() {
|
|
414
|
+
const { ai } = this;
|
|
415
|
+
const tickRate = ai.session.tickRate;
|
|
416
|
+
const plan = this.plan;
|
|
417
|
+
return {
|
|
418
|
+
team: this.team,
|
|
419
|
+
computers: this.computers(),
|
|
420
|
+
requests: this.requests().map((each) => ({
|
|
421
|
+
id: each.id,
|
|
422
|
+
kind: each.kind,
|
|
423
|
+
from: each.from,
|
|
424
|
+
at: pair(each.at),
|
|
425
|
+
strength: Math.round(each.strength),
|
|
426
|
+
by: each.by,
|
|
427
|
+
answered: [...each.answered],
|
|
428
|
+
left: Math.max(0, Math.round((each.until - ai.tick) / tickRate))
|
|
429
|
+
})),
|
|
430
|
+
...plan && { plan: {
|
|
431
|
+
target: pair(plan.target),
|
|
432
|
+
in: Math.round((plan.at - ai.tick) / tickRate),
|
|
433
|
+
by: plan.by,
|
|
434
|
+
joined: [...plan.joined],
|
|
435
|
+
declined: [...plan.declined]
|
|
436
|
+
} },
|
|
437
|
+
enemyBases: this.enemyBases().length
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
/** What it remembers, for a save: a copy (the board is the world's, saved with it) */
|
|
441
|
+
/** Whether it has anything to remember now: one that does not is left out of a save */
|
|
442
|
+
remembers() {
|
|
443
|
+
return this.enabled;
|
|
444
|
+
}
|
|
445
|
+
/** Its part of the brain's report */
|
|
446
|
+
reportTo(report) {
|
|
447
|
+
if (this.enabled) report.team = this.report();
|
|
448
|
+
}
|
|
449
|
+
/** Gives a copy of the team play's memory, for a save of the brain */
|
|
450
|
+
save() {
|
|
451
|
+
return {
|
|
452
|
+
v: 1,
|
|
453
|
+
heard: this.memory.heard,
|
|
454
|
+
said: { ...this.memory.said }
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
/** Takes back what `save` gave: whether it was read */
|
|
458
|
+
restore(memory) {
|
|
459
|
+
const given = memory;
|
|
460
|
+
if (!given || typeof given !== "object" || given.v !== 1) return false;
|
|
461
|
+
this.memory = {
|
|
462
|
+
v: 1,
|
|
463
|
+
heard: given.heard ?? -1,
|
|
464
|
+
said: { ...given.said ?? {} }
|
|
465
|
+
};
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
/**
|
|
470
|
+
* The team module: the team's board brought up to date each think (`ai.team.think`: itself and what it knows written,
|
|
471
|
+
* pings and an ally's damage heard as calls for help, its own raids asked help for, the plan of an attack together
|
|
472
|
+
* answered), and the `help` goal on the picker. With how it plays where the brain's definition and the seat's options
|
|
473
|
+
* say nothing (`TeamOptions`)
|
|
474
|
+
*
|
|
475
|
+
* @beta
|
|
476
|
+
*/
|
|
477
|
+
var team = (options = {}) => defineModule({
|
|
478
|
+
id: "team",
|
|
479
|
+
make: (ai) => {
|
|
480
|
+
ai.area(Team).configure(options);
|
|
481
|
+
return {
|
|
482
|
+
id: "team",
|
|
483
|
+
phase: "sense",
|
|
484
|
+
after: ["defence"],
|
|
485
|
+
think: () => ai.area(Team).think()
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
//#endregion
|
|
490
|
+
export { HELP, PINGED, Team, emptyTeam, team };
|
|
491
|
+
|
|
492
|
+
//# sourceMappingURL=team.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","names":[],"sources":["../../src/ai/team.ts"],"sourcesContent":["import type { PlayerId } from '#engine/entity'\nimport { DEFEND, Defence } from './defence'\nimport type { AiArea } from './area'\nimport type { AiReport } from './report'\nimport { distSq, type Vec2 } from '#engine/math'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { consider, curve, defineGoal, type GoalDef } from './goals'\nimport type { UnitSet } from './view'\nimport { pair, point, where } from './geometry'\n\n/*\n * Team play (AI plan, C5): computers that play on one side as one side. Before this, a computer ally neither helped\n * nor answered: a person's ping went unheard, an ally's hall burned in plain sight, two computers of a team sent their\n * waves a minute apart and lost them one after the other. This is the word between them, and with the people on\n * their side:\n *\n * - **The team's board** (`TeamBoard`): one per team, shared by the team's computers, kept in the world as a state\n * of its own (`core.ai.teams`) so that a save keeps it. It is never replicated: no player, human or computer, gets\n * it in a snapshot, and only the debug panel's AI tab shows it (through the report). Pooling what the computers of a\n * team know is fair by construction: sight is per team already, so the board holds nothing a human ally could not\n * see. Each computer writes to it through its brain (`ai.team`) as it thinks, in the seats' order, which is the same\n * every game.\n * - **Requests** (`request`): `help` at a place, with the strength seen there, for so long. A computer posts one when a\n * raid on it is more than it can meet at home; it hears a person's ping as one (`danger` and `assist` at a place: help\n * there; `look` and `onMyWay` noted); and damage it sees done to an ally's units or buildings is one, sized by the\n * enemies seen there. The `help` goal (`defendUsers`, the classic Defend Users) weighs a request against what it can\n * send (`helpOdds`): it sends a squad of its idle fighters, as many as make the odds, and never its last defence.\n * - **Attacking together** (`together`): the first computer of the team whose wave is ready proposes a target and a\n * time a little ahead (`gatherFor`); the others join by their next think if their wave is ready, or decline; at the\n * time every computer that joined sends its wave to the target. Who proposes first follows the seats' think offsets,\n * the same every game: the lowest seat often leads, which is fine.\n * - **What they know of the enemy, pooled** (`enemyBases`): each computer puts the bases it remembers on the board;\n * any computer of the team reads them all.\n * - **Saying things** (`say`, off by default): a line of chat to its side as it sends a wave, comes to help, falls\n * back. The lines are the game's (`lines`): the kit never puts words in a game.\n */\n\n/**\n * Something one computer of a team asks of the others, on the team's board: help at a place\n *\n * @beta\n */\nexport interface TeamRequest {\n\t/** Its number on the board */\n\tid: number\n\t/** What is asked: help, an attack, a defence or a rally */\n\tkind: 'help' | 'attack' | 'defend' | 'rally'\n\t/** Who asks: a computer of the team, or a person whose ping or plight it is */\n\tfrom: PlayerId\n\t/** Where the help is asked, in cells */\n\tat: Vec2\n\t/** The enemy strength seen there as it was asked (0 for none seen: a ping on a place) */\n\tstrength: number\n\t/** The tick it is asked until */\n\tuntil: number\n\t/** What it came of: a raid on a computer, a person's ping, damage seen done to an ally, a word of the game's */\n\tby: 'raid' | 'ping' | 'damage' | 'word'\n\t/** The computers that answered it */\n\tanswered: PlayerId[]\n}\n\n/**\n * An attack the computers of a team agree on (`together`): where, when, who proposed it, who joined and who did not\n *\n * @beta\n */\nexport interface AttackPlan {\n\t/** Where the attack goes, in cells */\n\ttarget: Vec2\n\t/** The tick the waves go at */\n\tat: number\n\t/** The player who proposed the attack */\n\tby: PlayerId\n\t/** The computers that joined the attack */\n\tjoined: PlayerId[]\n\t/** The computers that declined it */\n\tdeclined: PlayerId[]\n\t/** The tick it was proposed at */\n\tsince: number\n}\n\n/**\n * A team's board as the world keeps it (`core.ai.teams`, by team): plain data, kept in a save, never replicated\n *\n * @beta\n */\nexport interface TeamBoard {\n\t/** The version of the board's format: 1 so far */\n\tv: 1\n\t/** The requests on the board */\n\trequests: TeamRequest[]\n\t/** The attack the computers agreed on; nothing when there is none */\n\tplan?: AttackPlan\n\t/** What each computer of the team remembers of the enemy's bases, and when it last thought */\n\tknown: Record<string, { tick: number; bases: { owner: PlayerId; at: Vec2; last: number }[] }>\n\t/** The next request's number */\n\tnext: number\n}\n\n/**\n * How a brain plays with its team (`BrainDef.team`, the seat's `AiOptions.team` over it, the `team()` module's own\n * under both). Data\n *\n * @beta\n */\nexport interface TeamOptions {\n\t/** Whether it helps its allies, people and computers, where asked (the classic Defend Users): yes when left out */\n\tdefendUsers?: boolean\n\t/**\n\t * Whether it does what an ally's ping asks besides help (`RuleSettings.talk.pings.meanings`): a squad sent to fight at\n\t * an `attack` (a push), one to hold a place at a `defend` (a hold), its squads out brought home at a `rally` (a\n\t * retreat). Yes when left out\n\t */\n\tanswerPings?: boolean\n\t/** The odds of the fight (`Strength.odds`) what it sends to help is to have: one in two when left out */\n\thelpOdds?: number\n\t/** Whether it asks its team for help with a raid more than it can meet: yes when left out */\n\taskForHelp?: boolean\n\t/** Whether its waves wait for the team's plan and go together: no when left out */\n\ttogether?: boolean\n\t/** Seconds ahead of the proposal the waves of a plan go: 20 when left out */\n\tgatherFor?: number\n\t/** Seconds a request stands: 30 when left out */\n\trequestFor?: number\n\t/** Whether it says a line to its side as it sends a wave, comes to help, falls back: no when left out */\n\tsay?: boolean\n\t/** Its lines, the game's words: `{ attacking, helping, retreating }`. Nothing is said for a line not given */\n\tlines?: Partial<Record<'attacking' | 'helping' | 'retreating', string>>\n}\n\n/**\n * What a brain remembers of its team play between thinks (`BrainMemory.team`): up to when it heard, when it last said\n * each line\n *\n * @beta\n */\nexport interface TeamPlayMemory {\n\t/** The version of the memory's format: 1 so far */\n\tv: 1\n\t/** Up to which board request, by number, it heard */\n\theard: number\n\t/** When it last said each line, by line */\n\tsaid: Record<string, number>\n}\n\n/**\n * Team play as the report shows it (`AiReport.team`): the team, its computers, the requests on its board, the plan of\n * an attack together, how many enemy bases the team knows\n *\n * @beta\n */\nexport interface TeamReport {\n\t/** The team's number */\n\tteam: number\n\t/** The computer players of the team */\n\tcomputers: PlayerId[]\n\t/** The requests on the board, each with its number, kind, who asked, where, strength, source, who answered and how long is left */\n\trequests: {\n\t\tid: number\n\t\tkind: TeamRequest['kind']\n\t\tfrom: PlayerId\n\t\tat: [number, number]\n\t\tstrength: number\n\t\tby: TeamRequest['by']\n\t\tanswered: PlayerId[]\n\t\tleft: number\n\t}[]\n\t/** The attack together, with its target, how many seconds off it is, who proposed it, who joined and who declined */\n\tplan?: { target: [number, number]; in: number; by: PlayerId; joined: PlayerId[]; declined: PlayerId[] }\n\t/** How many enemy bases the team knows */\n\tenemyBases: number\n}\n\n/** How near two requests of one asker are to be one */\nconst SAME_PLACE = 16\n/** How near the place of a request the enemies seen there are counted in its strength */\nconst SEEN_NEAR = 16\n/** How far a computer's fighters go to help: further is across the map */\nconst HELP_REACH = 80\n/** The most units sent to a call with no enemy seen there: enough to look and to hold a little */\nconst HELP_UNSEEN = 3\n/** Seconds a plan waits past its time for the waves of those that joined, before it is over */\nconst PLAN_OVER = 30\n/**\n * The id of the help goal\n *\n * @beta\n */\nexport const HELP = 'help'\n\n/**\n * The id of the goal that does what an ally's ping asks (`push`, `hold`): `pinged`\n *\n * @beta\n */\nexport const PINGED = 'pinged'\n/** What is sent at a ping, by what it asks: the squad's name */\nconst PING_SQUADS = { attack: 'push', defend: 'hold' } as const\n\n/**\n * An empty board\n *\n * @internal\n */\nexport const emptyTeam = (): TeamBoard => ({ v: 1, requests: [], known: {}, next: 1 })\n\n/**\n * A brain's team play (`ai.team`): the team's board (`board`: requests, the plan of an attack together, what each\n * computer knows), the `help` goal, and what it says. The board is the world's (`core.ai.teams`) where the seat hands\n * it over (`BrainContext.team`), else its own: a brain made by hand plays alone\n *\n * @internal\n */\nexport class Team implements AiArea {\n\t/** What finds it on a brain (`ai.area(Team)`): made the first time a module asks for it */\n\tstatic readonly id = 'team'\n\t/** Makes the team play of a brain; what `ai.area(Team)` calls the first time a module asks for it */\n\tstatic make(ai: Brain): Team {\n\t\treturn new Team(ai, ai.teamBoard)\n\t}\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'team'\n\t/** What the log says where a save's memory of it is of a shape it does not read */\n\treadonly afresh = 'the save remembers the computer player’s team play in a shape this brain does not read: it starts afresh'\n\n\t/** Whether a `team()` module is in the brain */\n\tenabled = false\n\tprivate memory: TeamPlayMemory = { v: 1, heard: -1, said: {} }\n\tprivate moduleOptions: TeamOptions = {}\n\tprivate own: TeamBoard = emptyTeam()\n\t/** The help goal: added to the brain's picker by the module, where it defends users */\n\treadonly goal: GoalDef\n\t/** The goal that does what an ally's ping asks (`answerPings`): added with the help goal */\n\treadonly pingGoal: GoalDef\n\n\tconstructor(\n\t\t/** The brain it plays for */\n\t\treadonly ai: Brain,\n\t\t/** The team's board, as the seat hands it over: the world's, read anew each time (a load replaces it) */\n\t\tprivate readonly shared?: () => TeamBoard\n\t) {\n\t\tthis.goal = this.makeGoal()\n\t\tthis.pingGoal = this.makePingGoal()\n\t}\n\n\t/** Puts the `team()` module's options under the brain's settings, and the help goal on the picker */\n\tconfigure(options: TeamOptions): void {\n\t\tthis.moduleOptions = options\n\t\tif (!this.enabled && (this.options.defendUsers ?? true)) this.ai.goals.add(this.goal)\n\t\tif (!this.enabled && (this.options.answerPings ?? true)) this.ai.goals.add(this.pingGoal)\n\t\tthis.enabled = true\n\t}\n\n\t/** How it plays with its team: the module's options, the brain's settings over them (`ai.settings.team`) */\n\tget options(): TeamOptions {\n\t\treturn this.ai.cache('team.options', () => ({ ...this.moduleOptions, ...this.ai.settings.team }))\n\t}\n\n\t/** Whether its waves wait for the team's plan (`together`) */\n\tget together(): boolean {\n\t\treturn this.enabled && !!this.options.together\n\t}\n\n\t/** The team's board: the world's, shared by the team's computers, or its own where the seat gave none */\n\tget board(): TeamBoard {\n\t\treturn this.shared?.() ?? this.own\n\t}\n\n\t/** Its team's number */\n\tget team(): number {\n\t\treturn this.ai.view.me.team\n\t}\n\n\t/** The computers of its team, as seen on the board lately (each writes itself as it thinks), itself among them */\n\tcomputers(): PlayerId[] {\n\t\tconst { board, ai } = this\n\t\tconst recent = ai.tick - 10 * ai.session.tickRate\n\t\treturn Object.entries(board.known)\n\t\t\t.filter(([, known]) => known.tick >= recent)\n\t\t\t.map(([id]) => Number(id))\n\t\t\t.sort((a, b) => a - b)\n\t}\n\n\t/** The requests on the board, those of a kind where given: those still standing */\n\trequests(kind?: TeamRequest['kind']): TeamRequest[] {\n\t\tconst { tick } = this.ai\n\t\treturn this.board.requests.filter((each) => each.until > tick && (kind === undefined || each.kind === kind))\n\t}\n\n\t/**\n\t * Asks the team for something at a place: a request on the board, or the one of the same asker, kind and place made\n\t * to stand longer, with the strength seen now. Gives back the request\n\t */\n\trequest(\n\t\tkind: TeamRequest['kind'],\n\t\tat: Vec2,\n\t\tstrength: number,\n\t\tby: TeamRequest['by'],\n\t\tfrom: PlayerId = this.ai.playerId,\n\t\tseconds?: number\n\t): TeamRequest {\n\t\tconst { ai, board } = this\n\t\tconst until = ai.tick + Math.round((seconds ?? this.options.requestFor ?? 30) * ai.session.tickRate)\n\t\tconst same = board.requests.find(\n\t\t\t(each) => each.from === from && each.kind === kind && each.until > ai.tick && distSq(each.at, at) <= SAME_PLACE * SAME_PLACE\n\t\t)\n\t\tif (same) {\n\t\t\tsame.until = Math.max(same.until, until)\n\t\t\tsame.strength = Math.max(same.strength, strength)\n\t\t\treturn same\n\t\t}\n\t\tconst request: TeamRequest = { id: board.next++, kind, from, at: point(at), strength, until, by, answered: [] }\n\t\tboard.requests.push(request)\n\t\tai.decide(`asks for ${kind} at ${where(at)}${from === ai.playerId ? '' : ` for player ${from}`} (${by}, strength ${Math.round(strength)})`, {\n\t\t\tkind: 'team'\n\t\t})\n\t\treturn request\n\t}\n\n\t/** The enemy's bases the team knows, every computer's put together: one a place, the latest seen */\n\tenemyBases(): { owner: PlayerId; at: Vec2; last: number }[] {\n\t\tconst merged: { owner: PlayerId; at: Vec2; last: number }[] = []\n\t\tconst known = this.board.known\n\t\tfor (const id of Object.keys(known).sort((a, b) => Number(a) - Number(b))) {\n\t\t\tfor (const base of known[id].bases) {\n\t\t\t\tconst same = merged.find((each) => each.owner === base.owner && distSq(each.at, base.at) < SAME_PLACE * SAME_PLACE)\n\t\t\t\tif (same) same.last = Math.max(same.last, base.last)\n\t\t\t\telse merged.push({ ...base, at: point(base.at) })\n\t\t\t}\n\t\t}\n\t\treturn merged\n\t}\n\n\t/** The plan of an attack together, while it stands */\n\tget plan(): AttackPlan | undefined {\n\t\tconst plan = this.board.plan\n\t\treturn plan && this.ai.tick <= plan.at + PLAN_OVER * this.ai.session.tickRate ? plan : undefined\n\t}\n\n\t/** Proposes an attack together: a target, the waves to go `gatherFor` seconds from now. Joined by the proposer */\n\tpropose(target: Vec2): AttackPlan {\n\t\tconst { ai } = this\n\t\tconst plan: AttackPlan = {\n\t\t\ttarget: point(target),\n\t\t\tat: ai.tick + Math.round((this.options.gatherFor ?? 20) * ai.session.tickRate),\n\t\t\tby: ai.playerId,\n\t\t\tjoined: [ai.playerId],\n\t\t\tdeclined: [],\n\t\t\tsince: ai.tick\n\t\t}\n\t\tthis.board.plan = plan\n\t\tai.decide(`proposes an attack together on ${where(target)} in ${this.options.gatherFor ?? 20} s`, { kind: 'team' })\n\t\treturn plan\n\t}\n\n\t/** Joins the plan standing: its wave goes with the others' */\n\tjoin(): void {\n\t\tconst plan = this.plan\n\t\tif (!plan || plan.joined.includes(this.ai.playerId)) return\n\t\tplan.joined.push(this.ai.playerId)\n\t\tplan.declined = plan.declined.filter((each) => each !== this.ai.playerId)\n\t\tthis.ai.decide(`joins player ${plan.by}'s attack on ${where(plan.target)}`, { kind: 'team' })\n\t}\n\n\t/** Says no to the plan standing: its wave goes on its own time */\n\tdecline(): void {\n\t\tconst plan = this.plan\n\t\tif (!plan || plan.declined.includes(this.ai.playerId) || plan.joined.includes(this.ai.playerId)) return\n\t\tplan.declined.push(this.ai.playerId)\n\t\tthis.ai.decide(`declines player ${plan.by}'s attack on ${where(plan.target)}: its wave is not ready`, { kind: 'team' })\n\t}\n\n\t/** Says a line of the game's to its side (`say`, `lines`), no more than once in ten seconds a line */\n\tsay(line: 'attacking' | 'helping' | 'retreating'): void {\n\t\tconst { ai } = this\n\t\tconst options = this.options\n\t\tconst text = options.lines?.[line]\n\t\tif (!this.enabled || !options.say || !text) return\n\t\tconst last = this.memory.said[line]\n\t\tif (last !== undefined && ai.tick - last < 10 * ai.session.tickRate) return\n\t\tthis.memory.said[line] = ai.tick\n\t\tai.send({ type: 'chat', text, to: 'allies' })\n\t}\n\n\t/**\n\t * The think, once a think: the board brought up to date (what is over dropped, itself and what it knows written),\n\t * the people heard (pings, damage to allies), its own raids asked help for, the plan answered\n\t */\n\tthink(): void {\n\t\tconst { ai, board } = this\n\t\tconst tick = ai.tick\n\t\tboard.requests = board.requests.filter((each) => each.until > tick)\n\t\tif (board.plan && tick > board.plan.at + PLAN_OVER * ai.session.tickRate) delete board.plan\n\t\tif (ai.def.knowledge !== false) {\n\t\t\tboard.known[ai.playerId] = {\n\t\t\t\ttick,\n\t\t\t\tbases: ai.knowledge.enemy\n\t\t\t\t\t.bases()\n\t\t\t\t\t.filter((base) => !base.gone)\n\t\t\t\t\t.map((base) => ({ owner: base.owner, at: point(base.at), last: base.last }))\n\t\t\t}\n\t\t} else board.known[ai.playerId] = { tick, bases: [] }\n\t\tconst heardFrom = this.memory.heard\n\t\tthis.memory.heard = tick\n\t\tif (ai.def.knowledge !== false && heardFrom >= 0) this.hear(heardFrom)\n\t\tif (this.options.answerPings ?? true) this.fallBack()\n\t\tif ((this.options.askForHelp ?? true) && ai.area(Defence).enabled) {\n\t\t\tfor (const raid of ai.area(Defence).raids()) {\n\t\t\t\tif (raid.strength * ai.area(Defence).margin <= this.homeStrength()) continue\n\t\t\t\tthis.request('help', raid.base.at, raid.strength, 'raid')\n\t\t\t}\n\t\t}\n\t\t// a plan of another's not joined by the think after it was proposed: declined\n\t\tconst plan = this.plan\n\t\tif (plan && plan.by !== ai.playerId && !plan.joined.includes(ai.playerId) && plan.since < heardFrom) this.decline()\n\t}\n\n\t/**\n\t * An ally's ping to fall back (`rally`), not answered yet: its squads out (waves, raids, harassers, a push; not what\n\t * defends, helps or looks) come home, and it says so. What that ally pinged to push or hold before is not done any\n\t * more (`pinged`): the latest ping of a person's is what it asks\n\t */\n\tprivate fallBack(): void {\n\t\tconst { ai } = this\n\t\tconst home = ai.view.home()\n\t\tif (!home) return\n\t\tfor (const request of this.requests('rally')) {\n\t\t\tif (request.by !== 'ping' || request.from === ai.playerId || request.answered.includes(ai.playerId)) continue\n\t\t\trequest.answered.push(ai.playerId)\n\t\t\tconst out = ai.squads\n\t\t\t\t.all()\n\t\t\t\t.squads.filter(\n\t\t\t\t\t(squad) =>\n\t\t\t\t\t\tsquad.alive &&\n\t\t\t\t\t\tsquad.length &&\n\t\t\t\t\t\t(![DEFEND, HELP, PINGED, 'scout'].includes(squad.owner ?? '') || squad.name === PING_SQUADS.attack) &&\n\t\t\t\t\t\tsquad.current?.kind !== 'retreat'\n\t\t\t\t)\n\t\t\tfor (const squad of out) squad.retreat(home, `player ${request.from} asks to fall back`)\n\t\t\tai.decide(`falls back home at player ${request.from}'s ping: ${out.length ? out.map((squad) => squad.name).join(', ') : 'nothing out'}`, {\n\t\t\t\tkind: 'team'\n\t\t\t})\n\t\t\tif (out.length) this.say('retreating')\n\t\t}\n\t}\n\n\t/**\n\t * The ping of an ally's it does now: the latest standing `attack` or `defend` of another's, in reach of home, and\n\t * not before a `rally` of theirs since (a retreat asked after a push is what they want now)\n\t */\n\tprivate pinged(): TeamRequest | undefined {\n\t\tconst { ai } = this\n\t\treturn ai.cache('team.pinged', () => {\n\t\t\tconst home = ai.view.home()\n\t\t\tif (!home) return undefined\n\t\t\tconst rallies = this.requests('rally').filter((each) => each.by === 'ping')\n\t\t\tconst candidates = [...this.requests('attack'), ...this.requests('defend')].filter(\n\t\t\t\t(each) =>\n\t\t\t\t\teach.by === 'ping' &&\n\t\t\t\t\teach.from !== ai.playerId &&\n\t\t\t\t\tdistSq(each.at, home) <= HELP_REACH * HELP_REACH &&\n\t\t\t\t\t!rallies.some((rally) => rally.from === each.from && rally.id > each.id)\n\t\t\t)\n\t\t\tcandidates.sort((a, b) => b.id - a.id)\n\t\t\treturn candidates[0]\n\t\t})\n\t}\n\n\t/**\n\t * The goal that does what an ally's ping asks: a squad to fight there (`push`), or to hold the place (`hold`). One at\n\t * a time: a later ping takes the units of the one before\n\t */\n\tprivate makePingGoal(): GoalDef {\n\t\tconst sent = (available: UnitSet, request: TeamRequest) => this.helpers(available, { at: request.at, strength: this.seenAt(request.at) })\n\t\treturn defineGoal({\n\t\t\tid: PINGED,\n\t\t\tweight: 0.75,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('an ally pings to push or hold', () => (this.pinged() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'enough to send',\n\t\t\t\t\t(ai) => {\n\t\t\t\t\t\tconst request = this.pinged()\n\t\t\t\t\t\treturn request ? sent(ai.goals.pool(), request).length : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t)\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst request = this.pinged()\n\t\t\t\t\treturn request ? sent(available, request) : []\n\t\t\t\t}\n\t\t\t},\n\t\t\tcommitment: 10,\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tconst request = this.pinged()\n\t\t\t\tif (!request || (request.kind !== 'attack' && request.kind !== 'defend')) return\n\t\t\t\tconst name = PING_SQUADS[request.kind]\n\t\t\t\t// sent there already: it goes on while the ping stands\n\t\t\t\tconst there = ai.squads.named(name)\n\t\t\t\tconst at = there?.current?.data.at as Vec2 | undefined\n\t\t\t\tif (there && at && distSq(at, request.at) <= SAME_PLACE * SAME_PLACE && there.done === undefined) return\n\t\t\t\tconst squad = claimed.squad(name, claimed.units)\n\t\t\t\tif (request.kind === 'attack') squad.attack(request.at)\n\t\t\t\telse squad.defend(request.at, SEEN_NEAR)\n\t\t\t\tif (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId)\n\t\t\t\tai.decide(\n\t\t\t\t\t`${request.kind === 'attack' ? 'pushes' : 'holds'} at ${where(request.at)} with ${claimed.units.length}, at player ${request.from}'s ping`,\n\t\t\t\t\t{ kind: 'team', goal: PINGED }\n\t\t\t\t)\n\t\t\t\tif (request.kind === 'attack') this.say('attacking')\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Its fighters at home nothing holds: what it meets a raid with before it asks */\n\tprivate homeStrength(): number {\n\t\tconst { ai } = this\n\t\treturn ai.goals.pool().fighters().strength()\n\t}\n\n\t/** What was heard since the last think: the people's pings at a place, damage done to an ally where it was seen */\n\tprivate hear(since: number): void {\n\t\tconst { ai } = this\n\t\tconst { view } = ai\n\t\tconst ally = (player: PlayerId) => player !== ai.playerId && view.player(player)?.relation === 'ally'\n\t\tfor (const ping of ai.knowledge.events.pings()) {\n\t\t\tif (ping.tick <= since || !ally(ping.player)) continue\n\t\t\t// what the kind asks, as the game's rules say (`RuleSettings.talk.pings.meanings`)\n\t\t\tconst meaning = ai.session.registry.settings.talk.pings.meanings?.[ping.kind]\n\t\t\tif (meaning && meaning !== 'ignore') this.request(meaning, ping.at, meaning === 'help' ? this.seenAt(ping.at) : 0, 'ping', ping.player)\n\t\t\telse ai.decide(`hears player ${ping.player}'s ${ping.kind} at ${where(ping.at)}`, { kind: 'team' })\n\t\t}\n\t\tfor (const hit of ai.knowledge.events.damage()) {\n\t\t\tif (hit.tick <= since || !ally(hit.owner)) continue\n\t\t\tconst strength = this.seenAt(hit.at)\n\t\t\tif (strength > 0) this.request('help', hit.at, strength, 'damage', hit.owner)\n\t\t}\n\t}\n\n\t/** The strength of the enemies in sight near a place */\n\tprivate seenAt(at: Vec2): number {\n\t\treturn this.ai.view.enemies.units().alive().near(at, SEEN_NEAR).strength()\n\t}\n\n\t/** The request it would answer now: the strongest standing of another, in reach of home, it can send enough to */\n\tprivate calling(): TeamRequest | undefined {\n\t\tconst { ai } = this\n\t\treturn ai.cache('team.calling', () => {\n\t\t\tconst home = ai.view.home()\n\t\t\tif (!home) return undefined\n\t\t\tconst candidates = this.requests('help').filter((each) => each.from !== ai.playerId && distSq(each.at, home) <= HELP_REACH * HELP_REACH)\n\t\t\tcandidates.sort((a, b) => b.strength - a.strength || a.id - b.id)\n\t\t\treturn candidates[0]\n\t\t})\n\t}\n\n\t/** How much stronger than a call what is sent to it is: from the odds asked, by the square law (one in two: as strong) */\n\tget margin(): number {\n\t\tconst odds = Math.min(0.95, Math.max(0.05, this.options.helpOdds ?? 0.5))\n\t\treturn Math.sqrt(odds / (1 - odds))\n\t}\n\n\t/** Who it sends to a call: its idle fighters nothing holds, the nearest first, as many as make the odds asked */\n\tprivate helpers(available: UnitSet, request: Pick<TeamRequest, 'strength' | 'at'>): UnitSet {\n\t\tconst { ai } = this\n\t\tconst need = request.strength * this.margin\n\t\tconst idle = available\n\t\t\t.fighters()\n\t\t\t.idle()\n\t\t\t.items.slice()\n\t\t\t.sort((a, b) => distSq(a, request.at) - distSq(b, request.at) || a.id - b.id)\n\t\tconst chosen: EntityState[] = []\n\t\tlet got = 0\n\t\tfor (const unit of idle) {\n\t\t\tif (request.strength > 0 ? got >= need : chosen.length >= HELP_UNSEEN) break\n\t\t\tchosen.push(unit)\n\t\t\tgot += ai.view.strength.of(unit)\n\t\t}\n\t\t// not enough to make the odds: none sent, rather than a few to their deaths\n\t\tif (request.strength > 0 && got < need) return available.where(() => false)\n\t\treturn available.where((unit) => chosen.includes(unit))\n\t}\n\n\t/** The help goal: a call of an ally's standing, and enough to send to it */\n\tprivate makeGoal(): GoalDef {\n\t\treturn defineGoal({\n\t\t\tid: HELP,\n\t\t\tweight: 0.7,\n\t\t\tconsiderations: [\n\t\t\t\tconsider('an ally calls for help', () => (this.calling() ? 1 : 0), curve.step(1)),\n\t\t\t\tconsider(\n\t\t\t\t\t'enough to send',\n\t\t\t\t\t(ai) => {\n\t\t\t\t\t\tconst request = this.calling()\n\t\t\t\t\t\treturn request ? this.helpers(ai.goals.pool(), request).length : 0\n\t\t\t\t\t},\n\t\t\t\t\tcurve.step(1)\n\t\t\t\t)\n\t\t\t],\n\t\t\tclaims: {\n\t\t\t\tunits: (_ai, available) => {\n\t\t\t\t\tconst request = this.calling()\n\t\t\t\t\treturn request ? this.helpers(available, request) : []\n\t\t\t\t}\n\t\t\t},\n\t\t\tcommitment: 10,\n\t\t\trun: (ai, claimed) => {\n\t\t\t\tconst request = this.calling()\n\t\t\t\tif (!request) return\n\t\t\t\tconst squad = ai.squads.named('help')\n\t\t\t\tconst at = squad?.current?.data.at as Vec2 | undefined\n\t\t\t\tif (squad && at && distSq(at, request.at) <= SAME_PLACE * SAME_PLACE && squad.done === undefined) {\n\t\t\t\t\t// there already: made up to what the call is now (more of them seen there), from what nothing holds\n\t\t\t\t\tconst more = this.helpers(ai.goals.pool(), {\n\t\t\t\t\t\t...request,\n\t\t\t\t\t\tstrength: Math.max(0, request.strength * this.margin - squad.strength()) / this.margin\n\t\t\t\t\t})\n\t\t\t\t\tif (request.strength > 0 && more.length) squad.add(more, 'more seen there')\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tclaimed.squad('help', claimed.units).defend(request.at, SEEN_NEAR)\n\t\t\t\tif (!request.answered.includes(ai.playerId)) request.answered.push(ai.playerId)\n\t\t\t\tai.decide(`answers player ${request.from}'s call for help at ${where(request.at)} with ${claimed.units.length}`, { kind: 'team', goal: HELP })\n\t\t\t\tthis.say('helping')\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Team play as the report shows it */\n\treport(): TeamReport {\n\t\tconst { ai } = this\n\t\tconst tickRate = ai.session.tickRate\n\t\tconst plan = this.plan\n\t\treturn {\n\t\t\tteam: this.team,\n\t\t\tcomputers: this.computers(),\n\t\t\trequests: this.requests().map((each) => ({\n\t\t\t\tid: each.id,\n\t\t\t\tkind: each.kind,\n\t\t\t\tfrom: each.from,\n\t\t\t\tat: pair(each.at),\n\t\t\t\tstrength: Math.round(each.strength),\n\t\t\t\tby: each.by,\n\t\t\t\tanswered: [...each.answered],\n\t\t\t\tleft: Math.max(0, Math.round((each.until - ai.tick) / tickRate))\n\t\t\t})),\n\t\t\t...(plan && {\n\t\t\t\tplan: {\n\t\t\t\t\ttarget: pair(plan.target),\n\t\t\t\t\tin: Math.round((plan.at - ai.tick) / tickRate),\n\t\t\t\t\tby: plan.by,\n\t\t\t\t\tjoined: [...plan.joined],\n\t\t\t\t\tdeclined: [...plan.declined]\n\t\t\t\t}\n\t\t\t}),\n\t\t\tenemyBases: this.enemyBases().length\n\t\t}\n\t}\n\n\t/** What it remembers, for a save: a copy (the board is the world's, saved with it) */\n\t/** Whether it has anything to remember now: one that does not is left out of a save */\n\tremembers(): boolean {\n\t\treturn this.enabled\n\t}\n\n\t/** Its part of the brain's report */\n\treportTo(report: AiReport): void {\n\t\tif (this.enabled) report.team = this.report()\n\t}\n\n\t/** Gives a copy of the team play's memory, for a save of the brain */\n\tsave(): TeamPlayMemory {\n\t\treturn { v: 1, heard: this.memory.heard, said: { ...this.memory.said } }\n\t}\n\n\t/** Takes back what `save` gave: whether it was read */\n\trestore(memory: unknown): boolean {\n\t\tconst given = memory as TeamPlayMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.memory = { v: 1, heard: given.heard ?? -1, said: { ...(given.said ?? {}) } }\n\t\treturn true\n\t}\n}\n\n/**\n * The team module: the team's board brought up to date each think (`ai.team.think`: itself and what it knows written,\n * pings and an ally's damage heard as calls for help, its own raids asked help for, the plan of an attack together\n * answered), and the `help` goal on the picker. With how it plays where the brain's definition and the seat's options\n * say nothing (`TeamOptions`)\n *\n * @beta\n */\nexport const team = (options: TeamOptions = {}): AiModuleDef =>\n\tdefineModule({ id: 'team', make: (ai: Brain): AiModule => {\n\t\tai.area(Team).configure(options)\n\t\treturn {\n\t\t\tid: 'team',\n\t\t\tphase: 'sense',\n\t\t\tafter: ['defence'],\n\t\t\tthink: () => ai.area(Team).think()\n\t\t}\n\t} })\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tteam?: TeamPlayMemory\n\t}\n}\n"],"mappings":";;;;;;;AAkLA,IAAM,YAAY;;AAIlB,IAAM,cAAc;;AAEpB,IAAM,YAAY;;;;;;AAMlB,IAAa,OAAO;;;;;;AAOpB,IAAa,SAAS;;AAEtB,IAAM,cAAc;CAAE,QAAQ;CAAQ,QAAQ;AAAO;;;;;;AAOrD,IAAa,mBAA8B;CAAE,GAAG;CAAG,UAAU,CAAC;CAAG,OAAO,CAAC;CAAG,MAAM;AAAE;;;;;;;;AASpF,IAAa,OAAb,MAAa,KAAuB;CAwBzB;CAEQ;;CAxBlB,OAAgB,KAAK;;CAErB,OAAO,KAAK,IAAiB;EAC5B,OAAO,IAAI,KAAK,IAAI,GAAG,SAAS;CACjC;;CAEA,KAAc;;CAEd,SAAkB;;CAGlB,UAAU;CACV,SAAiC;EAAE,GAAG;EAAG,OAAO;EAAI,MAAM,CAAC;CAAE;CAC7D,gBAAqC,CAAC;CACtC,MAAyB,UAAU;;CAEnC;;CAEA;CAEA,YAEC,IAEA,QACC;EAHQ,KAAA,KAAA;EAEQ,KAAA,SAAA;EAEjB,KAAK,OAAO,KAAK,SAAS;EAC1B,KAAK,WAAW,KAAK,aAAa;CACnC;;CAGA,UAAU,SAA4B;EACrC,KAAK,gBAAgB;EACrB,IAAI,CAAC,KAAK,YAAY,KAAK,QAAQ,eAAe,OAAO,KAAK,GAAG,MAAM,IAAI,KAAK,IAAI;EACpF,IAAI,CAAC,KAAK,YAAY,KAAK,QAAQ,eAAe,OAAO,KAAK,GAAG,MAAM,IAAI,KAAK,QAAQ;EACxF,KAAK,UAAU;CAChB;;CAGA,IAAI,UAAuB;EAC1B,OAAO,KAAK,GAAG,MAAM,uBAAuB;GAAE,GAAG,KAAK;GAAe,GAAG,KAAK,GAAG,SAAS;EAAK,EAAE;CACjG;;CAGA,IAAI,WAAoB;EACvB,OAAO,KAAK,WAAW,CAAC,CAAC,KAAK,QAAQ;CACvC;;CAGA,IAAI,QAAmB;EACtB,OAAO,KAAK,SAAS,KAAK,KAAK;CAChC;;CAGA,IAAI,OAAe;EAClB,OAAO,KAAK,GAAG,KAAK,GAAG;CACxB;;CAGA,YAAwB;EACvB,MAAM,EAAE,OAAO,OAAO;EACtB,MAAM,SAAS,GAAG,OAAO,KAAK,GAAG,QAAQ;EACzC,OAAO,OAAO,QAAQ,MAAM,KAAK,CAAC,CAChC,QAAQ,GAAG,WAAW,MAAM,QAAQ,MAAM,CAAC,CAC3C,KAAK,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC,CACzB,MAAM,GAAG,MAAM,IAAI,CAAC;CACvB;;CAGA,SAAS,MAA2C;EACnD,MAAM,EAAE,SAAS,KAAK;EACtB,OAAO,KAAK,MAAM,SAAS,QAAQ,SAAS,KAAK,QAAQ,SAAS,SAAS,KAAA,KAAa,KAAK,SAAS,KAAK;CAC5G;;;;;CAMA,QACC,MACA,IACA,UACA,IACA,OAAiB,KAAK,GAAG,UACzB,SACc;EACd,MAAM,EAAE,IAAI,UAAU;EACtB,MAAM,QAAQ,GAAG,OAAO,KAAK,OAAO,WAAW,KAAK,QAAQ,cAAc,MAAM,GAAG,QAAQ,QAAQ;EACnG,MAAM,OAAO,MAAM,SAAS,MAC1B,SAAS,KAAK,SAAS,QAAQ,KAAK,SAAS,QAAQ,KAAK,QAAQ,GAAG,QAAQ,OAAO,KAAK,IAAI,EAAE,KAAK,GACtG;EACA,IAAI,MAAM;GACT,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,KAAK;GACvC,KAAK,WAAW,KAAK,IAAI,KAAK,UAAU,QAAQ;GAChD,OAAO;EACR;EACA,MAAM,UAAuB;GAAE,IAAI,MAAM;GAAQ;GAAM;GAAM,IAAI,MAAM,EAAE;GAAG;GAAU;GAAO;GAAI,UAAU,CAAC;EAAE;EAC9G,MAAM,SAAS,KAAK,OAAO;EAC3B,GAAG,OAAO,YAAY,KAAK,MAAM,MAAM,EAAE,IAAI,SAAS,GAAG,WAAW,KAAK,eAAe,OAAO,IAAI,GAAG,aAAa,KAAK,MAAM,QAAQ,EAAE,IAAI,EAC3I,MAAM,OACP,CAAC;EACD,OAAO;CACR;;CAGA,aAA4D;EAC3D,MAAM,SAAwD,CAAC;EAC/D,MAAM,QAAQ,KAAK,MAAM;EACzB,KAAK,MAAM,MAAM,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC,GACvE,KAAK,MAAM,QAAQ,MAAM,GAAG,CAAC,OAAO;GACnC,MAAM,OAAO,OAAO,MAAM,SAAS,KAAK,UAAU,KAAK,SAAS,OAAO,KAAK,IAAI,KAAK,EAAE,IAAI,GAAuB;GAClH,IAAI,MAAM,KAAK,OAAO,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI;QAC9C,OAAO,KAAK;IAAE,GAAG;IAAM,IAAI,MAAM,KAAK,EAAE;GAAE,CAAC;EACjD;EAED,OAAO;CACR;;CAGA,IAAI,OAA+B;EAClC,MAAM,OAAO,KAAK,MAAM;EACxB,OAAO,QAAQ,KAAK,GAAG,QAAQ,KAAK,KAAK,YAAY,KAAK,GAAG,QAAQ,WAAW,OAAO,KAAA;CACxF;;CAGA,QAAQ,QAA0B;EACjC,MAAM,EAAE,OAAO;EACf,MAAM,OAAmB;GACxB,QAAQ,MAAM,MAAM;GACpB,IAAI,GAAG,OAAO,KAAK,OAAO,KAAK,QAAQ,aAAa,MAAM,GAAG,QAAQ,QAAQ;GAC7E,IAAI,GAAG;GACP,QAAQ,CAAC,GAAG,QAAQ;GACpB,UAAU,CAAC;GACX,OAAO,GAAG;EACX;EACA,KAAK,MAAM,OAAO;EAClB,GAAG,OAAO,kCAAkC,MAAM,MAAM,EAAE,MAAM,KAAK,QAAQ,aAAa,GAAG,KAAK,EAAE,MAAM,OAAO,CAAC;EAClH,OAAO;CACR;;CAGA,OAAa;EACZ,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,QAAQ,KAAK,OAAO,SAAS,KAAK,GAAG,QAAQ,GAAG;EACrD,KAAK,OAAO,KAAK,KAAK,GAAG,QAAQ;EACjC,KAAK,WAAW,KAAK,SAAS,QAAQ,SAAS,SAAS,KAAK,GAAG,QAAQ;EACxE,KAAK,GAAG,OAAO,gBAAgB,KAAK,GAAG,eAAe,MAAM,KAAK,MAAM,KAAK,EAAE,MAAM,OAAO,CAAC;CAC7F;;CAGA,UAAgB;EACf,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,QAAQ,KAAK,SAAS,SAAS,KAAK,GAAG,QAAQ,KAAK,KAAK,OAAO,SAAS,KAAK,GAAG,QAAQ,GAAG;EACjG,KAAK,SAAS,KAAK,KAAK,GAAG,QAAQ;EACnC,KAAK,GAAG,OAAO,mBAAmB,KAAK,GAAG,eAAe,MAAM,KAAK,MAAM,EAAE,0BAA0B,EAAE,MAAM,OAAO,CAAC;CACvH;;CAGA,IAAI,MAAoD;EACvD,MAAM,EAAE,OAAO;EACf,MAAM,UAAU,KAAK;EACrB,MAAM,OAAO,QAAQ,QAAQ;EAC7B,IAAI,CAAC,KAAK,WAAW,CAAC,QAAQ,OAAO,CAAC,MAAM;EAC5C,MAAM,OAAO,KAAK,OAAO,KAAK;EAC9B,IAAI,SAAS,KAAA,KAAa,GAAG,OAAO,OAAO,KAAK,GAAG,QAAQ,UAAU;EACrE,KAAK,OAAO,KAAK,QAAQ,GAAG;EAC5B,GAAG,KAAK;GAAE,MAAM;GAAQ;GAAM,IAAI;EAAS,CAAC;CAC7C;;;;;CAMA,QAAc;EACb,MAAM,EAAE,IAAI,UAAU;EACtB,MAAM,OAAO,GAAG;EAChB,MAAM,WAAW,MAAM,SAAS,QAAQ,SAAS,KAAK,QAAQ,IAAI;EAClE,IAAI,MAAM,QAAQ,OAAO,MAAM,KAAK,KAAK,YAAY,GAAG,QAAQ,UAAU,OAAO,MAAM;EACvF,IAAI,GAAG,IAAI,cAAc,OACxB,MAAM,MAAM,GAAG,YAAY;GAC1B;GACA,OAAO,GAAG,UAAU,MAClB,MAAM,CAAC,CACP,QAAQ,SAAS,CAAC,KAAK,IAAI,CAAC,CAC5B,KAAK,UAAU;IAAE,OAAO,KAAK;IAAO,IAAI,MAAM,KAAK,EAAE;IAAG,MAAM,KAAK;GAAK,EAAE;EAC7E;OACM,MAAM,MAAM,GAAG,YAAY;GAAE;GAAM,OAAO,CAAC;EAAE;EACpD,MAAM,YAAY,KAAK,OAAO;EAC9B,KAAK,OAAO,QAAQ;EACpB,IAAI,GAAG,IAAI,cAAc,SAAS,aAAa,GAAG,KAAK,KAAK,SAAS;EACrE,IAAI,KAAK,QAAQ,eAAe,MAAM,KAAK,SAAS;EACpD,KAAK,KAAK,QAAQ,cAAc,SAAS,GAAG,KAAK,OAAO,CAAC,CAAC,SACzD,KAAK,MAAM,QAAQ,GAAG,KAAK,OAAO,CAAC,CAAC,MAAM,GAAG;GAC5C,IAAI,KAAK,WAAW,GAAG,KAAK,OAAO,CAAC,CAAC,UAAU,KAAK,aAAa,GAAG;GACpE,KAAK,QAAQ,QAAQ,KAAK,KAAK,IAAI,KAAK,UAAU,MAAM;EACzD;EAGD,MAAM,OAAO,KAAK;EAClB,IAAI,QAAQ,KAAK,OAAO,GAAG,YAAY,CAAC,KAAK,OAAO,SAAS,GAAG,QAAQ,KAAK,KAAK,QAAQ,WAAW,KAAK,QAAQ;CACnH;;;;;;CAOA,WAAyB;EACxB,MAAM,EAAE,OAAO;EACf,MAAM,OAAO,GAAG,KAAK,KAAK;EAC1B,IAAI,CAAC,MAAM;EACX,KAAK,MAAM,WAAW,KAAK,SAAS,OAAO,GAAG;GAC7C,IAAI,QAAQ,OAAO,UAAU,QAAQ,SAAS,GAAG,YAAY,QAAQ,SAAS,SAAS,GAAG,QAAQ,GAAG;GACrG,QAAQ,SAAS,KAAK,GAAG,QAAQ;GACjC,MAAM,MAAM,GAAG,OACb,IAAI,CAAC,CACL,OAAO,QACN,UACA,MAAM,SACN,MAAM,WACL,CAAC;;;;IAAuB;GAAO,CAAC,CAAC,SAAS,MAAM,SAAS,EAAE,KAAK,MAAM,SAAS,YAAY,WAC5F,MAAM,SAAS,SAAS,SAC1B;GACD,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,UAAU,QAAQ,KAAK,mBAAmB;GACvF,GAAG,OAAO,6BAA6B,QAAQ,KAAK,WAAW,IAAI,SAAS,IAAI,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,iBAAiB,EACxI,MAAM,OACP,CAAC;GACD,IAAI,IAAI,QAAQ,KAAK,IAAI,YAAY;EACtC;CACD;;;;;CAMA,SAA0C;EACzC,MAAM,EAAE,OAAO;EACf,OAAO,GAAG,MAAM,qBAAqB;GACpC,MAAM,OAAO,GAAG,KAAK,KAAK;GAC1B,IAAI,CAAC,MAAM,OAAO,KAAA;GAClB,MAAM,UAAU,KAAK,SAAS,OAAO,CAAC,CAAC,QAAQ,SAAS,KAAK,OAAO,MAAM;GAC1E,MAAM,aAAa,CAAC,GAAG,KAAK,SAAS,QAAQ,GAAG,GAAG,KAAK,SAAS,QAAQ,CAAC,CAAC,CAAC,QAC1E,SACA,KAAK,OAAO,UACZ,KAAK,SAAS,GAAG,YACjB,OAAO,KAAK,IAAI,IAAI,KAAK,QACzB,CAAC,QAAQ,MAAM,UAAU,MAAM,SAAS,KAAK,QAAQ,MAAM,KAAK,KAAK,EAAE,CACzE;GACA,WAAW,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;GACrC,OAAO,WAAW;EACnB,CAAC;CACF;;;;;CAMA,eAAgC;EAC/B,MAAM,QAAQ,WAAoB,YAAyB,KAAK,QAAQ,WAAW;GAAE,IAAI,QAAQ;GAAI,UAAU,KAAK,OAAO,QAAQ,EAAE;EAAE,CAAC;EACxI,OAAO,WAAW;GACjB,IAAI;GACJ,QAAQ;GACR,gBAAgB,CACf,SAAS,uCAAwC,KAAK,OAAO,IAAI,IAAI,GAAI,MAAM,KAAK,CAAC,CAAC,GACtF,SACC,mBACC,OAAO;IACP,MAAM,UAAU,KAAK,OAAO;IAC5B,OAAO,UAAU,KAAK,GAAG,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,SAAS;GAC1D,GACA,MAAM,KAAK,CAAC,CACb,CACD;GACA,QAAQ,EACP,QAAQ,KAAK,cAAc;IAC1B,MAAM,UAAU,KAAK,OAAO;IAC5B,OAAO,UAAU,KAAK,WAAW,OAAO,IAAI,CAAC;GAC9C,EACD;GACA,YAAY;GACZ,MAAM,IAAI,YAAY;IACrB,MAAM,UAAU,KAAK,OAAO;IAC5B,IAAI,CAAC,WAAY,QAAQ,SAAS,YAAY,QAAQ,SAAS,UAAW;IAC1E,MAAM,OAAO,YAAY,QAAQ;IAEjC,MAAM,QAAQ,GAAG,OAAO,MAAM,IAAI;IAClC,MAAM,KAAK,OAAO,SAAS,KAAK;IAChC,IAAI,SAAS,MAAM,OAAO,IAAI,QAAQ,EAAE,KAAK,OAA2B,MAAM,SAAS,KAAA,GAAW;IAClG,MAAM,QAAQ,QAAQ,MAAM,MAAM,QAAQ,KAAK;IAC/C,IAAI,QAAQ,SAAS,UAAU,MAAM,OAAO,QAAQ,EAAE;SACjD,MAAM,OAAO,QAAQ,IAAI,SAAS;IACvC,IAAI,CAAC,QAAQ,SAAS,SAAS,GAAG,QAAQ,GAAG,QAAQ,SAAS,KAAK,GAAG,QAAQ;IAC9E,GAAG,OACF,GAAG,QAAQ,SAAS,WAAW,WAAW,QAAQ,MAAM,MAAM,QAAQ,EAAE,EAAE,QAAQ,QAAQ,MAAM,OAAO,cAAc,QAAQ,KAAK,UAClI;KAAE,MAAM;KAAQ,MAAM;IAAO,CAC9B;IACA,IAAI,QAAQ,SAAS,UAAU,KAAK,IAAI,WAAW;GACpD;EACD,CAAC;CACF;;CAGA,eAA+B;EAC9B,MAAM,EAAE,OAAO;EACf,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC5C;;CAGA,KAAa,OAAqB;EACjC,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,SAAS;EACjB,MAAM,QAAQ,WAAqB,WAAW,GAAG,YAAY,KAAK,OAAO,MAAM,CAAC,EAAE,aAAa;EAC/F,KAAK,MAAM,QAAQ,GAAG,UAAU,OAAO,MAAM,GAAG;GAC/C,IAAI,KAAK,QAAQ,SAAS,CAAC,KAAK,KAAK,MAAM,GAAG;GAE9C,MAAM,UAAU,GAAG,QAAQ,SAAS,SAAS,KAAK,MAAM,WAAW,KAAK;GACxE,IAAI,WAAW,YAAY,UAAU,KAAK,QAAQ,SAAS,KAAK,IAAI,YAAY,SAAS,KAAK,OAAO,KAAK,EAAE,IAAI,GAAG,QAAQ,KAAK,MAAM;QACjI,GAAG,OAAO,gBAAgB,KAAK,OAAO,KAAK,KAAK,KAAK,MAAM,MAAM,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;EACnG;EACA,KAAK,MAAM,OAAO,GAAG,UAAU,OAAO,OAAO,GAAG;GAC/C,IAAI,IAAI,QAAQ,SAAS,CAAC,KAAK,IAAI,KAAK,GAAG;GAC3C,MAAM,WAAW,KAAK,OAAO,IAAI,EAAE;GACnC,IAAI,WAAW,GAAG,KAAK,QAAQ,QAAQ,IAAI,IAAI,UAAU,UAAU,IAAI,KAAK;EAC7E;CACD;;CAGA,OAAe,IAAkB;EAChC,OAAO,KAAK,GAAG,KAAK,QAAQ,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC,SAAS;CAC1E;;CAGA,UAA2C;EAC1C,MAAM,EAAE,OAAO;EACf,OAAO,GAAG,MAAM,sBAAsB;GACrC,MAAM,OAAO,GAAG,KAAK,KAAK;GAC1B,IAAI,CAAC,MAAM,OAAO,KAAA;GAClB,MAAM,aAAa,KAAK,SAAS,MAAM,CAAC,CAAC,QAAQ,SAAS,KAAK,SAAS,GAAG,YAAY,OAAO,KAAK,IAAI,IAAI,KAAK,IAAuB;GACvI,WAAW,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE;GAChE,OAAO,WAAW;EACnB,CAAC;CACF;;CAGA,IAAI,SAAiB;EACpB,MAAM,OAAO,KAAK,IAAI,KAAM,KAAK,IAAI,KAAM,KAAK,QAAQ,YAAY,EAAG,CAAC;EACxE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK;CACnC;;CAGA,QAAgB,WAAoB,SAAwD;EAC3F,MAAM,EAAE,OAAO;EACf,MAAM,OAAO,QAAQ,WAAW,KAAK;EACrC,MAAM,OAAO,UACX,SAAS,CAAC,CACV,KAAK,CAAC,CACN,MAAM,MAAM,CAAC,CACb,MAAM,GAAG,MAAM,OAAO,GAAG,QAAQ,EAAE,IAAI,OAAO,GAAG,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;EAC7E,MAAM,SAAwB,CAAC;EAC/B,IAAI,MAAM;EACV,KAAK,MAAM,QAAQ,MAAM;GACxB,IAAI,QAAQ,WAAW,IAAI,OAAO,OAAO,OAAO,UAAU,aAAa;GACvE,OAAO,KAAK,IAAI;GAChB,OAAO,GAAG,KAAK,SAAS,GAAG,IAAI;EAChC;EAEA,IAAI,QAAQ,WAAW,KAAK,MAAM,MAAM,OAAO,UAAU,YAAY,KAAK;EAC1E,OAAO,UAAU,OAAO,SAAS,OAAO,SAAS,IAAI,CAAC;CACvD;;CAGA,WAA4B;EAC3B,OAAO,WAAW;GACjB,IAAI;GACJ,QAAQ;GACR,gBAAgB,CACf,SAAS,gCAAiC,KAAK,QAAQ,IAAI,IAAI,GAAI,MAAM,KAAK,CAAC,CAAC,GAChF,SACC,mBACC,OAAO;IACP,MAAM,UAAU,KAAK,QAAQ;IAC7B,OAAO,UAAU,KAAK,QAAQ,GAAG,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,SAAS;GAClE,GACA,MAAM,KAAK,CAAC,CACb,CACD;GACA,QAAQ,EACP,QAAQ,KAAK,cAAc;IAC1B,MAAM,UAAU,KAAK,QAAQ;IAC7B,OAAO,UAAU,KAAK,QAAQ,WAAW,OAAO,IAAI,CAAC;GACtD,EACD;GACA,YAAY;GACZ,MAAM,IAAI,YAAY;IACrB,MAAM,UAAU,KAAK,QAAQ;IAC7B,IAAI,CAAC,SAAS;IACd,MAAM,QAAQ,GAAG,OAAO,MAAM,MAAM;IACpC,MAAM,KAAK,OAAO,SAAS,KAAK;IAChC,IAAI,SAAS,MAAM,OAAO,IAAI,QAAQ,EAAE,KAAK,OAA2B,MAAM,SAAS,KAAA,GAAW;KAEjG,MAAM,OAAO,KAAK,QAAQ,GAAG,MAAM,KAAK,GAAG;MAC1C,GAAG;MACH,UAAU,KAAK,IAAI,GAAG,QAAQ,WAAW,KAAK,SAAS,MAAM,SAAS,CAAC,IAAI,KAAK;KACjF,CAAC;KACD,IAAI,QAAQ,WAAW,KAAK,KAAK,QAAQ,MAAM,IAAI,MAAM,iBAAiB;KAC1E;IACD;IACA,QAAQ,MAAM,QAAQ,QAAQ,KAAK,CAAC,CAAC,OAAO,QAAQ,IAAI,SAAS;IACjE,IAAI,CAAC,QAAQ,SAAS,SAAS,GAAG,QAAQ,GAAG,QAAQ,SAAS,KAAK,GAAG,QAAQ;IAC9E,GAAG,OAAO,kBAAkB,QAAQ,KAAK,sBAAsB,MAAM,QAAQ,EAAE,EAAE,QAAQ,QAAQ,MAAM,UAAU;KAAE,MAAM;KAAQ,MAAM;IAAK,CAAC;IAC7I,KAAK,IAAI,SAAS;GACnB;EACD,CAAC;CACF;;CAGA,SAAqB;EACpB,MAAM,EAAE,OAAO;EACf,MAAM,WAAW,GAAG,QAAQ;EAC5B,MAAM,OAAO,KAAK;EAClB,OAAO;GACN,MAAM,KAAK;GACX,WAAW,KAAK,UAAU;GAC1B,UAAU,KAAK,SAAS,CAAC,CAAC,KAAK,UAAU;IACxC,IAAI,KAAK;IACT,MAAM,KAAK;IACX,MAAM,KAAK;IACX,IAAI,KAAK,KAAK,EAAE;IAChB,UAAU,KAAK,MAAM,KAAK,QAAQ;IAClC,IAAI,KAAK;IACT,UAAU,CAAC,GAAG,KAAK,QAAQ;IAC3B,MAAM,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,QAAQ,GAAG,QAAQ,QAAQ,CAAC;GAChE,EAAE;GACF,GAAI,QAAQ,EACX,MAAM;IACL,QAAQ,KAAK,KAAK,MAAM;IACxB,IAAI,KAAK,OAAO,KAAK,KAAK,GAAG,QAAQ,QAAQ;IAC7C,IAAI,KAAK;IACT,QAAQ,CAAC,GAAG,KAAK,MAAM;IACvB,UAAU,CAAC,GAAG,KAAK,QAAQ;GAC5B,EACD;GACA,YAAY,KAAK,WAAW,CAAC,CAAC;EAC/B;CACD;;;CAIA,YAAqB;EACpB,OAAO,KAAK;CACb;;CAGA,SAAS,QAAwB;EAChC,IAAI,KAAK,SAAS,OAAO,OAAO,KAAK,OAAO;CAC7C;;CAGA,OAAuB;EACtB,OAAO;GAAE,GAAG;GAAG,OAAO,KAAK,OAAO;GAAO,MAAM,EAAE,GAAG,KAAK,OAAO,KAAK;EAAE;CACxE;;CAGA,QAAQ,QAA0B;EACjC,MAAM,QAAQ;EACd,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,MAAM,GAAG,OAAO;EACjE,KAAK,SAAS;GAAE,GAAG;GAAG,OAAO,MAAM,SAAS;GAAI,MAAM,EAAE,GAAI,MAAM,QAAQ,CAAC,EAAG;EAAE;EAChF,OAAO;CACR;AACD;;;;;;;;;AAUA,IAAa,QAAQ,UAAuB,CAAC,MAC5C,aAAa;CAAE,IAAI;CAAQ,OAAO,OAAwB;EACzD,GAAG,KAAK,IAAI,CAAC,CAAC,UAAU,OAAO;EAC/B,OAAO;GACN,IAAI;GACJ,OAAO;GACP,OAAO,CAAC,SAAS;GACjB,aAAa,GAAG,KAAK,IAAI,CAAC,CAAC,MAAM;EAClC;CACD;AAAE,CAAC"}
|
package/dist/ai/threat.d.ts
CHANGED
|
@@ -23,7 +23,9 @@ export interface Threat {
|
|
|
23
23
|
export interface ThreatCell extends Threat {
|
|
24
24
|
/** The middle of the cell */
|
|
25
25
|
at: Vec2;
|
|
26
|
+
/** The cell's column on the grid, counted from 0 */
|
|
26
27
|
col: number;
|
|
28
|
+
/** The cell's row on the grid, counted from 0 */
|
|
27
29
|
row: number;
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
@@ -33,7 +35,9 @@ export interface ThreatCell extends Threat {
|
|
|
33
35
|
* @beta
|
|
34
36
|
*/
|
|
35
37
|
export interface ThreatQuery {
|
|
38
|
+
/** The layer the thing asked about is on; `ground` when left out */
|
|
36
39
|
layer?: Layer;
|
|
40
|
+
/** Whether enemy structures remembered but out of sight count too */
|
|
37
41
|
remembered?: boolean;
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
@@ -50,7 +54,9 @@ export declare class ThreatMap {
|
|
|
50
54
|
readonly view: AiView;
|
|
51
55
|
/** Cells across and down, and the side of one */
|
|
52
56
|
readonly cols: number;
|
|
57
|
+
/** How many cells down the grid has */
|
|
53
58
|
readonly rows: number;
|
|
59
|
+
/** The side of a cell in cells of the map */
|
|
54
60
|
readonly cell = 8;
|
|
55
61
|
private seen;
|
|
56
62
|
private withRemembered;
|