@v12-engine/engine 0.1.1 → 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/goals.js
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { exp } from "../exactMath.js";
|
|
2
|
+
import { defineModule } from "./module.js";
|
|
3
|
+
import { considerationsLine } from "./report.js";
|
|
4
|
+
import { UnitSet } from "./view.js";
|
|
5
|
+
//#region src/ai/goals.ts
|
|
6
|
+
var clamp01 = (x) => x > 1 ? 1 : x > 0 ? x : 0;
|
|
7
|
+
/**
|
|
8
|
+
* The usual response curves, each a line (`consider(name, read, curve.saturate(6))`): how a raw number becomes "how
|
|
9
|
+
* much do I care". A curve gives 0..1; what gives nonsense (NaN) counts as 0
|
|
10
|
+
*
|
|
11
|
+
* @beta
|
|
12
|
+
*/
|
|
13
|
+
var curve = {
|
|
14
|
+
/** A straight line from 0 at 0 to 1 at `max` (1 when left out: for a ratio), flat beyond: twice the units, twice the care, up to a point */
|
|
15
|
+
linear: (max = 1) => (x) => clamp01(x / max),
|
|
16
|
+
/** 1 − e^(−x/k): rises fast, then levels off at 1 (0.63 at `k`, 0.86 at `2k`): the sixth worker seen matters less than the first */
|
|
17
|
+
saturate: (k) => (x) => x <= 0 ? 0 : 1 - exp(-x / k),
|
|
18
|
+
/** k / (k + x): 1 at 0, falling to a half at `k` and towards 0: the less there is of it, the better (how held their base is) */
|
|
19
|
+
inverse: (k) => (x) => x <= 0 ? 1 : k / (k + x),
|
|
20
|
+
/** 0 below `at`, 1 from it on: a threshold (a wave is ready at so many units), an on-off (any intruder at all: `step(1)`) */
|
|
21
|
+
step: (at) => (x) => x >= at ? 1 : 0,
|
|
22
|
+
/** 1 between `low` and `high`, 0 outside: a window (an army of between 4 and 12) */
|
|
23
|
+
band: (low, high) => (x) => x >= low && x <= high ? 1 : 0,
|
|
24
|
+
/** A shape of the game's own: whatever the function gives, kept to 0..1 */
|
|
25
|
+
custom: (fn) => (x) => clamp01(fn(x))
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A consideration: a question with a name, and the curve that says how much its answer matters (`curve.linear()`
|
|
29
|
+
* when left out: the number is a ratio already)
|
|
30
|
+
*
|
|
31
|
+
* @beta
|
|
32
|
+
*/
|
|
33
|
+
function consider(name, read, shape = curve.linear()) {
|
|
34
|
+
return {
|
|
35
|
+
name,
|
|
36
|
+
read,
|
|
37
|
+
curve: shape
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Defines a goal: checked, and given back as it is, for a brain's `goals`, `meleeBrain.with({ goals })`, or
|
|
42
|
+
* `ai.goals.add`
|
|
43
|
+
*
|
|
44
|
+
* @beta
|
|
45
|
+
*/
|
|
46
|
+
function defineGoal(def) {
|
|
47
|
+
if (!def.id) throw new Error("A goal needs an id");
|
|
48
|
+
if (!Array.isArray(def.considerations)) throw new Error(`The goal "${def.id}" needs its considerations, as a list`);
|
|
49
|
+
if (typeof def.run !== "function") throw new Error(`The goal "${def.id}" needs a run`);
|
|
50
|
+
return def;
|
|
51
|
+
}
|
|
52
|
+
var MIN = .05;
|
|
53
|
+
var MARGIN = .15;
|
|
54
|
+
var COMMITMENT = 5;
|
|
55
|
+
/**
|
|
56
|
+
* The brain's goals and their picker (`ai.goals`): what the computer could do, scored each think, the best given what
|
|
57
|
+
* they claim (`think`, once a think: run by the `goals()` module, or by a module of the brain's own in its place among
|
|
58
|
+
* the others). What each holds is read here (`held`, `holds`, `holder`, `pool`), taken by a rule or a module
|
|
59
|
+
* (`take`), and reported (`report`)
|
|
60
|
+
*
|
|
61
|
+
* @beta
|
|
62
|
+
*/
|
|
63
|
+
var Goals = class {
|
|
64
|
+
ai;
|
|
65
|
+
/** Its id among the brain's areas: what its memory and its report are kept under */
|
|
66
|
+
id = "goals";
|
|
67
|
+
/** What the log says where a save's memory of it is of a shape it does not read */
|
|
68
|
+
afresh = "the save remembers what the computer player’s goals held in a shape this brain does not read: they start afresh";
|
|
69
|
+
/** How much each goal scored this think, by id: what the debug tools showed before the report */
|
|
70
|
+
scores = {};
|
|
71
|
+
/** The goal that scored highest above the minimum this think: what the army is on. None when nothing is worth doing */
|
|
72
|
+
best;
|
|
73
|
+
entries = /* @__PURE__ */ new Map();
|
|
74
|
+
holds = {};
|
|
75
|
+
cooldowns = {};
|
|
76
|
+
added = 0;
|
|
77
|
+
thoughtAt = -1;
|
|
78
|
+
min;
|
|
79
|
+
margin;
|
|
80
|
+
commitment;
|
|
81
|
+
constructor(ai, options = {}) {
|
|
82
|
+
this.ai = ai;
|
|
83
|
+
this.min = options.min ?? MIN;
|
|
84
|
+
this.margin = options.margin ?? MARGIN;
|
|
85
|
+
this.commitment = options.commitment ?? COMMITMENT;
|
|
86
|
+
}
|
|
87
|
+
/** Adds goals to pick among: a brain's own (`BrainDef.goals`), the seat's (`AiOptions.goals`), a module's */
|
|
88
|
+
add(...defs) {
|
|
89
|
+
for (const def of defs) {
|
|
90
|
+
if (this.entries.has(def.id)) throw new Error(`The brain "${this.ai.def.id}" has two goals called "${def.id}"`);
|
|
91
|
+
this.entries.set(def.id, {
|
|
92
|
+
def,
|
|
93
|
+
order: this.added++,
|
|
94
|
+
score: 0,
|
|
95
|
+
urgent: false,
|
|
96
|
+
considerations: [],
|
|
97
|
+
picked: false
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Takes a goal out: what it held goes back to the pool, and it is told `removed`. Whether there was one */
|
|
102
|
+
remove(id) {
|
|
103
|
+
if (!this.entries.get(id)) return false;
|
|
104
|
+
this.release(id, "removed");
|
|
105
|
+
this.entries.delete(id);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
/** The goals, as added */
|
|
109
|
+
list() {
|
|
110
|
+
return [...this.entries.values()].map((entry) => entry.def);
|
|
111
|
+
}
|
|
112
|
+
/** A goal by id */
|
|
113
|
+
get(id) {
|
|
114
|
+
return this.entries.get(id)?.def;
|
|
115
|
+
}
|
|
116
|
+
/** What a goal holds, while it does */
|
|
117
|
+
held(id) {
|
|
118
|
+
return this.holds[id];
|
|
119
|
+
}
|
|
120
|
+
/** What every goal holds, by goal id */
|
|
121
|
+
all() {
|
|
122
|
+
return this.holds;
|
|
123
|
+
}
|
|
124
|
+
/** The goal that holds a unit, by the unit's id: none for a unit in the pool */
|
|
125
|
+
holder(unit) {
|
|
126
|
+
for (const id in this.holds) if (this.holds[id].units.includes(unit)) return id;
|
|
127
|
+
}
|
|
128
|
+
/** The player's units no goal holds, as of the think's picture: what a goal picked next may claim */
|
|
129
|
+
pool() {
|
|
130
|
+
const held = this.heldIds();
|
|
131
|
+
const { mine } = this.ai.view;
|
|
132
|
+
return held.size ? mine.where((entity) => !held.has(entity.id)) : mine;
|
|
133
|
+
}
|
|
134
|
+
/** The money the goals hold together (`GoalClaims.money`): held in the purse (`ai.purse`), which takes it off what is free */
|
|
135
|
+
reserved() {
|
|
136
|
+
const sum = {};
|
|
137
|
+
for (const id in this.holds) {
|
|
138
|
+
const { money } = this.holds[id];
|
|
139
|
+
for (const kind in money) sum[kind] = (sum[kind] ?? 0) + money[kind];
|
|
140
|
+
}
|
|
141
|
+
return sum;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Takes units from whatever goals hold them, for a rule (B2) or a module (the defence, C4) that wants them: a goal
|
|
145
|
+
* left with none is told why (`told` when left out). Those of them that were held, by id.
|
|
146
|
+
*
|
|
147
|
+
* With `by`, the units are then held by that rule or module itself (`by.id`, which names no goal: `rule:attack`),
|
|
148
|
+
* for `by.seconds` (30 when left out) or until `release(by.id)`: no goal may claim them meanwhile, for a rule goes
|
|
149
|
+
* before the goals (the one order of who may move a unit: goals, then rules take, then the defence; micro never
|
|
150
|
+
* retasks). Units taken again by the same id are added to what it holds, and its time starts again. `seconds:
|
|
151
|
+
* Infinity` holds them until let go of (`release`, `drop`): what a squad that is no goal's holds its units by
|
|
152
|
+
*/
|
|
153
|
+
take(units, why = "told", by) {
|
|
154
|
+
const wanted = new Set(units);
|
|
155
|
+
const taken = [];
|
|
156
|
+
for (const id in this.holds) {
|
|
157
|
+
if (id === by?.id) continue;
|
|
158
|
+
const hold = this.holds[id];
|
|
159
|
+
const kept = hold.units.filter((unit) => !wanted.has(unit));
|
|
160
|
+
if (kept.length === hold.units.length) continue;
|
|
161
|
+
taken.push(...hold.units.filter((unit) => wanted.has(unit)));
|
|
162
|
+
hold.units = kept;
|
|
163
|
+
if (!kept.length) this.release(id, why);
|
|
164
|
+
}
|
|
165
|
+
if (by) {
|
|
166
|
+
if (this.entries.has(by.id)) throw new Error(`"${by.id}" is a goal of the brain: what a rule holds needs a name of its own`);
|
|
167
|
+
const { tick, session } = this.ai;
|
|
168
|
+
const kept = (this.holds[by.id]?.units ?? []).filter((unit) => this.ai.view.mine.has(unit));
|
|
169
|
+
const all = [...kept, ...[...wanted].filter((unit) => !kept.includes(unit) && this.ai.view.mine.has(unit))];
|
|
170
|
+
all.sort((a, b) => this.ai.view.indexOf(this.ai.view.byId(a)) - this.ai.view.indexOf(this.ai.view.byId(b)));
|
|
171
|
+
const seconds = by.seconds ?? 30;
|
|
172
|
+
const forever = seconds === Infinity;
|
|
173
|
+
this.holds[by.id] = {
|
|
174
|
+
units: all,
|
|
175
|
+
since: this.holds[by.id]?.since ?? tick,
|
|
176
|
+
until: forever ? tick : tick + Math.round(seconds * session.tickRate),
|
|
177
|
+
score: 1,
|
|
178
|
+
...forever && { kept: true }
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return taken;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Adds units from the pool (what nothing holds) to what a goal, a rule or a module holds: a squad's reinforcements
|
|
185
|
+
* (`Squad.reinforce`). What another holds is passed over: `take` is for that. Those given, by id
|
|
186
|
+
*/
|
|
187
|
+
give(id, units) {
|
|
188
|
+
const hold = this.holds[id];
|
|
189
|
+
if (!hold) return [];
|
|
190
|
+
const { view } = this.ai;
|
|
191
|
+
const held = this.heldIds();
|
|
192
|
+
const given = [];
|
|
193
|
+
for (const unit of units) if (!held.has(unit) && view.mine.has(unit) && !given.includes(unit)) given.push(unit);
|
|
194
|
+
if (!given.length) return given;
|
|
195
|
+
hold.units = hold.units.filter((unit) => view.mine.has(unit));
|
|
196
|
+
hold.units.push(...given);
|
|
197
|
+
hold.units.sort((a, b) => view.indexOf(view.byId(a)) - view.indexOf(view.byId(b)));
|
|
198
|
+
return given;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Lets go of some of what a goal, a rule or a module holds: they go back to the pool. One left with none is released,
|
|
202
|
+
* told why (`done` when left out). Those let go of, by id
|
|
203
|
+
*/
|
|
204
|
+
drop(id, units, why = "done") {
|
|
205
|
+
const hold = this.holds[id];
|
|
206
|
+
if (!hold) return [];
|
|
207
|
+
const gone = new Set(units);
|
|
208
|
+
const dropped = hold.units.filter((unit) => gone.has(unit));
|
|
209
|
+
if (!dropped.length) return dropped;
|
|
210
|
+
hold.units = hold.units.filter((unit) => !gone.has(unit));
|
|
211
|
+
if (!hold.units.length) this.release(id, why);
|
|
212
|
+
return dropped;
|
|
213
|
+
}
|
|
214
|
+
/** What rules and modules hold (`take` with `by`), by their id: not goals' */
|
|
215
|
+
taken() {
|
|
216
|
+
const result = {};
|
|
217
|
+
for (const id in this.holds) if (!this.entries.has(id)) result[id] = this.holds[id];
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/** Whether a unit is held by a rule or a module rather than by a goal (`take` with `by`): what nothing else is to give orders to */
|
|
221
|
+
ruled(unit) {
|
|
222
|
+
for (const id in this.holds) if (!this.entries.has(id) && this.holds[id].units.includes(unit)) return true;
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
/** Takes a goal's claim away, telling it why (`told` when left out): its units go back to the pool. Whether it held one */
|
|
226
|
+
release(id, why = "told") {
|
|
227
|
+
const hold = this.holds[id];
|
|
228
|
+
if (!hold) return false;
|
|
229
|
+
delete this.holds[id];
|
|
230
|
+
if (hold.money) this.ai.purse.release(id);
|
|
231
|
+
const entry = this.entries.get(id);
|
|
232
|
+
if (!entry) {
|
|
233
|
+
this.ai.decide(`${id} lets go of ${hold.units.length === 1 ? "1 unit" : `${hold.units.length} units`}`, { kind: "rule" });
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
this.ai.decide(`${id} stopped: ${stopped(why, entry.lostTo)}`, {
|
|
237
|
+
kind: "goal",
|
|
238
|
+
goal: id
|
|
239
|
+
});
|
|
240
|
+
entry.def.stop?.(this.ai, why, this.claimedOf(id, hold, false));
|
|
241
|
+
const cooldown = entry.def.cooldown ?? 0;
|
|
242
|
+
if (cooldown > 0) this.cooldowns[id] = this.ai.tick + Math.round(cooldown * this.ai.session.tickRate);
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* The think: every goal scored (its considerations read, curved, multiplied, weighed), the goals that hold a claim
|
|
247
|
+
* kept to it or beaten, the rest picked best first with what they claim, and each picked one run. Once a think: a
|
|
248
|
+
* second call in the same think does nothing
|
|
249
|
+
*/
|
|
250
|
+
think() {
|
|
251
|
+
const { ai } = this;
|
|
252
|
+
const { tick, view } = ai;
|
|
253
|
+
if (this.thoughtAt === tick) return;
|
|
254
|
+
this.thoughtAt = tick;
|
|
255
|
+
for (const id in this.holds) {
|
|
256
|
+
const hold = this.holds[id];
|
|
257
|
+
const entry = this.entries.get(id);
|
|
258
|
+
const alive = hold.units.filter((unit) => view.mine.has(unit));
|
|
259
|
+
if (alive.length !== hold.units.length) hold.units = alive;
|
|
260
|
+
if (!entry) {
|
|
261
|
+
if (!hold.kept && tick >= hold.until || !alive.length) this.release(id, "done");
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (!alive.length && entry.def.claims?.units) this.release(id, "done");
|
|
265
|
+
}
|
|
266
|
+
for (const id in this.cooldowns) if (this.cooldowns[id] <= tick) delete this.cooldowns[id];
|
|
267
|
+
const entries = [...this.entries.values()];
|
|
268
|
+
this.scores = {};
|
|
269
|
+
this.best = void 0;
|
|
270
|
+
let bestScore = this.min;
|
|
271
|
+
for (const entry of entries) {
|
|
272
|
+
this.score(entry);
|
|
273
|
+
this.scores[entry.def.id] = entry.score;
|
|
274
|
+
if (entry.score > bestScore) {
|
|
275
|
+
bestScore = entry.score;
|
|
276
|
+
this.best = entry.def.id;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
for (const entry of entries) {
|
|
280
|
+
const { id } = entry.def;
|
|
281
|
+
if (this.holds[id] && entry.score <= (entry.def.min ?? this.min)) this.release(id, "done");
|
|
282
|
+
}
|
|
283
|
+
const ranked = entries.filter((entry) => entry.score > (entry.def.min ?? this.min)).sort((a, b) => b.score - a.score || a.order - b.order);
|
|
284
|
+
const pool = new Set(this.pool().ids());
|
|
285
|
+
for (let i = 0; i < ranked.length; i++) {
|
|
286
|
+
const entry = ranked[i];
|
|
287
|
+
const { def } = entry;
|
|
288
|
+
const { id } = def;
|
|
289
|
+
if (this.cooldowns[id] !== void 0) {
|
|
290
|
+
entry.why = "cooldown";
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
let hold = this.holds[id];
|
|
294
|
+
let first = false;
|
|
295
|
+
if (hold) {
|
|
296
|
+
if (!hold.units.length && def.claims?.units) {
|
|
297
|
+
this.release(id, entry.lost ?? "beaten");
|
|
298
|
+
entry.why = entry.lost === "urgent" ? "taken by an urgent goal" : "beaten";
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
hold = this.claim(entry, ranked, i, pool);
|
|
303
|
+
if (!hold) continue;
|
|
304
|
+
first = true;
|
|
305
|
+
}
|
|
306
|
+
entry.picked = true;
|
|
307
|
+
const claimed = this.claimedOf(id, hold, first);
|
|
308
|
+
if (first) this.decided(entry, claimed);
|
|
309
|
+
def.run(ai, claimed);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* A goal's score this think: each consideration read and curved, their product, the weight, the game's say. Once a
|
|
314
|
+
* consideration answers 0 the goal is vetoed, and the ones after it are not asked: put the cheap questions first
|
|
315
|
+
*/
|
|
316
|
+
score(entry) {
|
|
317
|
+
const { ai } = this;
|
|
318
|
+
const { def } = entry;
|
|
319
|
+
let product = 1;
|
|
320
|
+
entry.considerations = [];
|
|
321
|
+
for (const consideration of def.considerations) {
|
|
322
|
+
if (product === 0) {
|
|
323
|
+
entry.considerations.push({
|
|
324
|
+
name: consideration.name,
|
|
325
|
+
value: 0,
|
|
326
|
+
curved: 0,
|
|
327
|
+
asked: false
|
|
328
|
+
});
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const value = finite(consideration.read(ai));
|
|
332
|
+
const curved = positive(consideration.curve(value));
|
|
333
|
+
entry.considerations.push({
|
|
334
|
+
name: consideration.name,
|
|
335
|
+
value,
|
|
336
|
+
curved
|
|
337
|
+
});
|
|
338
|
+
product *= curved;
|
|
339
|
+
}
|
|
340
|
+
let score = positive(product * (def.weight ?? 1) * (ai.profile.weights?.[def.id] ?? 1));
|
|
341
|
+
entry.score = score;
|
|
342
|
+
entry.urgent = score > (def.min ?? this.min) && (typeof def.urgent === "function" ? def.urgent(ai) : !!def.urgent);
|
|
343
|
+
entry.picked = false;
|
|
344
|
+
entry.why = void 0;
|
|
345
|
+
entry.lost = void 0;
|
|
346
|
+
entry.lostTo = void 0;
|
|
347
|
+
}
|
|
348
|
+
/** Writes down a goal picked anew, for the decision log: its score, what it holds, its considerations */
|
|
349
|
+
decided(entry, claimed) {
|
|
350
|
+
const { def } = entry;
|
|
351
|
+
const units = def.claims?.units ? ` (${claimed.units.length === 1 ? "1 unit" : `${claimed.units.length} units`})` : "";
|
|
352
|
+
const reasons = considerationsLine(entry);
|
|
353
|
+
this.ai.decide(`${def.id} picked at ${entry.score.toFixed(2)}${units}${entry.urgent ? ", urgent" : ""}${reasons && `: ${reasons}`}`, {
|
|
354
|
+
kind: "goal",
|
|
355
|
+
goal: def.id
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* What a goal picked anew takes: the units it chooses from the pool and from the holds of goals ranked below it
|
|
360
|
+
* that it may take from (by the margin within their commitment, by any lead after it, and by any lead at all for an
|
|
361
|
+
* urgent goal), and the money it names. Nothing where it asked for units and chose none
|
|
362
|
+
*/
|
|
363
|
+
claim(entry, ranked, at, pool) {
|
|
364
|
+
const { ai } = this;
|
|
365
|
+
const { def } = entry;
|
|
366
|
+
const { view, tick } = ai;
|
|
367
|
+
const units = [];
|
|
368
|
+
if (def.claims?.units) {
|
|
369
|
+
const held = this.heldIds();
|
|
370
|
+
for (const unit of pool) if (held.has(unit)) pool.delete(unit);
|
|
371
|
+
const preys = [];
|
|
372
|
+
for (let j = at + 1; j < ranked.length; j++) {
|
|
373
|
+
const other = ranked[j];
|
|
374
|
+
const hold = this.holds[other.def.id];
|
|
375
|
+
if (!hold?.units.length) continue;
|
|
376
|
+
const lead = tick < hold.until && !entry.urgent ? other.def.margin ?? this.margin : 0;
|
|
377
|
+
if (entry.score > other.score + lead) preys.push(other);
|
|
378
|
+
}
|
|
379
|
+
const takeable = new Set(pool);
|
|
380
|
+
for (const prey of preys) for (const unit of this.holds[prey.def.id].units) takeable.add(unit);
|
|
381
|
+
const available = view.mine.where((unit) => takeable.has(unit.id));
|
|
382
|
+
for (const chosen of def.claims.units(ai, available)) if (takeable.has(chosen.id) && !units.includes(chosen.id)) units.push(chosen.id);
|
|
383
|
+
if (!units.length) {
|
|
384
|
+
entry.why = "nothing to claim";
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
units.sort((a, b) => view.indexOf(view.byId(a)) - view.indexOf(view.byId(b)));
|
|
388
|
+
for (const unit of units) {
|
|
389
|
+
if (pool.delete(unit)) continue;
|
|
390
|
+
for (const prey of preys) {
|
|
391
|
+
const hold = this.holds[prey.def.id];
|
|
392
|
+
const index = hold.units.indexOf(unit);
|
|
393
|
+
if (index < 0) continue;
|
|
394
|
+
hold.units.splice(index, 1);
|
|
395
|
+
prey.lost = entry.urgent ? "urgent" : "beaten";
|
|
396
|
+
prey.lostTo = def.id;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const money = this.moneyOf(def);
|
|
402
|
+
if (money) ai.purse.reserve(def.id, money);
|
|
403
|
+
const commitment = def.commitment ?? this.commitment;
|
|
404
|
+
const hold = {
|
|
405
|
+
units,
|
|
406
|
+
...money && { money },
|
|
407
|
+
since: tick,
|
|
408
|
+
until: tick + Math.round(commitment * ai.session.tickRate),
|
|
409
|
+
score: entry.score
|
|
410
|
+
};
|
|
411
|
+
this.holds[def.id] = hold;
|
|
412
|
+
return hold;
|
|
413
|
+
}
|
|
414
|
+
/** The money a goal names, as a cost: a number is in the game's money */
|
|
415
|
+
moneyOf(def) {
|
|
416
|
+
const { ai } = this;
|
|
417
|
+
const asked = typeof def.claims?.money === "function" ? def.claims.money(ai) : def.claims?.money;
|
|
418
|
+
if (asked === void 0) return void 0;
|
|
419
|
+
if (typeof asked === "number") {
|
|
420
|
+
if (!(asked > 0)) return void 0;
|
|
421
|
+
const currency = ai.registry.currency ?? ai.registry.resources[0]?.id;
|
|
422
|
+
return currency === void 0 ? void 0 : { [currency]: asked };
|
|
423
|
+
}
|
|
424
|
+
return Object.keys(asked).length ? { ...asked } : void 0;
|
|
425
|
+
}
|
|
426
|
+
/** What a goal holds, as it is handed to it */
|
|
427
|
+
claimedOf(goal, hold, first) {
|
|
428
|
+
const { ai } = this;
|
|
429
|
+
const units = new UnitSet(ai.view, hold.units.map((id) => ai.view.byId(id)).filter((unit) => !!unit));
|
|
430
|
+
const squad = (name, of, options = {}) => {
|
|
431
|
+
const kept = ai.squads.named(name);
|
|
432
|
+
if (!kept || kept.owner !== goal) return ai.squads.make(name, of, {
|
|
433
|
+
...options,
|
|
434
|
+
owner: goal
|
|
435
|
+
});
|
|
436
|
+
kept.data.options = {
|
|
437
|
+
...ai.squads.defaults,
|
|
438
|
+
...options
|
|
439
|
+
};
|
|
440
|
+
return kept.add(of);
|
|
441
|
+
};
|
|
442
|
+
return {
|
|
443
|
+
units,
|
|
444
|
+
...hold.money && { money: hold.money },
|
|
445
|
+
began: hold.since,
|
|
446
|
+
first,
|
|
447
|
+
squad
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
heldIds() {
|
|
451
|
+
const held = /* @__PURE__ */ new Set();
|
|
452
|
+
for (const id in this.holds) for (const unit of this.holds[id].units) held.add(unit);
|
|
453
|
+
return held;
|
|
454
|
+
}
|
|
455
|
+
/** Every goal as the picker last saw it: score, considerations, what it holds, why it did not run */
|
|
456
|
+
report() {
|
|
457
|
+
const { view } = this.ai;
|
|
458
|
+
return [...this.entries.values()].map((entry) => {
|
|
459
|
+
const { def } = entry;
|
|
460
|
+
const hold = this.holds[def.id];
|
|
461
|
+
return {
|
|
462
|
+
id: def.id,
|
|
463
|
+
scope: def.scope ?? "army",
|
|
464
|
+
score: entry.score,
|
|
465
|
+
considerations: entry.considerations,
|
|
466
|
+
picked: entry.picked,
|
|
467
|
+
urgent: entry.urgent,
|
|
468
|
+
...hold && { held: {
|
|
469
|
+
units: hold.units.length,
|
|
470
|
+
ids: [...hold.units],
|
|
471
|
+
strength: view.strength.sum(hold.units.map((id) => view.byId(id)).filter((unit) => !!unit)),
|
|
472
|
+
...hold.money && { money: { ...hold.money } },
|
|
473
|
+
since: hold.since,
|
|
474
|
+
until: hold.until
|
|
475
|
+
} },
|
|
476
|
+
...entry.why && { why: entry.why }
|
|
477
|
+
};
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/** What is held and on cooldown, for a save */
|
|
481
|
+
/** Whether it has anything to remember now: one that does not is left out of a save */
|
|
482
|
+
remembers() {
|
|
483
|
+
return this.list().length > 0 || Object.keys(this.all()).length > 0;
|
|
484
|
+
}
|
|
485
|
+
/** Gives what the goals remember, the holds and the rest, as plain data for a save of the brain */
|
|
486
|
+
save() {
|
|
487
|
+
const holds = {};
|
|
488
|
+
for (const id in this.holds) {
|
|
489
|
+
const hold = this.holds[id];
|
|
490
|
+
holds[id] = {
|
|
491
|
+
...hold,
|
|
492
|
+
units: [...hold.units],
|
|
493
|
+
...hold.money && { money: { ...hold.money } }
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
return {
|
|
497
|
+
v: 1,
|
|
498
|
+
holds,
|
|
499
|
+
cooldowns: { ...this.cooldowns }
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/** Takes back what `save` gave: whether it was read */
|
|
503
|
+
restore(memory) {
|
|
504
|
+
const given = memory;
|
|
505
|
+
if (!given || typeof given !== "object" || given.v !== 1) return false;
|
|
506
|
+
this.holds = {};
|
|
507
|
+
for (const id in given.holds ?? {}) {
|
|
508
|
+
const hold = given.holds[id];
|
|
509
|
+
this.holds[id] = {
|
|
510
|
+
...hold,
|
|
511
|
+
units: [...hold.units ?? []],
|
|
512
|
+
...hold.money && { money: { ...hold.money } }
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
this.cooldowns = { ...given.cooldowns ?? {} };
|
|
516
|
+
return true;
|
|
517
|
+
}
|
|
518
|
+
/** What the debug tools show: the report, the best, and the picker's numbers */
|
|
519
|
+
inspect() {
|
|
520
|
+
return {
|
|
521
|
+
goals: this.report(),
|
|
522
|
+
...this.best !== void 0 && { goal: this.best }
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
/** Why a goal stopped, in words, for the decision log */
|
|
527
|
+
function stopped(why, by) {
|
|
528
|
+
switch (why) {
|
|
529
|
+
case "beaten": return by ? `beaten by ${by}` : "beaten";
|
|
530
|
+
case "urgent": return by ? `its units taken by ${by}, urgent` : "its units taken by an urgent goal";
|
|
531
|
+
case "done": return "done, or nothing left to run with";
|
|
532
|
+
case "told": return "its units taken by a rule or a module";
|
|
533
|
+
case "removed": return "taken out of the brain";
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
/** A number as it is, and 0 for what is none (NaN, infinite): the picker never picks on nonsense */
|
|
537
|
+
var finite = (x) => Number.isFinite(x) ? x : 0;
|
|
538
|
+
/** A curved value or a score: finite, and nothing under 0 */
|
|
539
|
+
var positive = (x) => Number.isFinite(x) && x > 0 ? x : 0;
|
|
540
|
+
/**
|
|
541
|
+
* The goals module: runs the brain's picker (`ai.goals.think`) in its place among the brain's modules, after what
|
|
542
|
+
* reads the game and before what acts on orders. With goals of its own to add to the brain's
|
|
543
|
+
*
|
|
544
|
+
* @beta
|
|
545
|
+
*/
|
|
546
|
+
var goals = (defs = []) => defineModule({
|
|
547
|
+
id: "goals",
|
|
548
|
+
make: (ai) => {
|
|
549
|
+
ai.goals.add(...defs);
|
|
550
|
+
return {
|
|
551
|
+
id: "goals",
|
|
552
|
+
phase: "act",
|
|
553
|
+
think: () => ai.goals.think()
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
//#endregion
|
|
558
|
+
export { Goals, consider, curve, defineGoal, goals };
|
|
559
|
+
|
|
560
|
+
//# sourceMappingURL=goals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goals.js","names":[],"sources":["../../src/ai/goals.ts"],"sourcesContent":["import type { Cost } from '#engine/defs'\nimport type { AiArea } from './area'\nimport { exp } from '#engine/exactMath'\nimport type { EntityState } from '#engine/session/protocol'\nimport { type Brain } from './brain'\nimport { type AiModule, type AiModuleDef, defineModule } from './module'\nimport { considerationsLine } from './report'\nimport type { Squad, SquadOptions } from './squads'\nimport { UnitSet } from './view'\n\n/*\n * Goals that score themselves (AI plan, B1): how a computer player decides what to do with what it has. The old way\n * was a ladder of ifs (`if (underAttack) defend() else if (ready) attack()`), and the first version of the melee\n * player's goals was a constant each (defend 1, attack 0.8): one ran, for the whole army, and nothing weighed \"a small\n * raid at my expansion while my army is away\" against \"their army at my gate\". This is the **utility** pattern,\n * written down once:\n *\n * - A **goal** is something the computer could do (`defineGoal`): defend, attack, creep, scout, raid their workers.\n * - It scores itself from **considerations**: each a question over what it sees that gives a number (how many enemies\n * at my buildings; the strength of my idle army over my whole army; seconds since their base was looked at), passed\n * through a **curve** that says how much that number matters, as 0..1 (`curve.linear`, `saturate`, `inverse`,\n * `step`, `band`, `custom`). The goal's **score** is the product of its considerations times its `weight`: a product\n * is a soft AND, so a goal that wants several things at once scores high only when it has them all, and a\n * consideration at 0 vetoes it outright (no worker seen: no raid), which saves every goal an `if`.\n * - The **picker** (`Goals.think`, once a think) scores every goal, takes them best first, and gives each what it\n * **claims**: units from the pool (what no goal holds) and money; the next goal sees what is left, until nothing\n * scores above `min`. So several goals run at once on different units, and a goal that claims nothing of what it\n * asked for is not picked.\n * - **Commitment**, or hysteresis: two goals at 0.61 and 0.60 would swap every think and the army would walk in\n * circles. A picked goal keeps its claim for `commitment` seconds unless another scores more than it by `margin`;\n * after that, anything that scores more may take from it. `urgent` goals (the melee player's defend, when the raid is\n * stronger than what the army out holds) break any commitment the moment they score above the committed goal.\n * - **Who may move a unit, in one place.** A unit is held by one goal at a time (`holder`), taken from the pool when\n * the goal is picked and given back when it stops; a rule (B2) or the defence (C4) that wants a unit takes it\n * through `take`, and the goal that held it is told (`stop('told')`). Squads (C1) are made of what a goal holds.\n *\n * The report of it all (`report`: every goal's score, its considerations with their raw and curved values, what it\n * holds and why it was not picked) is what the debug tools show, so \"why did it do that\" is read, not guessed. What\n * is held is plain data kept in the brain's memory (`save`, `restore`), ticks and ids: a save keeps the army's goal\n */\n\n/**\n * A response curve: a number (how many, how strong, how long) to how much it matters, 0..1\n *\n * @beta\n */\nexport type Curve = (x: number) => number\n\nconst clamp01 = (x: number) => (x > 1 ? 1 : x > 0 ? x : 0)\n\n/**\n * The usual response curves, each a line (`consider(name, read, curve.saturate(6))`): how a raw number becomes \"how\n * much do I care\". A curve gives 0..1; what gives nonsense (NaN) counts as 0\n *\n * @beta\n */\nexport const curve = {\n\t/** A straight line from 0 at 0 to 1 at `max` (1 when left out: for a ratio), flat beyond: twice the units, twice the care, up to a point */\n\tlinear:\n\t\t(max = 1): Curve =>\n\t\t(x) =>\n\t\t\tclamp01(x / max),\n\t/** 1 − e^(−x/k): rises fast, then levels off at 1 (0.63 at `k`, 0.86 at `2k`): the sixth worker seen matters less than the first */\n\tsaturate:\n\t\t(k: number): Curve =>\n\t\t(x) =>\n\t\t\tx <= 0 ? 0 : 1 - exp(-x / k),\n\t/** k / (k + x): 1 at 0, falling to a half at `k` and towards 0: the less there is of it, the better (how held their base is) */\n\tinverse:\n\t\t(k: number): Curve =>\n\t\t(x) =>\n\t\t\tx <= 0 ? 1 : k / (k + x),\n\t/** 0 below `at`, 1 from it on: a threshold (a wave is ready at so many units), an on-off (any intruder at all: `step(1)`) */\n\tstep:\n\t\t(at: number): Curve =>\n\t\t(x) =>\n\t\t\tx >= at ? 1 : 0,\n\t/** 1 between `low` and `high`, 0 outside: a window (an army of between 4 and 12) */\n\tband:\n\t\t(low: number, high: number): Curve =>\n\t\t(x) =>\n\t\t\tx >= low && x <= high ? 1 : 0,\n\t/** A shape of the game's own: whatever the function gives, kept to 0..1 */\n\tcustom:\n\t\t(fn: (x: number) => number): Curve =>\n\t\t(x) =>\n\t\t\tclamp01(fn(x))\n} as const\n\n/**\n * One question a goal asks of what it sees, and how much the answer matters: `read` gives the raw number, `curve`\n * turns it into 0..1. The report keeps both\n *\n * @beta\n */\nexport interface Consideration {\n\t/** What it asks, for the report: \"intruders at my buildings\" */\n\tname: string\n\t/** The raw number, read from the brain each think: cheap, or cached for the think (`ai.cache`) */\n\tread: (ai: Brain) => number\n\t/** How much the number matters, 0..1 */\n\tcurve: Curve\n}\n\n/**\n * A consideration: a question with a name, and the curve that says how much its answer matters (`curve.linear()`\n * when left out: the number is a ratio already)\n *\n * @beta\n */\nexport function consider(name: string, read: (ai: Brain) => number, shape: Curve = curve.linear()): Consideration {\n\treturn { name, read, curve: shape }\n}\n\n/**\n * What a goal is about, and so what it competes with: `army` goals claim units, `economy` goals money, `squad` and\n * `hero` goals are about one of those (scored once each until squads (C1) and heroes (C2) score them apiece), or a\n * game's own word\n *\n * @beta\n */\nexport type GoalScope = 'army' | 'economy' | 'squad' | 'hero' | (string & {})\n\n/**\n * Why a goal lost its claim (`GoalDef.stop`): `beaten` by one that scored more by the margin, `urgent` by an urgent\n * one, `done` as its own score fell to nothing, `told` by a rule or a module that took its units, `removed` from the\n * brain\n *\n * @beta\n */\nexport type StopReason = 'beaten' | 'urgent' | 'done' | 'told' | 'removed'\n\n/**\n * What a goal claims to run: units from the pool and money from the purse. The picker gives each goal what it asks\n * of what is left, best goal first\n *\n * @beta\n */\nexport interface GoalClaims {\n\t/**\n\t * The units it takes, chosen from what it may have (`available`: the pool, and what goals it may take from hold):\n\t * the nearest six fighters, one scout, everything. A goal that asks for units and gets none is not picked\n\t */\n\tunits?: (ai: Brain, available: UnitSet) => Iterable<EntityState>\n\t/**\n\t * The money it holds while it runs, in the game's money (`Registry.currency`) as a number, or as a cost by resource;\n\t * a function for one that depends. Held against the purse (`Goals.reserved`), given back when the goal stops\n\t */\n\tmoney?: number | Cost | ((ai: Brain) => number | Cost | undefined)\n}\n\n/**\n * What a picked goal was given (`GoalDef.run`): the units it holds this think (the dead and the lost dropped), the\n * money, when it was picked, and whether this is the first think it runs\n *\n * @beta\n */\nexport interface Claimed {\n\t/** The units it holds, as of this think's picture */\n\tunits: UnitSet\n\t/** The money it holds, where it asked for any */\n\tmoney?: Cost\n\t/** The tick it was picked at */\n\tbegan: number\n\t/** Whether this is the first think it runs: when its orders are to be sent, once */\n\tfirst: boolean\n\t/**\n\t * Makes a squad the goal owns (`ai.squads.make` with the goal as its `owner`): when the goal stops, its squads go.\n\t * Called again for a name the goal has a squad of already (a run each think), it is that squad, kept as it is (its\n\t * task, its `size`), the units given added to it and its options those given now\n\t */\n\tsquad(name: string, units: Iterable<EntityState | number>, options?: SquadOptions): Squad\n}\n\n/**\n * A goal: something the computer could do, scored by its considerations, run with what it claims (`defineGoal`)\n *\n * @beta\n */\nexport interface GoalDef {\n\t/** Unique among the brain's goals, prefixed as components are (the engine's `ai.defend`, a game's `mygame.raid`) */\n\tid: string\n\t/** What it is about: `army` when left out */\n\tscope?: GoalScope\n\t/** Its questions: the score is their product (a soft AND: one at 0 vetoes the goal), times the weight */\n\tconsiderations: Consideration[]\n\t/** What it is worth against the other goals at their best: 1 when left out */\n\tweight?: number\n\t/** The score under which it is not picked: the picker's (`PickingOptions.min`) when left out */\n\tmin?: number\n\t/** What it takes to run: units, money. None: it runs on its score alone, holding nothing */\n\tclaims?: GoalClaims\n\t/**\n\t * Seconds it keeps its claim once picked, unless another scores more than it by the margin, or an urgent one scores\n\t * more at all. The picker's default when left out. Hysteresis: without it two close goals swap every think\n\t */\n\tcommitment?: number\n\t/** How much more another goal must score to take from this one within its commitment: the picker's when left out */\n\tmargin?: number\n\t/** Whether it may break another goal's commitment as soon as it scores more: a raid that cannot wait */\n\turgent?: boolean | ((ai: Brain) => boolean)\n\t/** Seconds after it stops before it may be picked again */\n\tcooldown?: number\n\t/** What it does, each think it holds its claim: `claimed.first` on the first, where its orders are sent once and then watched */\n\trun(ai: Brain, claimed: Claimed): void\n\t/** Told when it loses its claim, and why: to let go of what it was doing */\n\tstop?(ai: Brain, why: StopReason, claimed: Claimed): void\n}\n\n/**\n * Defines a goal: checked, and given back as it is, for a brain's `goals`, `meleeBrain.with({ goals })`, or\n * `ai.goals.add`\n *\n * @beta\n */\nexport function defineGoal(def: GoalDef): GoalDef {\n\tif (!def.id) throw new Error('A goal needs an id')\n\tif (!Array.isArray(def.considerations)) throw new Error(`The goal \"${def.id}\" needs its considerations, as a list`)\n\tif (typeof def.run !== 'function') throw new Error(`The goal \"${def.id}\" needs a run`)\n\treturn def\n}\n\n/**\n * How a brain picks among its goals, where a goal does not say for itself (`BrainDef.picking`)\n *\n * @beta\n */\nexport interface PickingOptions {\n\t/** The score under which a goal is not picked: 0.05 when left out */\n\tmin?: number\n\t/** How much more a goal must score than a committed one to take from it: 0.15 when left out */\n\tmargin?: number\n\t/** Seconds a picked goal keeps its claim: 5 when left out */\n\tcommitment?: number\n}\n\n/**\n * What a goal holds while it runs: its units (ids, of the player's), its money, when it was picked and until when it\n * is committed. Plain data, kept in the brain's memory\n *\n * @beta\n */\nexport interface Hold {\n\t/** The units it holds, by id, in the picture's order */\n\tunits: number[]\n\t/** The money it holds (`GoalClaims.money`) */\n\tmoney?: Cost\n\t/** The tick it was picked at */\n\tsince: number\n\t/** The tick its commitment ends at: for a rule's or a module's hold (`take` with `by`), the tick it lets go at */\n\tuntil: number\n\t/** For a rule's or a module's hold: kept until let go of (`release`), whatever `until` says. A squad of one's own holds so */\n\tkept?: true\n\t/** What it scored when picked */\n\tscore: number\n}\n\n/**\n * What the goals remember between thinks: what each holds, and until when each is on cooldown\n *\n * @beta\n */\nexport interface GoalsMemory {\n\t/** The version of this shape */\n\tv: 1\n\t/** What each goal holds, by goal id */\n\tholds: Record<string, Hold>\n\t/** The tick each goal on cooldown may be picked again at, by goal id */\n\tcooldowns: Record<string, number>\n}\n\n/**\n * One goal as the picker last saw it: for the debug tools, and for \"why did it do that\"\n *\n * @beta\n */\nexport interface GoalReport {\n\t/** The goal */\n\tid: string\n\t/** What it is about */\n\tscope: GoalScope\n\t/** Its score: the considerations' product, weighed */\n\tscore: number\n\t/**\n\t * Each question, its raw answer and how much that mattered. One after a question answered 0 is not asked (the goal\n\t * is vetoed already): `asked: false`, its numbers 0\n\t */\n\tconsiderations: { name: string; value: number; curved: number; asked?: false }[]\n\t/** Whether it ran this think */\n\tpicked: boolean\n\t/** Whether it may break a commitment now */\n\turgent: boolean\n\t/** What it holds: how many units (and which, `ids`), how strong together, the money, since when and until when (ticks) */\n\theld?: { units: number; ids: number[]; strength: number; money?: Cost; since: number; until: number }\n\t/** Why it did not run, where it scored enough: `cooldown`, `nothing to claim`, or what it lost its claim to */\n\twhy?: string\n}\n\n/** Where a goal's definition is kept, with what the picker found of it this think */\ninterface Entry {\n\tdef: GoalDef\n\t/** Its place in the order added: the tie-breaker among equal scores, so that two thinks pick alike */\n\torder: number\n\tscore: number\n\turgent: boolean\n\tconsiderations: GoalReport['considerations']\n\tpicked: boolean\n\twhy?: string\n\t/** Why it lost units this think, where it did: its stop reason once it has none left */\n\tlost?: StopReason\n\t/** The goal it lost units to this think, for the decision log */\n\tlostTo?: string\n}\n\nconst MIN = 0.05\nconst MARGIN = 0.15\nconst COMMITMENT = 5\n\n/**\n * The brain's goals and their picker (`ai.goals`): what the computer could do, scored each think, the best given what\n * they claim (`think`, once a think: run by the `goals()` module, or by a module of the brain's own in its place among\n * the others). What each holds is read here (`held`, `holds`, `holder`, `pool`), taken by a rule or a module\n * (`take`), and reported (`report`)\n *\n * @beta\n */\nexport class Goals implements AiArea {\n\t/** Its id among the brain's areas: what its memory and its report are kept under */\n\treadonly id = 'goals'\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 what the computer player’s goals held in a shape this brain does not read: they start afresh'\n\n\t/** How much each goal scored this think, by id: what the debug tools showed before the report */\n\tscores: Record<string, number> = {}\n\t/** The goal that scored highest above the minimum this think: what the army is on. None when nothing is worth doing */\n\tbest: string | undefined\n\tprivate readonly entries = new Map<string, Entry>()\n\tprivate holds: Record<string, Hold> = {}\n\tprivate cooldowns: Record<string, number> = {}\n\tprivate added = 0\n\tprivate thoughtAt = -1\n\tprivate readonly min: number\n\tprivate readonly margin: number\n\tprivate readonly commitment: number\n\n\tconstructor(\n\t\t/** The brain they are the goals of */\n\t\treadonly ai: Brain,\n\t\toptions: PickingOptions = {}\n\t) {\n\t\tthis.min = options.min ?? MIN\n\t\tthis.margin = options.margin ?? MARGIN\n\t\tthis.commitment = options.commitment ?? COMMITMENT\n\t}\n\n\t/** Adds goals to pick among: a brain's own (`BrainDef.goals`), the seat's (`AiOptions.goals`), a module's */\n\tadd(...defs: GoalDef[]): void {\n\t\tfor (const def of defs) {\n\t\t\tif (this.entries.has(def.id)) throw new Error(`The brain \"${this.ai.def.id}\" has two goals called \"${def.id}\"`)\n\t\t\tthis.entries.set(def.id, { def, order: this.added++, score: 0, urgent: false, considerations: [], picked: false })\n\t\t}\n\t}\n\n\t/** Takes a goal out: what it held goes back to the pool, and it is told `removed`. Whether there was one */\n\tremove(id: string): boolean {\n\t\tconst entry = this.entries.get(id)\n\t\tif (!entry) return false\n\t\tthis.release(id, 'removed')\n\t\tthis.entries.delete(id)\n\t\treturn true\n\t}\n\n\t/** The goals, as added */\n\tlist(): GoalDef[] {\n\t\treturn [...this.entries.values()].map((entry) => entry.def)\n\t}\n\n\t/** A goal by id */\n\tget(id: string): GoalDef | undefined {\n\t\treturn this.entries.get(id)?.def\n\t}\n\n\t/** What a goal holds, while it does */\n\theld(id: string): Hold | undefined {\n\t\treturn this.holds[id]\n\t}\n\n\t/** What every goal holds, by goal id */\n\tall(): Readonly<Record<string, Hold>> {\n\t\treturn this.holds\n\t}\n\n\t/** The goal that holds a unit, by the unit's id: none for a unit in the pool */\n\tholder(unit: number): string | undefined {\n\t\tfor (const id in this.holds) if (this.holds[id].units.includes(unit)) return id\n\t\treturn undefined\n\t}\n\n\t/** The player's units no goal holds, as of the think's picture: what a goal picked next may claim */\n\tpool(): UnitSet {\n\t\tconst held = this.heldIds()\n\t\tconst { mine } = this.ai.view\n\t\treturn held.size ? mine.where((entity) => !held.has(entity.id)) : mine\n\t}\n\n\t/** The money the goals hold together (`GoalClaims.money`): held in the purse (`ai.purse`), which takes it off what is free */\n\treserved(): Cost {\n\t\tconst sum: Cost = {}\n\t\tfor (const id in this.holds) {\n\t\t\tconst { money } = this.holds[id]\n\t\t\tfor (const kind in money) sum[kind] = (sum[kind] ?? 0) + money[kind]\n\t\t}\n\t\treturn sum\n\t}\n\n\t/**\n\t * Takes units from whatever goals hold them, for a rule (B2) or a module (the defence, C4) that wants them: a goal\n\t * left with none is told why (`told` when left out). Those of them that were held, by id.\n\t *\n\t * With `by`, the units are then held by that rule or module itself (`by.id`, which names no goal: `rule:attack`),\n\t * for `by.seconds` (30 when left out) or until `release(by.id)`: no goal may claim them meanwhile, for a rule goes\n\t * before the goals (the one order of who may move a unit: goals, then rules take, then the defence; micro never\n\t * retasks). Units taken again by the same id are added to what it holds, and its time starts again. `seconds:\n\t * Infinity` holds them until let go of (`release`, `drop`): what a squad that is no goal's holds its units by\n\t */\n\ttake(units: Iterable<number>, why: StopReason = 'told', by?: { id: string; seconds?: number }): number[] {\n\t\tconst wanted = new Set(units)\n\t\tconst taken: number[] = []\n\t\tfor (const id in this.holds) {\n\t\t\tif (id === by?.id) continue\n\t\t\tconst hold = this.holds[id]\n\t\t\tconst kept = hold.units.filter((unit) => !wanted.has(unit))\n\t\t\tif (kept.length === hold.units.length) continue\n\t\t\ttaken.push(...hold.units.filter((unit) => wanted.has(unit)))\n\t\t\thold.units = kept\n\t\t\tif (!kept.length) this.release(id, why)\n\t\t}\n\t\tif (by) {\n\t\t\tif (this.entries.has(by.id)) throw new Error(`\"${by.id}\" is a goal of the brain: what a rule holds needs a name of its own`)\n\t\t\tconst { tick, session } = this.ai\n\t\t\t// what it held and is gone is let go of here: a brain with no goals has no picker to do it each think\n\t\t\tconst kept = (this.holds[by.id]?.units ?? []).filter((unit) => this.ai.view.mine.has(unit))\n\t\t\tconst all = [...kept, ...[...wanted].filter((unit) => !kept.includes(unit) && this.ai.view.mine.has(unit))]\n\t\t\tall.sort((a, b) => this.ai.view.indexOf(this.ai.view.byId(a)!) - this.ai.view.indexOf(this.ai.view.byId(b)!))\n\t\t\tconst seconds = by.seconds ?? 30\n\t\t\t// for ever is no number a save can keep: such a hold is `kept`, and its `until` is when it was taken\n\t\t\tconst forever = seconds === Infinity\n\t\t\tthis.holds[by.id] = {\n\t\t\t\tunits: all,\n\t\t\t\tsince: this.holds[by.id]?.since ?? tick,\n\t\t\t\tuntil: forever ? tick : tick + Math.round(seconds * session.tickRate),\n\t\t\t\tscore: 1,\n\t\t\t\t...(forever && { kept: true as const })\n\t\t\t}\n\t\t}\n\t\treturn taken\n\t}\n\n\t/**\n\t * Adds units from the pool (what nothing holds) to what a goal, a rule or a module holds: a squad's reinforcements\n\t * (`Squad.reinforce`). What another holds is passed over: `take` is for that. Those given, by id\n\t */\n\tgive(id: string, units: Iterable<number>): number[] {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return []\n\t\tconst { view } = this.ai\n\t\tconst held = this.heldIds()\n\t\tconst given: number[] = []\n\t\tfor (const unit of units) if (!held.has(unit) && view.mine.has(unit) && !given.includes(unit)) given.push(unit)\n\t\tif (!given.length) return given\n\t\thold.units = hold.units.filter((unit) => view.mine.has(unit))\n\t\thold.units.push(...given)\n\t\thold.units.sort((a, b) => view.indexOf(view.byId(a)!) - view.indexOf(view.byId(b)!))\n\t\treturn given\n\t}\n\n\t/**\n\t * Lets go of some of what a goal, a rule or a module holds: they go back to the pool. One left with none is released,\n\t * told why (`done` when left out). Those let go of, by id\n\t */\n\tdrop(id: string, units: Iterable<number>, why: StopReason = 'done'): number[] {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return []\n\t\tconst gone = new Set(units)\n\t\tconst dropped = hold.units.filter((unit) => gone.has(unit))\n\t\tif (!dropped.length) return dropped\n\t\thold.units = hold.units.filter((unit) => !gone.has(unit))\n\t\tif (!hold.units.length) this.release(id, why)\n\t\treturn dropped\n\t}\n\n\t/** What rules and modules hold (`take` with `by`), by their id: not goals' */\n\ttaken(): Record<string, Hold> {\n\t\tconst result: Record<string, Hold> = {}\n\t\tfor (const id in this.holds) if (!this.entries.has(id)) result[id] = this.holds[id]\n\t\treturn result\n\t}\n\n\t/** Whether a unit is held by a rule or a module rather than by a goal (`take` with `by`): what nothing else is to give orders to */\n\truled(unit: number): boolean {\n\t\tfor (const id in this.holds) if (!this.entries.has(id) && this.holds[id].units.includes(unit)) return true\n\t\treturn false\n\t}\n\n\t/** Takes a goal's claim away, telling it why (`told` when left out): its units go back to the pool. Whether it held one */\n\trelease(id: string, why: StopReason = 'told'): boolean {\n\t\tconst hold = this.holds[id]\n\t\tif (!hold) return false\n\t\tdelete this.holds[id]\n\t\tif (hold.money) this.ai.purse.release(id)\n\t\tconst entry = this.entries.get(id)\n\t\tif (!entry) {\n\t\t\tthis.ai.decide(`${id} lets go of ${hold.units.length === 1 ? '1 unit' : `${hold.units.length} units`}`, { kind: 'rule' })\n\t\t\treturn true\n\t\t}\n\t\tthis.ai.decide(`${id} stopped: ${stopped(why, entry.lostTo)}`, { kind: 'goal', goal: id })\n\t\tentry.def.stop?.(this.ai, why, this.claimedOf(id, hold, false))\n\t\tconst cooldown = entry.def.cooldown ?? 0\n\t\tif (cooldown > 0) this.cooldowns[id] = this.ai.tick + Math.round(cooldown * this.ai.session.tickRate)\n\t\treturn true\n\t}\n\n\t/**\n\t * The think: every goal scored (its considerations read, curved, multiplied, weighed), the goals that hold a claim\n\t * kept to it or beaten, the rest picked best first with what they claim, and each picked one run. Once a think: a\n\t * second call in the same think does nothing\n\t */\n\tthink(): void {\n\t\tconst { ai } = this\n\t\tconst { tick, view } = ai\n\t\tif (this.thoughtAt === tick) return\n\t\tthis.thoughtAt = tick\n\n\t\t// what is held and no longer mine (dead, given away) is let go of first\n\t\tfor (const id in this.holds) {\n\t\t\tconst hold = this.holds[id]\n\t\t\tconst entry = this.entries.get(id)\n\t\t\tconst alive = hold.units.filter((unit) => view.mine.has(unit))\n\t\t\tif (alive.length !== hold.units.length) hold.units = alive\n\t\t\t// what a rule holds is its own until its time is up, or nothing of it is left\n\t\t\tif (!entry) {\n\t\t\t\tif ((!hold.kept && tick >= hold.until) || !alive.length) this.release(id, 'done')\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// a goal whose every unit died has nothing left to run with\n\t\t\tif (!alive.length && entry.def.claims?.units) this.release(id, 'done')\n\t\t}\n\t\tfor (const id in this.cooldowns) if (this.cooldowns[id] <= tick) delete this.cooldowns[id]\n\n\t\t// every goal scored, whether or not it can run: the report says what each was worth\n\t\tconst entries = [...this.entries.values()]\n\t\tthis.scores = {}\n\t\tthis.best = undefined\n\t\tlet bestScore = this.min\n\t\tfor (const entry of entries) {\n\t\t\tthis.score(entry)\n\t\t\tthis.scores[entry.def.id] = entry.score\n\t\t\tif (entry.score > bestScore) {\n\t\t\t\tbestScore = entry.score\n\t\t\t\tthis.best = entry.def.id\n\t\t\t}\n\t\t}\n\n\t\t// a held goal whose score fell to nothing is done; one on cooldown or under the minimum is out of the running\n\t\tfor (const entry of entries) {\n\t\t\tconst { id } = entry.def\n\t\t\tif (this.holds[id] && entry.score <= (entry.def.min ?? this.min)) this.release(id, 'done')\n\t\t}\n\n\t\t// best first; among equals, as added, so that two thinks of one picture pick alike\n\t\tconst ranked = entries.filter((entry) => entry.score > (entry.def.min ?? this.min)).sort((a, b) => b.score - a.score || a.order - b.order)\n\t\tconst pool = new Set(this.pool().ids())\n\t\tfor (let i = 0; i < ranked.length; i++) {\n\t\t\tconst entry = ranked[i]\n\t\t\tconst { def } = entry\n\t\t\tconst { id } = def\n\t\t\tif (this.cooldowns[id] !== undefined) {\n\t\t\t\tentry.why = 'cooldown'\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlet hold: Hold | undefined = this.holds[id]\n\t\t\tlet first = false\n\t\t\tif (hold) {\n\t\t\t\t// it keeps what it holds, less what the goals above it took: with nothing left of what it claimed, it is beaten\n\t\t\t\tif (!hold.units.length && def.claims?.units) {\n\t\t\t\t\tthis.release(id, entry.lost ?? 'beaten')\n\t\t\t\t\tentry.why = entry.lost === 'urgent' ? 'taken by an urgent goal' : 'beaten'\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\thold = this.claim(entry, ranked, i, pool)\n\t\t\t\tif (!hold) continue\n\t\t\t\tfirst = true\n\t\t\t}\n\t\t\tentry.picked = true\n\t\t\tconst claimed = this.claimedOf(id, hold, first)\n\t\t\tif (first) this.decided(entry, claimed)\n\t\t\tdef.run(ai, claimed)\n\t\t}\n\t}\n\n\t/**\n\t * A goal's score this think: each consideration read and curved, their product, the weight, the game's say. Once a\n\t * consideration answers 0 the goal is vetoed, and the ones after it are not asked: put the cheap questions first\n\t */\n\tprivate score(entry: Entry): void {\n\t\tconst { ai } = this\n\t\tconst { def } = entry\n\t\tlet product = 1\n\t\tentry.considerations = []\n\t\tfor (const consideration of def.considerations) {\n\t\t\tif (product === 0) {\n\t\t\t\tentry.considerations.push({ name: consideration.name, value: 0, curved: 0, asked: false })\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst value = finite(consideration.read(ai))\n\t\t\tconst curved = positive(consideration.curve(value))\n\t\t\tentry.considerations.push({ name: consideration.name, value, curved })\n\t\t\tproduct *= curved\n\t\t}\n\t\t// its weight, and what the profile says it weighs (a personality's leanings: `{ attack: 1.3 }`)\n\t\t// a weight of the game's or the profile's that is no number scores nothing, as a consideration's does\n\t\tlet score = positive(product * (def.weight ?? 1) * (ai.profile.weights?.[def.id] ?? 1))\n\t\tentry.score = score\n\t\t// whether it may break a commitment: asked only of a goal in the running\n\t\tentry.urgent = score > (def.min ?? this.min) && (typeof def.urgent === 'function' ? def.urgent(ai) : !!def.urgent)\n\t\tentry.picked = false\n\t\tentry.why = undefined\n\t\tentry.lost = undefined\n\t\tentry.lostTo = undefined\n\t}\n\n\t/** Writes down a goal picked anew, for the decision log: its score, what it holds, its considerations */\n\tprivate decided(entry: Entry, claimed: Claimed): void {\n\t\tconst { def } = entry\n\t\tconst units = def.claims?.units ? ` (${claimed.units.length === 1 ? '1 unit' : `${claimed.units.length} units`})` : ''\n\t\tconst reasons = considerationsLine(entry)\n\t\tthis.ai.decide(`${def.id} picked at ${entry.score.toFixed(2)}${units}${entry.urgent ? ', urgent' : ''}${reasons && `: ${reasons}`}`, {\n\t\t\tkind: 'goal',\n\t\t\tgoal: def.id\n\t\t})\n\t}\n\n\t/**\n\t * What a goal picked anew takes: the units it chooses from the pool and from the holds of goals ranked below it\n\t * that it may take from (by the margin within their commitment, by any lead after it, and by any lead at all for an\n\t * urgent goal), and the money it names. Nothing where it asked for units and chose none\n\t */\n\tprivate claim(entry: Entry, ranked: Entry[], at: number, pool: Set<number>): Hold | undefined {\n\t\tconst { ai } = this\n\t\tconst { def } = entry\n\t\tconst { view, tick } = ai\n\t\tconst units: number[] = []\n\t\tif (def.claims?.units) {\n\t\t\t// what the goals run before it gave themselves since the pool was read (a squad reinforced) is no longer the pool's\n\t\t\tconst held = this.heldIds()\n\t\t\tfor (const unit of pool) if (held.has(unit)) pool.delete(unit)\n\t\t\t// whose units it may take, by the rules of commitment\n\t\t\tconst preys: Entry[] = []\n\t\t\tfor (let j = at + 1; j < ranked.length; j++) {\n\t\t\t\tconst other = ranked[j]\n\t\t\t\tconst hold = this.holds[other.def.id]\n\t\t\t\tif (!hold?.units.length) continue\n\t\t\t\tconst committed = tick < hold.until\n\t\t\t\tconst lead = committed && !entry.urgent ? (other.def.margin ?? this.margin) : 0\n\t\t\t\tif (entry.score > other.score + lead) preys.push(other)\n\t\t\t}\n\t\t\tconst takeable = new Set(pool)\n\t\t\tfor (const prey of preys) for (const unit of this.holds[prey.def.id].units) takeable.add(unit)\n\t\t\tconst available = view.mine.where((unit) => takeable.has(unit.id))\n\t\t\tfor (const chosen of def.claims.units(ai, available)) if (takeable.has(chosen.id) && !units.includes(chosen.id)) units.push(chosen.id)\n\t\t\tif (!units.length) {\n\t\t\t\tentry.why = 'nothing to claim'\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tunits.sort((a, b) => view.indexOf(view.byId(a)!) - view.indexOf(view.byId(b)!))\n\t\t\tfor (const unit of units) {\n\t\t\t\tif (pool.delete(unit)) continue\n\t\t\t\tfor (const prey of preys) {\n\t\t\t\t\tconst hold = this.holds[prey.def.id]\n\t\t\t\t\tconst index = hold.units.indexOf(unit)\n\t\t\t\t\tif (index < 0) continue\n\t\t\t\t\thold.units.splice(index, 1)\n\t\t\t\t\tprey.lost = entry.urgent ? 'urgent' : 'beaten'\n\t\t\t\t\tprey.lostTo = def.id\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst money = this.moneyOf(def)\n\t\t// held against the purse from now: nothing of the think spends what the goal holds\n\t\tif (money) ai.purse.reserve(def.id, money)\n\t\tconst commitment = def.commitment ?? this.commitment\n\t\tconst hold: Hold = {\n\t\t\tunits,\n\t\t\t...(money && { money }),\n\t\t\tsince: tick,\n\t\t\tuntil: tick + Math.round(commitment * ai.session.tickRate),\n\t\t\tscore: entry.score\n\t\t}\n\t\tthis.holds[def.id] = hold\n\t\treturn hold\n\t}\n\n\t/** The money a goal names, as a cost: a number is in the game's money */\n\tprivate moneyOf(def: GoalDef): Cost | undefined {\n\t\tconst { ai } = this\n\t\tconst asked = typeof def.claims?.money === 'function' ? def.claims.money(ai) : def.claims?.money\n\t\tif (asked === undefined) return undefined\n\t\tif (typeof asked === 'number') {\n\t\t\tif (!(asked > 0)) return undefined\n\t\t\tconst currency = ai.registry.currency ?? ai.registry.resources[0]?.id\n\t\t\treturn currency === undefined ? undefined : { [currency]: asked }\n\t\t}\n\t\treturn Object.keys(asked).length ? { ...asked } : undefined\n\t}\n\n\t/** What a goal holds, as it is handed to it */\n\tprivate claimedOf(goal: string, hold: Hold, first: boolean): Claimed {\n\t\tconst { ai } = this\n\t\tconst units = new UnitSet(\n\t\t\tai.view,\n\t\t\thold.units.map((id) => ai.view.byId(id)).filter((unit): unit is EntityState => !!unit)\n\t\t)\n\t\t// the goal's squad of that name, kept: called again (each think) it is the same squad, made up with what is given\n\t\tconst squad = (name: string, of: Iterable<EntityState | number>, options: SquadOptions = {}) => {\n\t\t\tconst kept = ai.squads.named(name)\n\t\t\tif (!kept || kept.owner !== goal) return ai.squads.make(name, of, { ...options, owner: goal })\n\t\t\tkept.data.options = { ...ai.squads.defaults, ...options }\n\t\t\treturn kept.add(of)\n\t\t}\n\t\treturn { units, ...(hold.money && { money: hold.money }), began: hold.since, first, squad }\n\t}\n\n\tprivate heldIds(): Set<number> {\n\t\tconst held = new Set<number>()\n\t\tfor (const id in this.holds) for (const unit of this.holds[id].units) held.add(unit)\n\t\treturn held\n\t}\n\n\t/** Every goal as the picker last saw it: score, considerations, what it holds, why it did not run */\n\treport(): GoalReport[] {\n\t\tconst { view } = this.ai\n\t\treturn [...this.entries.values()].map((entry) => {\n\t\t\tconst { def } = entry\n\t\t\tconst hold = this.holds[def.id]\n\t\t\treturn {\n\t\t\t\tid: def.id,\n\t\t\t\tscope: def.scope ?? 'army',\n\t\t\t\tscore: entry.score,\n\t\t\t\tconsiderations: entry.considerations,\n\t\t\t\tpicked: entry.picked,\n\t\t\t\turgent: entry.urgent,\n\t\t\t\t...(hold && {\n\t\t\t\t\theld: {\n\t\t\t\t\t\tunits: hold.units.length,\n\t\t\t\t\t\tids: [...hold.units],\n\t\t\t\t\t\tstrength: view.strength.sum(hold.units.map((id) => view.byId(id)).filter((unit): unit is EntityState => !!unit)),\n\t\t\t\t\t\t...(hold.money && { money: { ...hold.money } }),\n\t\t\t\t\t\tsince: hold.since,\n\t\t\t\t\t\tuntil: hold.until\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\t...(entry.why && { why: entry.why })\n\t\t\t}\n\t\t})\n\t}\n\n\t/** What is held and on cooldown, for a save */\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.list().length > 0 || Object.keys(this.all()).length > 0\n\t}\n\n\t/** Gives what the goals remember, the holds and the rest, as plain data for a save of the brain */\n\tsave(): GoalsMemory {\n\t\tconst holds: Record<string, Hold> = {}\n\t\tfor (const id in this.holds) {\n\t\t\tconst hold = this.holds[id]\n\t\t\tholds[id] = { ...hold, units: [...hold.units], ...(hold.money && { money: { ...hold.money } }) }\n\t\t}\n\t\treturn { v: 1, holds, cooldowns: { ...this.cooldowns } }\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 GoalsMemory | undefined\n\t\tif (!given || typeof given !== 'object' || given.v !== 1) return false\n\t\tthis.holds = {}\n\t\tfor (const id in given.holds ?? {}) {\n\t\t\tconst hold = given.holds[id]\n\t\t\tthis.holds[id] = { ...hold, units: [...(hold.units ?? [])], ...(hold.money && { money: { ...hold.money } }) }\n\t\t}\n\t\tthis.cooldowns = { ...(given.cooldowns ?? {}) }\n\t\treturn true\n\t}\n\n\t/** What the debug tools show: the report, the best, and the picker's numbers */\n\tinspect(): Record<string, unknown> {\n\t\treturn { goals: this.report(), ...(this.best !== undefined && { goal: this.best }) }\n\t}\n}\n\n/** Why a goal stopped, in words, for the decision log */\nfunction stopped(why: StopReason, by: string | undefined): string {\n\tswitch (why) {\n\t\tcase 'beaten':\n\t\t\treturn by ? `beaten by ${by}` : 'beaten'\n\t\tcase 'urgent':\n\t\t\treturn by ? `its units taken by ${by}, urgent` : 'its units taken by an urgent goal'\n\t\tcase 'done':\n\t\t\treturn 'done, or nothing left to run with'\n\t\tcase 'told':\n\t\t\treturn 'its units taken by a rule or a module'\n\t\tcase 'removed':\n\t\t\treturn 'taken out of the brain'\n\t}\n}\n\n/** A number as it is, and 0 for what is none (NaN, infinite): the picker never picks on nonsense */\nconst finite = (x: number) => (Number.isFinite(x) ? x : 0)\n/** A curved value or a score: finite, and nothing under 0 */\nconst positive = (x: number) => (Number.isFinite(x) && x > 0 ? x : 0)\n\n/**\n * The goals module: runs the brain's picker (`ai.goals.think`) in its place among the brain's modules, after what\n * reads the game and before what acts on orders. With goals of its own to add to the brain's\n *\n * @beta\n */\nexport const goals = (defs: GoalDef[] = []): AiModuleDef =>\n\tdefineModule({ id: 'goals', make: (ai: Brain): AiModule => {\n\t\tai.goals.add(...defs)\n\t\treturn {\n\t\t\tid: 'goals',\n\t\t\tphase: 'act',\n\t\t\tthink: () => ai.goals.think()\n\t\t}\n\t} })\n\ndeclare module './area' {\n\tinterface AreaMemories {\n\t\tgoals?: GoalsMemory\n\t}\n}\n"],"mappings":"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"}
|