@v12-engine/engine 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abilities/amounts.d.ts +28 -0
- package/dist/abilities/amounts.js +74 -0
- package/dist/abilities/amounts.js.map +1 -0
- package/dist/abilities/buffs.d.ts +106 -6
- package/dist/abilities/buffs.js +443 -0
- package/dist/abilities/buffs.js.map +1 -0
- package/dist/abilities/castTold.d.ts +2 -0
- package/dist/abilities/castTold.js +66 -0
- package/dist/abilities/castTold.js.map +1 -0
- package/dist/abilities/chance.d.ts +38 -0
- package/dist/abilities/chance.js +77 -0
- package/dist/abilities/chance.js.map +1 -0
- package/dist/abilities/charges.d.ts +18 -0
- package/dist/abilities/charges.js +101 -0
- package/dist/abilities/charges.js.map +1 -0
- package/dist/abilities/control.d.ts +28 -0
- package/dist/abilities/control.js +113 -0
- package/dist/abilities/control.js.map +1 -0
- package/dist/abilities/dispel.js +51 -0
- package/dist/abilities/dispel.js.map +1 -0
- package/dist/abilities/effectFields.d.ts +1 -1
- package/dist/abilities/effectFields.js +676 -0
- package/dist/abilities/effectFields.js.map +1 -0
- package/dist/abilities/effectIndex.d.ts +27 -0
- package/dist/abilities/effectIndex.js +64 -0
- package/dist/abilities/effectIndex.js.map +1 -0
- package/dist/abilities/effects/buff.d.ts +9 -3
- package/dist/abilities/effects/buff.js +84 -0
- package/dist/abilities/effects/buff.js.map +1 -0
- package/dist/abilities/effects/conditions.d.ts +2 -0
- package/dist/abilities/effects/conditions.js +41 -0
- package/dist/abilities/effects/conditions.js.map +1 -0
- package/dist/abilities/effects/core.js +54 -0
- package/dist/abilities/effects/core.js.map +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -1
- package/dist/abilities/effects/damage.js +43 -0
- package/dist/abilities/effects/damage.js.map +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -2
- package/dist/abilities/effects/heal.js +51 -0
- package/dist/abilities/effects/heal.js.map +1 -0
- package/dist/abilities/effects/missile.d.ts +13 -1
- package/dist/abilities/effects/missile.js +104 -0
- package/dist/abilities/effects/missile.js.map +1 -0
- package/dist/abilities/effects/morph.d.ts +5 -0
- package/dist/abilities/effects/morph.js +43 -0
- package/dist/abilities/effects/morph.js.map +1 -0
- package/dist/abilities/effects/moves.d.ts +16 -4
- package/dist/abilities/effects/moves.js +212 -0
- package/dist/abilities/effects/moves.js.map +1 -0
- package/dist/abilities/effects/passives.d.ts +19 -9
- package/dist/abilities/effects/passives.js +131 -0
- package/dist/abilities/effects/passives.js.map +1 -0
- package/dist/abilities/effects/proxy.d.ts +5 -0
- package/dist/abilities/effects/proxy.js +60 -0
- package/dist/abilities/effects/proxy.js.map +1 -0
- package/dist/abilities/effects/sight.d.ts +2 -2
- package/dist/abilities/effects/sight.js +39 -0
- package/dist/abilities/effects/sight.js.map +1 -0
- package/dist/abilities/effects/spawn.d.ts +5 -2
- package/dist/abilities/effects/spawn.js +40 -0
- package/dist/abilities/effects/spawn.js.map +1 -0
- package/dist/abilities/effects/timed.d.ts +2 -2
- package/dist/abilities/effects/timed.js +96 -0
- package/dist/abilities/effects/timed.js.map +1 -0
- package/dist/abilities/effects/trade.d.ts +1 -1
- package/dist/abilities/effects/trade.js +25 -0
- package/dist/abilities/effects/trade.js.map +1 -0
- package/dist/abilities/effects.d.ts +97 -23
- package/dist/abilities/effects.js +860 -0
- package/dist/abilities/effects.js.map +1 -0
- package/dist/abilities/land.d.ts +38 -4
- package/dist/abilities/land.js +189 -0
- package/dist/abilities/land.js.map +1 -0
- package/dist/abilities/recast.d.ts +45 -0
- package/dist/abilities/recast.js +118 -0
- package/dist/abilities/recast.js.map +1 -0
- package/dist/abilities/scaled.js +40 -0
- package/dist/abilities/scaled.js.map +1 -0
- package/dist/abilities/screen.d.ts +6 -0
- package/dist/abilities/screen.js +83 -0
- package/dist/abilities/screen.js.map +1 -0
- package/dist/abilities/shapes.d.ts +66 -0
- package/dist/abilities/shapes.js +122 -0
- package/dist/abilities/shapes.js.map +1 -0
- package/dist/abilities/text.d.ts +14 -2
- package/dist/abilities/text.js +204 -0
- package/dist/abilities/text.js.map +1 -0
- package/dist/abilities/triggers.d.ts +98 -0
- package/dist/abilities/triggers.js +351 -0
- package/dist/abilities/triggers.js.map +1 -0
- package/dist/abilityChanges.d.ts +131 -0
- package/dist/abilityChanges.js +345 -0
- package/dist/abilityChanges.js.map +1 -0
- package/dist/ai/area.d.ts +4 -1
- package/dist/ai/brain.d.ts +4 -1
- package/dist/ai/brain.js +844 -0
- package/dist/ai/brain.js.map +1 -0
- package/dist/ai/budget.js +74 -0
- package/dist/ai/budget.js.map +1 -0
- package/dist/ai/checks.d.ts +9 -1
- package/dist/ai/checks.js +242 -0
- package/dist/ai/checks.js.map +1 -0
- package/dist/ai/computer.d.ts +11 -4
- package/dist/ai/computer.js +251 -0
- package/dist/ai/computer.js.map +1 -0
- package/dist/ai/defence.d.ts +4 -0
- package/dist/ai/defence.js +430 -0
- package/dist/ai/defence.js.map +1 -0
- package/dist/ai/define.d.ts +3 -2
- package/dist/ai/define.js +31 -0
- package/dist/ai/define.js.map +1 -0
- package/dist/ai/economy.d.ts +10 -7
- package/dist/ai/economy.js +780 -0
- package/dist/ai/economy.js.map +1 -0
- package/dist/ai/geometry.js +38 -0
- package/dist/ai/geometry.js.map +1 -0
- package/dist/ai/goals.d.ts +1 -0
- package/dist/ai/goals.js +560 -0
- package/dist/ai/goals.js.map +1 -0
- package/dist/ai/knowledge.d.ts +72 -7
- package/dist/ai/knowledge.js +804 -0
- package/dist/ai/knowledge.js.map +1 -0
- package/dist/ai/lanes.d.ts +10 -2
- package/dist/ai/lanes.js +715 -0
- package/dist/ai/lanes.js.map +1 -0
- package/dist/ai/melee/build.js +264 -0
- package/dist/ai/melee/build.js.map +1 -0
- package/dist/ai/melee/goals.d.ts +7 -0
- package/dist/ai/melee/goals.js +720 -0
- package/dist/ai/melee/goals.js.map +1 -0
- package/dist/ai/melee/heroes.js +68 -0
- package/dist/ai/melee/heroes.js.map +1 -0
- package/dist/ai/melee/index.d.ts +1 -1
- package/dist/ai/melee/index.js +51 -0
- package/dist/ai/melee/index.js.map +1 -0
- package/dist/ai/melee/production.js +29 -0
- package/dist/ai/melee/production.js.map +1 -0
- package/dist/ai/melee/surrender.js +64 -0
- package/dist/ai/melee/surrender.js.map +1 -0
- package/dist/ai/micro.d.ts +9 -0
- package/dist/ai/micro.js +1316 -0
- package/dist/ai/micro.js.map +1 -0
- package/dist/ai/mission.d.ts +9 -2
- package/dist/ai/mission.js +538 -0
- package/dist/ai/mission.js.map +1 -0
- package/dist/ai/missionRules.d.ts +1 -1
- package/dist/ai/missionRules.js +26 -0
- package/dist/ai/missionRules.js.map +1 -0
- package/dist/ai/module.d.ts +6 -2
- package/dist/ai/module.js +37 -0
- package/dist/ai/module.js.map +1 -0
- package/dist/ai/options.d.ts +3 -3
- package/dist/ai/plans/build.d.ts +20 -1
- package/dist/ai/plans/build.js +608 -0
- package/dist/ai/plans/build.js.map +1 -0
- package/dist/ai/plans/placement.d.ts +4 -1
- package/dist/ai/plans/placement.js +295 -0
- package/dist/ai/plans/placement.js.map +1 -0
- package/dist/ai/plans/plans.d.ts +9 -0
- package/dist/ai/plans/plans.js +110 -0
- package/dist/ai/plans/plans.js.map +1 -0
- package/dist/ai/plans/production.d.ts +14 -2
- package/dist/ai/plans/production.js +434 -0
- package/dist/ai/plans/production.js.map +1 -0
- package/dist/ai/plans/purse.d.ts +6 -3
- package/dist/ai/plans/purse.js +139 -0
- package/dist/ai/plans/purse.js.map +1 -0
- package/dist/ai/plans/tech.d.ts +6 -0
- package/dist/ai/plans/tech.js +122 -0
- package/dist/ai/plans/tech.js.map +1 -0
- package/dist/ai/profiles.d.ts +4 -4
- package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
- package/dist/ai/profiles.js.map +1 -0
- package/dist/ai/reach.js +54 -0
- package/dist/ai/reach.js.map +1 -0
- package/dist/ai/report.d.ts +8 -0
- package/dist/ai/report.js +87 -0
- package/dist/ai/report.js.map +1 -0
- package/dist/ai/roles.d.ts +4 -0
- package/dist/ai/roles.js +207 -0
- package/dist/ai/roles.js.map +1 -0
- package/dist/ai/rules.d.ts +8 -2
- package/dist/ai/rules.js +416 -0
- package/dist/ai/rules.js.map +1 -0
- package/dist/ai/scouting.d.ts +6 -0
- package/dist/ai/scouting.js +324 -0
- package/dist/ai/scouting.js.map +1 -0
- package/dist/ai/settings.js +99 -0
- package/dist/ai/settings.js.map +1 -0
- package/dist/ai/squads.d.ts +21 -2
- package/dist/ai/squads.js +916 -0
- package/dist/ai/squads.js.map +1 -0
- package/dist/ai/strength.js +320 -0
- package/dist/ai/strength.js.map +1 -0
- package/dist/ai/task.d.ts +3 -1
- package/dist/ai/task.js +17 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tasks/attack.js +24 -0
- package/dist/ai/tasks/attack.js.map +1 -0
- package/dist/ai/tasks/capture.d.ts +3 -3
- package/dist/ai/tasks/capture.js +37 -0
- package/dist/ai/tasks/capture.js.map +1 -0
- package/dist/ai/tasks/creep.js +29 -0
- package/dist/ai/tasks/creep.js.map +1 -0
- package/dist/ai/tasks/defend.js +61 -0
- package/dist/ai/tasks/defend.js.map +1 -0
- package/dist/ai/tasks/drop.js +81 -0
- package/dist/ai/tasks/drop.js.map +1 -0
- package/dist/ai/tasks/escort.js +59 -0
- package/dist/ai/tasks/escort.js.map +1 -0
- package/dist/ai/tasks/gather.js +48 -0
- package/dist/ai/tasks/gather.js.map +1 -0
- package/dist/ai/tasks/harass.js +39 -0
- package/dist/ai/tasks/harass.js.map +1 -0
- package/dist/ai/tasks/hold.js +32 -0
- package/dist/ai/tasks/hold.js.map +1 -0
- package/dist/ai/tasks/index.js +34 -0
- package/dist/ai/tasks/index.js.map +1 -0
- package/dist/ai/tasks/move.js +26 -0
- package/dist/ai/tasks/move.js.map +1 -0
- package/dist/ai/tasks/patrol.js +59 -0
- package/dist/ai/tasks/patrol.js.map +1 -0
- package/dist/ai/tasks/retreat.js +28 -0
- package/dist/ai/tasks/retreat.js.map +1 -0
- package/dist/ai/tasks/scout.js +73 -0
- package/dist/ai/tasks/scout.js.map +1 -0
- package/dist/ai/tasks/shared.d.ts +1 -1
- package/dist/ai/tasks/shared.js +137 -0
- package/dist/ai/tasks/shared.js.map +1 -0
- package/dist/ai/team.d.ts +18 -1
- package/dist/ai/team.js +492 -0
- package/dist/ai/team.js.map +1 -0
- package/dist/ai/threat.d.ts +6 -0
- package/dist/ai/threat.js +206 -0
- package/dist/ai/threat.js.map +1 -0
- package/dist/ai/view.d.ts +21 -7
- package/dist/ai/view.js +677 -0
- package/dist/ai/view.js.map +1 -0
- package/dist/ai/waves.d.ts +6 -0
- package/dist/ai/waves.js +410 -0
- package/dist/ai/waves.js.map +1 -0
- package/dist/ai.js +54 -6239
- package/dist/aiTesting.d.ts +6 -3
- package/dist/aiTesting.js +229 -0
- package/dist/aiTesting.js.map +1 -0
- package/dist/areas.d.ts +4 -1
- package/dist/areas.js +295 -0
- package/dist/areas.js.map +1 -0
- package/dist/attacks.d.ts +3 -3
- package/dist/attacks.js +127 -0
- package/dist/attacks.js.map +1 -0
- package/dist/burning.d.ts +267 -0
- package/dist/burning.js +795 -0
- package/dist/burning.js.map +1 -0
- package/dist/bytes.js +21 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callings.d.ts +71 -0
- package/dist/callings.js +157 -0
- package/dist/callings.js.map +1 -0
- package/dist/cameraOrders.d.ts +78 -0
- package/dist/cameraOrders.js +114 -0
- package/dist/cameraOrders.js.map +1 -0
- package/dist/camps.d.ts +70 -4
- package/dist/camps.js +501 -0
- package/dist/camps.js.map +1 -0
- package/dist/capture.d.ts +15 -3
- package/dist/capture.js +304 -0
- package/dist/capture.js.map +1 -0
- package/dist/cellLayers.d.ts +78 -13
- package/dist/cellLayers.js +275 -0
- package/dist/cellLayers.js.map +1 -0
- package/dist/cellPatches.d.ts +24 -0
- package/dist/cellPatches.js +73 -0
- package/dist/cellPatches.js.map +1 -0
- package/dist/cinematics.d.ts +10 -5
- package/dist/cinematics.js +161 -0
- package/dist/cinematics.js.map +1 -0
- package/dist/clock.d.ts +2 -2
- package/dist/clock.js +78 -0
- package/dist/clock.js.map +1 -0
- package/dist/commands.d.ts +36 -4
- package/dist/commands.js +636 -0
- package/dist/commands.js.map +1 -0
- package/dist/components.d.ts +31 -10
- package/dist/components.js +74 -0
- package/dist/components.js.map +1 -0
- package/dist/computers.d.ts +4 -4
- package/dist/computers.js +194 -0
- package/dist/computers.js.map +1 -0
- package/dist/concealment.d.ts +25 -2
- package/dist/concealment.js +409 -0
- package/dist/concealment.js.map +1 -0
- package/dist/coreComponents.js +130 -0
- package/dist/coreComponents.js.map +1 -0
- package/dist/createGame.d.ts +306 -0
- package/dist/createGame.js +405 -0
- package/dist/createGame.js.map +1 -0
- package/dist/dashing.d.ts +18 -2
- package/dist/dashing.js +41 -0
- package/dist/dashing.js.map +1 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +5 -3
- package/dist/debug2.js +76 -0
- package/dist/debug2.js.map +1 -0
- package/dist/debugCommands.d.ts +6 -6
- package/dist/debugCommands.js +537 -0
- package/dist/debugCommands.js.map +1 -0
- package/dist/debugging.d.ts +1 -0
- package/dist/defaultSets.d.ts +183 -0
- package/dist/defaultSets.js +216 -0
- package/dist/defaultSets.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.js +78 -0
- package/dist/definitions.js.map +1 -0
- package/dist/defs.d.ts +1895 -165
- package/dist/defs.js +380 -0
- package/dist/defs.js.map +1 -0
- package/dist/denying.d.ts +4 -4
- package/dist/denying.js +106 -0
- package/dist/denying.js.map +1 -0
- package/dist/destructibles.d.ts +2 -2
- package/dist/destructibles.js +36 -0
- package/dist/destructibles.js.map +1 -0
- package/dist/determinism.d.ts +4 -4
- package/dist/determinism.js +247 -0
- package/dist/determinism.js.map +1 -0
- package/dist/dialog.d.ts +17 -2
- package/dist/dialog.js +108 -0
- package/dist/dialog.js.map +1 -0
- package/dist/effectRefs.js +28 -0
- package/dist/effectRefs.js.map +1 -0
- package/dist/effects.d.ts +27 -11
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/endings.d.ts +1 -1
- package/dist/endings.js +78 -0
- package/dist/endings.js.map +1 -0
- package/dist/engagement.d.ts +40 -6
- package/dist/engagement.js +530 -0
- package/dist/engagement.js.map +1 -0
- package/dist/engineEvents.d.ts +72 -9
- package/dist/engineEvents.js +520 -0
- package/dist/engineEvents.js.map +1 -0
- package/dist/entity.d.ts +275 -26
- package/dist/entity.js +441 -0
- package/dist/entity.js.map +1 -0
- package/dist/entityIndex.d.ts +10 -3
- package/dist/entityIndex.js +149 -0
- package/dist/entityIndex.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +11 -5
- package/dist/events.js +158 -0
- package/dist/events.js.map +1 -0
- package/dist/exactMath.js +273 -0
- package/dist/exactMath.js.map +1 -0
- package/dist/features.d.ts +1 -1
- package/dist/features.js +127 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +25 -5
- package/dist/fields.js +140 -0
- package/dist/fields.js.map +1 -0
- package/dist/fixture.d.ts +3 -3
- package/dist/fixture.js +512 -0
- package/dist/fixture.js.map +1 -0
- package/dist/fog.d.ts +26 -3
- package/dist/fog.js +333 -0
- package/dist/fog.js.map +1 -0
- package/dist/foliage.d.ts +476 -0
- package/dist/foliage.js +1478 -0
- package/dist/foliage.js.map +1 -0
- package/dist/foliageDebug.d.ts +57 -0
- package/dist/foliageDebug.js +172 -0
- package/dist/foliageDebug.js.map +1 -0
- package/dist/foliageRegrowth.d.ts +20 -0
- package/dist/foliageRegrowth.js +332 -0
- package/dist/foliageRegrowth.js.map +1 -0
- package/dist/formState.d.ts +67 -0
- package/dist/formState.js +65 -0
- package/dist/formState.js.map +1 -0
- package/dist/formation.d.ts +46 -8
- package/dist/formation.js +297 -0
- package/dist/formation.js.map +1 -0
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +146 -0
- package/dist/forms.js.map +1 -0
- package/dist/friendlyFire.d.ts +2 -2
- package/dist/friendlyFire.js +37 -0
- package/dist/friendlyFire.js.map +1 -0
- package/dist/game.d.ts +141 -48
- package/dist/game.js +834 -0
- package/dist/game.js.map +1 -0
- package/dist/gameData.d.ts +96 -22
- package/dist/gameData.js +1690 -0
- package/dist/gameData.js.map +1 -0
- package/dist/gameFiles.d.ts +3 -3
- package/dist/gameFiles.js +14 -0
- package/dist/gameFiles.js.map +1 -0
- package/dist/gates.js +92 -0
- package/dist/gates.js.map +1 -0
- package/dist/generate.d.ts +28 -1
- package/dist/generate.js +1062 -0
- package/dist/generate.js.map +1 -0
- package/dist/generateWorker.d.ts +7 -3
- package/dist/generateWorker.js +86 -0
- package/dist/generateWorker.js.map +1 -0
- package/dist/grid.d.ts +9 -0
- package/dist/grid.js +102 -0
- package/dist/grid.js.map +1 -0
- package/dist/ground.d.ts +17 -1
- package/dist/ground.js +375 -0
- package/dist/ground.js.map +1 -0
- package/dist/groundObjects.d.ts +70 -0
- package/dist/groundObjects.js +371 -0
- package/dist/groundObjects.js.map +1 -0
- package/dist/groundSpeed.d.ts +20 -3
- package/dist/groundSpeed.js +117 -0
- package/dist/groundSpeed.js.map +1 -0
- package/dist/hero.d.ts +126 -10
- package/dist/hero.js +432 -0
- package/dist/hero.js.map +1 -0
- package/dist/holds.d.ts +94 -0
- package/dist/holds.js +305 -0
- package/dist/holds.js.map +1 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.js +30 -0
- package/dist/home.js.map +1 -0
- package/dist/hooks.d.ts +339 -57
- package/dist/hooks.js +105 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hotReload.d.ts +6 -5
- package/dist/hotReload.js +145 -0
- package/dist/hotReload.js.map +1 -0
- package/dist/ids.d.ts +3 -3
- package/dist/ids.js +30 -0
- package/dist/ids.js.map +1 -0
- package/dist/idsFile.d.ts +36 -0
- package/dist/idsFile.js +134 -0
- package/dist/idsFile.js.map +1 -0
- package/dist/index.d.ts +105 -68
- package/dist/index.js +194 -4701
- package/dist/inspect.d.ts +29 -2
- package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
- package/dist/inspect.js.map +1 -0
- package/dist/inventory.d.ts +14 -1
- package/dist/inventory.js +84 -0
- package/dist/inventory.js.map +1 -0
- package/dist/items.d.ts +136 -8
- package/dist/items.js +585 -0
- package/dist/items.js.map +1 -0
- package/dist/lanes.d.ts +12 -3
- package/dist/lanes.js +496 -0
- package/dist/lanes.js.map +1 -0
- package/dist/life.d.ts +6 -2
- package/dist/life.js +287 -0
- package/dist/life.js.map +1 -0
- package/dist/log.d.ts +26 -3
- package/dist/log.js +192 -0
- package/dist/log.js.map +1 -0
- package/dist/manaBurn.d.ts +2 -2
- package/dist/manaBurn.js +75 -0
- package/dist/manaBurn.js.map +1 -0
- package/dist/map/file.d.ts +56 -3
- package/dist/map/file.js +264 -0
- package/dist/map/file.js.map +1 -0
- package/dist/map/images.js +61 -0
- package/dist/map/images.js.map +1 -0
- package/dist/map/look.d.ts +1 -1
- package/dist/map/look.js +30 -0
- package/dist/map/look.js.map +1 -0
- package/dist/map/pathProfile.js +183 -0
- package/dist/map/pathProfile.js.map +1 -0
- package/dist/map/resize.d.ts +4 -0
- package/dist/map/resize.js +136 -0
- package/dist/map/resize.js.map +1 -0
- package/dist/map/schema.js +257 -0
- package/dist/map/schema.js.map +1 -0
- package/dist/map/terrain.js +214 -0
- package/dist/map/terrain.js.map +1 -0
- package/dist/map/types.d.ts +92 -13
- package/dist/map/types.js +251 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mapCheck/cells.js +94 -0
- package/dist/mapCheck/cells.js.map +1 -0
- package/dist/mapCheck/rules/foliage.d.ts +9 -0
- package/dist/mapCheck/rules/foliage.js +83 -0
- package/dist/mapCheck/rules/foliage.js.map +1 -0
- package/dist/mapCheck/rules/names.js +39 -0
- package/dist/mapCheck/rules/names.js.map +1 -0
- package/dist/mapCheck/rules/objects.d.ts +1 -1
- package/dist/mapCheck/rules/objects.js +56 -0
- package/dist/mapCheck/rules/objects.js.map +1 -0
- package/dist/mapCheck/rules/paths.js +32 -0
- package/dist/mapCheck/rules/paths.js.map +1 -0
- package/dist/mapCheck/rules/players.js +20 -0
- package/dist/mapCheck/rules/players.js.map +1 -0
- package/dist/mapCheck/rules/races.js +56 -0
- package/dist/mapCheck/rules/races.js.map +1 -0
- package/dist/mapCheck/rules/random.js +47 -0
- package/dist/mapCheck/rules/random.js.map +1 -0
- package/dist/mapCheck/rules/regions.js +30 -0
- package/dist/mapCheck/rules/regions.js.map +1 -0
- package/dist/mapCheck/rules/targets.js +31 -0
- package/dist/mapCheck/rules/targets.js.map +1 -0
- package/dist/mapCheck/rules/walking.js +45 -0
- package/dist/mapCheck/rules/walking.js.map +1 -0
- package/dist/mapCheck.d.ts +2 -2
- package/dist/mapCheck.js +63 -0
- package/dist/mapCheck.js.map +1 -0
- package/dist/mapFields.d.ts +25 -2
- package/dist/mapFields.js +134 -0
- package/dist/mapFields.js.map +1 -0
- package/dist/mapFile.js +176 -0
- package/dist/mapFile.js.map +1 -0
- package/dist/mapMeasure.d.ts +8 -0
- package/dist/mapMeasure.js +283 -0
- package/dist/mapMeasure.js.map +1 -0
- package/dist/mapMerge.d.ts +1 -0
- package/dist/mapMerge.js +172 -0
- package/dist/mapMerge.js.map +1 -0
- package/dist/mapObjectives.js +138 -0
- package/dist/mapObjectives.js.map +1 -0
- package/dist/mapObjects.js +80 -0
- package/dist/mapObjects.js.map +1 -0
- package/dist/math.d.ts +37 -7
- package/dist/math.js +155 -0
- package/dist/math.js.map +1 -0
- package/dist/messages.d.ts +71 -4
- package/dist/messages.js +29 -0
- package/dist/messages.js.map +1 -0
- package/dist/missionRules.d.ts +10 -2
- package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
- package/dist/missionRules.js.map +1 -0
- package/dist/mods.d.ts +39 -20
- package/dist/mods.js +271 -0
- package/dist/mods.js.map +1 -0
- package/dist/moves.d.ts +87 -0
- package/dist/moves.js +539 -0
- package/dist/moves.js.map +1 -0
- package/dist/names.d.ts +7 -0
- package/dist/names.js +122 -0
- package/dist/names.js.map +1 -0
- package/dist/navigation/agentParams.js +14 -0
- package/dist/navigation/agentParams.js.map +1 -0
- package/dist/navigation/air.d.ts +7 -3
- package/dist/navigation/air.js +401 -0
- package/dist/navigation/air.js.map +1 -0
- package/dist/navigation/builds.d.ts +34 -2
- package/dist/navigation/builds.js +287 -0
- package/dist/navigation/builds.js.map +1 -0
- package/dist/navigation/groundAreas.d.ts +59 -1
- package/dist/navigation/groundAreas.js +407 -0
- package/dist/navigation/groundAreas.js.map +1 -0
- package/dist/navigation/navigation.d.ts +98 -9
- package/dist/navigation/recast.d.ts +194 -18
- package/dist/navigation/recast.js +1379 -0
- package/dist/navigation/recast.js.map +1 -0
- package/dist/navigation/sidePaths.d.ts +8 -3
- package/dist/navigation/sidePaths.js +241 -0
- package/dist/navigation/sidePaths.js.map +1 -0
- package/dist/navigation/sized.js +243 -0
- package/dist/navigation/sized.js.map +1 -0
- package/dist/nearest.js +32 -0
- package/dist/nearest.js.map +1 -0
- package/dist/noise.js +59 -0
- package/dist/noise.js.map +1 -0
- package/dist/objectives.d.ts +12 -3
- package/dist/objectives.js +144 -0
- package/dist/objectives.js.map +1 -0
- package/dist/orders/basic.d.ts +5 -5
- package/dist/orders/basic.js +417 -0
- package/dist/orders/basic.js.map +1 -0
- package/dist/orders/build.js +278 -0
- package/dist/orders/build.js.map +1 -0
- package/dist/orders/cast.d.ts +13 -3
- package/dist/orders/cast.js +558 -0
- package/dist/orders/cast.js.map +1 -0
- package/dist/orders/facts.js +16 -0
- package/dist/orders/facts.js.map +1 -0
- package/dist/orders/harvest.d.ts +21 -5
- package/dist/orders/harvest.js +540 -0
- package/dist/orders/harvest.js.map +1 -0
- package/dist/orders/idle.d.ts +3 -1
- package/dist/orders/idle.js +234 -0
- package/dist/orders/idle.js.map +1 -0
- package/dist/orders/items.js +92 -0
- package/dist/orders/items.js.map +1 -0
- package/dist/orders/queue.js +108 -0
- package/dist/orders/queue.js.map +1 -0
- package/dist/orders/waiting.d.ts +39 -0
- package/dist/orders/waiting.js +149 -0
- package/dist/orders/waiting.js.map +1 -0
- package/dist/pack.schema.js +13 -0
- package/dist/pack.schema.js.map +1 -0
- package/dist/pack.schema.json +7622 -841
- package/dist/packs/director/index.d.ts +13 -5
- package/dist/packs/director/index.js +204 -0
- package/dist/packs/director/index.js.map +1 -0
- package/dist/packs/heroes/campaign.d.ts +3 -2
- package/dist/packs/heroes/campaign.js +241 -0
- package/dist/packs/heroes/campaign.js.map +1 -0
- package/dist/packs/heroes/carry.d.ts +6 -0
- package/dist/packs/heroes/carry.js +112 -0
- package/dist/packs/heroes/carry.js.map +1 -0
- package/dist/packs/heroes/commands.js +115 -0
- package/dist/packs/heroes/commands.js.map +1 -0
- package/dist/packs/heroes/fallen.d.ts +43 -0
- package/dist/packs/heroes/fallen.js +61 -0
- package/dist/packs/heroes/fallen.js.map +1 -0
- package/dist/packs/heroes/hire.js +60 -0
- package/dist/packs/heroes/hire.js.map +1 -0
- package/dist/packs/heroes/index.d.ts +7 -6
- package/dist/packs/heroes/index.js +130 -0
- package/dist/packs/heroes/index.js.map +1 -0
- package/dist/packs/heroes/loop.d.ts +95 -0
- package/dist/packs/heroes/loop.js +250 -0
- package/dist/packs/heroes/loop.js.map +1 -0
- package/dist/packs/heroes/making.d.ts +6 -3
- package/dist/packs/heroes/making.js +55 -0
- package/dist/packs/heroes/making.js.map +1 -0
- package/dist/packs/heroes/respawn.d.ts +3 -3
- package/dist/packs/heroes/respawn.js +87 -0
- package/dist/packs/heroes/respawn.js.map +1 -0
- package/dist/packs/heroes/sets.d.ts +32 -0
- package/dist/packs/heroes/sets.js +51 -0
- package/dist/packs/heroes/sets.js.map +1 -0
- package/dist/packs/heroes/spells.d.ts +16 -0
- package/dist/packs/heroes/spells.js +269 -0
- package/dist/packs/heroes/spells.js.map +1 -0
- package/dist/packs/items/defaults.d.ts +43 -0
- package/dist/packs/items/defaults.js +1504 -0
- package/dist/packs/items/defaults.js.map +1 -0
- package/dist/packs/items/index.d.ts +27 -0
- package/dist/packs/items/index.js +214 -0
- package/dist/packs/items/index.js.map +1 -0
- package/dist/packs/moba/index.d.ts +3 -3
- package/dist/packs/moba/index.js +174 -0
- package/dist/packs/moba/index.js.map +1 -0
- package/dist/packs/pack.d.ts +15 -15
- package/dist/packs/pack.js +14 -0
- package/dist/packs/pack.js.map +1 -0
- package/dist/packs.d.ts +15 -7
- package/dist/packs.js +222 -0
- package/dist/packs.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +109 -0
- package/dist/paths.js.map +1 -0
- package/dist/plain.js +57 -0
- package/dist/plain.js.map +1 -0
- package/dist/player.d.ts +33 -10
- package/dist/player.js +159 -0
- package/dist/player.js.map +1 -0
- package/dist/portals.d.ts +1 -1
- package/dist/portals.js +194 -0
- package/dist/portals.js.map +1 -0
- package/dist/prefabs.d.ts +25 -2
- package/dist/prefabs.js +239 -0
- package/dist/prefabs.js.map +1 -0
- package/dist/presetBuildings.js +58 -0
- package/dist/presetBuildings.js.map +1 -0
- package/dist/presetFoliage.d.ts +27 -0
- package/dist/presetFoliage.js +98 -0
- package/dist/presetFoliage.js.map +1 -0
- package/dist/presetGround.js +65 -0
- package/dist/presetGround.js.map +1 -0
- package/dist/proxies.d.ts +12 -0
- package/dist/proxies.js +79 -0
- package/dist/proxies.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +88 -0
- package/dist/query.js.map +1 -0
- package/dist/races.d.ts +15 -14
- package/dist/races.js +172 -0
- package/dist/races.js.map +1 -0
- package/dist/randomGroups.js +91 -0
- package/dist/randomGroups.js.map +1 -0
- package/dist/registry.d.ts +117 -53
- package/dist/registry.js +323 -0
- package/dist/registry.js.map +1 -0
- package/dist/remains.d.ts +11 -9
- package/dist/remains.js +188 -0
- package/dist/remains.js.map +1 -0
- package/dist/replication.d.ts +12 -7
- package/dist/replication.js +100 -0
- package/dist/replication.js.map +1 -0
- package/dist/rng.d.ts +2 -0
- package/dist/rng.js +40 -0
- package/dist/rng.js.map +1 -0
- package/dist/rules.d.ts +186 -99
- package/dist/rules.js +179 -0
- package/dist/rules.js.map +1 -0
- package/dist/rulesCheck.d.ts +5 -4
- package/dist/rulesCheck.js +693 -0
- package/dist/rulesCheck.js.map +1 -0
- package/dist/runes.d.ts +2 -2
- package/dist/runes.js +80 -0
- package/dist/runes.js.map +1 -0
- package/dist/save.d.ts +37 -12
- package/dist/save.js +532 -0
- package/dist/save.js.map +1 -0
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +99 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.js +156 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/score.d.ts +19 -19
- package/dist/score.js +709 -0
- package/dist/score.js.map +1 -0
- package/dist/sequences.d.ts +10 -6
- package/dist/sequences.js +206 -0
- package/dist/sequences.js.map +1 -0
- package/dist/server/doorman.js +154 -0
- package/dist/server/doorman.js.map +1 -0
- package/dist/server/gameServer.d.ts +16 -1
- package/dist/server/gameServer.js +643 -0
- package/dist/server/gameServer.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/lobby.js +199 -0
- package/dist/server/lobby.js.map +1 -0
- package/dist/server/log.js +18 -0
- package/dist/server/log.js.map +1 -0
- package/dist/server/match.js +267 -0
- package/dist/server/match.js.map +1 -0
- package/dist/server/mode.d.ts +18 -9
- package/dist/server/mode.js +220 -0
- package/dist/server/mode.js.map +1 -0
- package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
- package/dist/server/navigation-worker.js.map +1 -0
- package/dist/server/navigation.js +39 -0
- package/dist/server/navigation.js.map +1 -0
- package/dist/server/ops.d.ts +4 -0
- package/dist/server/ops.js +137 -0
- package/dist/server/ops.js.map +1 -0
- package/dist/server/packs.d.ts +3 -3
- package/dist/server/packs.js +32 -0
- package/dist/server/packs.js.map +1 -0
- package/dist/server/ratings.d.ts +5 -0
- package/dist/server/ratings.js +104 -0
- package/dist/server/ratings.js.map +1 -0
- package/dist/server/relay.d.ts +12 -2
- package/dist/server/relay.js +144 -0
- package/dist/server/relay.js.map +1 -0
- package/dist/server/rooms.d.ts +9 -2
- package/dist/server/rooms.js +442 -0
- package/dist/server/rooms.js.map +1 -0
- package/dist/server/seat.js +116 -0
- package/dist/server/seat.js.map +1 -0
- package/dist/server/seatSettings.d.ts +3 -3
- package/dist/server/seatSettings.js +63 -0
- package/dist/server/seatSettings.js.map +1 -0
- package/dist/server/secret.js +13 -0
- package/dist/server/secret.js.map +1 -0
- package/dist/server/start.d.ts +13 -6
- package/dist/server/start.js +76 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/websocket.d.ts +9 -1
- package/dist/server/websocket.js +306 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/server.js +15 -2861
- package/dist/session/can.js +26 -0
- package/dist/session/can.js.map +1 -0
- package/dist/session/commandReplay.d.ts +8 -2
- package/dist/session/commandReplay.js +293 -0
- package/dist/session/commandReplay.js.map +1 -0
- package/dist/session/debug.js +151 -0
- package/dist/session/debug.js.map +1 -0
- package/dist/session/delay.js +62 -0
- package/dist/session/delay.js.map +1 -0
- package/dist/session/delta.d.ts +14 -1
- package/dist/session/delta.js +407 -0
- package/dist/session/delta.js.map +1 -0
- package/dist/session/entityState.js +415 -0
- package/dist/session/entityState.js.map +1 -0
- package/dist/session/local.d.ts +47 -5
- package/dist/session/local.js +670 -0
- package/dist/session/local.js.map +1 -0
- package/dist/session/memory.d.ts +20 -2
- package/dist/session/memory.js +131 -0
- package/dist/session/memory.js.map +1 -0
- package/dist/session/protocol.d.ts +325 -31
- package/dist/session/protocol.js +55 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/remote.d.ts +74 -12
- package/dist/session/remote.js +1394 -0
- package/dist/session/remote.js.map +1 -0
- package/dist/session/replay.d.ts +11 -2
- package/dist/session/replay.js +160 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/seed.js +12 -0
- package/dist/session/seed.js.map +1 -0
- package/dist/session/share.d.ts +5 -1
- package/dist/session/share.js +94 -0
- package/dist/session/share.js.map +1 -0
- package/dist/session/socket.d.ts +1 -1
- package/dist/session/socket.js +29 -0
- package/dist/session/socket.js.map +1 -0
- package/dist/session/wire.d.ts +5 -0
- package/dist/session/wire.js +84 -0
- package/dist/session/wire.js.map +1 -0
- package/dist/session/worker.d.ts +77 -12
- package/dist/session/worker.js +499 -0
- package/dist/session/worker.js.map +1 -0
- package/dist/shared.d.ts +31 -5
- package/dist/shared.js +166 -0
- package/dist/shared.js.map +1 -0
- package/dist/sides.d.ts +9 -3
- package/dist/sides.js +149 -0
- package/dist/sides.js.map +1 -0
- package/dist/sight.js +85 -0
- package/dist/sight.js.map +1 -0
- package/dist/simulate-worker.js +1 -1
- package/dist/simulate.d.ts +12 -8
- package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
- package/dist/simulate.js.map +1 -0
- package/dist/smart.js +77 -0
- package/dist/smart.js.map +1 -0
- package/dist/spatial.d.ts +32 -16
- package/dist/spatial.js +234 -0
- package/dist/spatial.js.map +1 -0
- package/dist/spawning.d.ts +1 -0
- package/dist/spawning.js +224 -0
- package/dist/spawning.js.map +1 -0
- package/dist/stances.d.ts +6 -3
- package/dist/stances.js +169 -0
- package/dist/stances.js.map +1 -0
- package/dist/start.d.ts +10 -10
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/stats.d.ts +42 -16
- package/dist/stats.js +290 -0
- package/dist/stats.js.map +1 -0
- package/dist/summoned.d.ts +52 -0
- package/dist/summoned.js +38 -0
- package/dist/summoned.js.map +1 -0
- package/dist/summons.d.ts +10 -13
- package/dist/summons.js +271 -0
- package/dist/summons.js.map +1 -0
- package/dist/systems/abilities.js +224 -0
- package/dist/systems/abilities.js.map +1 -0
- package/dist/systems/combat.d.ts +35 -1
- package/dist/systems/combat.js +677 -0
- package/dist/systems/combat.js.map +1 -0
- package/dist/systems/combatTold.d.ts +3 -1
- package/dist/systems/combatTold.js +85 -0
- package/dist/systems/combatTold.js.map +1 -0
- package/dist/systems/construction.js +80 -0
- package/dist/systems/construction.js.map +1 -0
- package/dist/systems/economy.d.ts +0 -6
- package/dist/systems/economy.js +128 -0
- package/dist/systems/economy.js.map +1 -0
- package/dist/systems/fog.d.ts +1 -1
- package/dist/systems/fog.js +120 -0
- package/dist/systems/fog.js.map +1 -0
- package/dist/systems/life.js +32 -0
- package/dist/systems/life.js.map +1 -0
- package/dist/systems/movement.d.ts +24 -12
- package/dist/systems/movement.js +1247 -0
- package/dist/systems/movement.js.map +1 -0
- package/dist/systems/orders.js +64 -0
- package/dist/systems/orders.js.map +1 -0
- package/dist/systems/production.js +322 -0
- package/dist/systems/production.js.map +1 -0
- package/dist/systems/productionQueue.js +120 -0
- package/dist/systems/productionQueue.js.map +1 -0
- package/dist/systems/victory.d.ts +1 -1
- package/dist/systems/victory.js +56 -0
- package/dist/systems/victory.js.map +1 -0
- package/dist/talk.d.ts +6 -6
- package/dist/talk.js +153 -0
- package/dist/talk.js.map +1 -0
- package/dist/targeting.d.ts +142 -0
- package/dist/targeting.js +49 -0
- package/dist/targeting.js.map +1 -0
- package/dist/tech.d.ts +20 -3
- package/dist/tech.js +239 -0
- package/dist/tech.js.map +1 -0
- package/dist/techTree.d.ts +7 -0
- package/dist/techTree.js +90 -0
- package/dist/techTree.js.map +1 -0
- package/dist/terrain.d.ts +59 -7
- package/dist/terrain.js +389 -0
- package/dist/terrain.js.map +1 -0
- package/dist/terrainSave.d.ts +6 -0
- package/dist/terrainSave.js +74 -0
- package/dist/terrainSave.js.map +1 -0
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +13 -739
- package/dist/testing.js.map +1 -1
- package/dist/tiles.d.ts +1 -1
- package/dist/tiles.js +43 -0
- package/dist/tiles.js.map +1 -0
- package/dist/timers.d.ts +29 -4
- package/dist/timers.js +242 -0
- package/dist/timers.js.map +1 -0
- package/dist/tomes.d.ts +4 -4
- package/dist/tomes.js +94 -0
- package/dist/tomes.js.map +1 -0
- package/dist/trade.js +103 -0
- package/dist/trade.js.map +1 -0
- package/dist/transport.d.ts +6 -1
- package/dist/transport.js +281 -0
- package/dist/transport.js.map +1 -0
- package/dist/tunables.d.ts +10 -3
- package/dist/tunables.js +56 -0
- package/dist/tunables.js.map +1 -0
- package/dist/unitResources.d.ts +67 -0
- package/dist/unitResources.js +266 -0
- package/dist/unitResources.js.map +1 -0
- package/dist/upkeep.d.ts +6 -1
- package/dist/upkeep.js +26 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/veterancy.d.ts +8 -3
- package/dist/veterancy.js +131 -0
- package/dist/veterancy.js.map +1 -0
- package/dist/vision.d.ts +36 -0
- package/dist/vision.js +133 -0
- package/dist/vision.js.map +1 -0
- package/dist/walls.d.ts +1 -1
- package/dist/walls.js +278 -0
- package/dist/walls.js.map +1 -0
- package/dist/world.d.ts +606 -88
- package/dist/world.js +1263 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
- package/dist/ai.js.map +0 -1
- package/dist/attributes.d.ts +0 -66
- package/dist/brain-BvVdUhX8.js +0 -7659
- package/dist/brain-BvVdUhX8.js.map +0 -1
- package/dist/builds-C6LfgvEU.js +0 -460
- package/dist/builds-C6LfgvEU.js.map +0 -1
- package/dist/coreComponents-syuh2fPG.js +0 -5149
- package/dist/coreComponents-syuh2fPG.js.map +0 -1
- package/dist/debugCommands-CzjrSm66.js +0 -14739
- package/dist/debugCommands-CzjrSm66.js.map +0 -1
- package/dist/determinism-BCymQwiE.js +0 -518
- package/dist/determinism-BCymQwiE.js.map +0 -1
- package/dist/game-DiJEN-Ks.js +0 -5800
- package/dist/game-DiJEN-Ks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect-D9dWHmZ0.js.map +0 -1
- package/dist/local-Dkovq42k.js +0 -1379
- package/dist/local-Dkovq42k.js.map +0 -1
- package/dist/missionRules-C-bGxm0Q.js.map +0 -1
- package/dist/navigation-worker.js.map +0 -1
- package/dist/packs-g5thvmGn.js +0 -3199
- package/dist/packs-g5thvmGn.js.map +0 -1
- package/dist/profiles-B3NS9jwk.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/simulate-oXBiw1Ff.js.map +0 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//#region src/ai/report.ts
|
|
2
|
+
/**
|
|
3
|
+
* How many decisions the log keeps
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
var DECISIONS_KEPT = 50;
|
|
8
|
+
/**
|
|
9
|
+
* The last fifty things a computer player decided (`Brain.decisions`, written by `ai.decide`), oldest first: kept in a
|
|
10
|
+
* save, plain data
|
|
11
|
+
*
|
|
12
|
+
* @beta
|
|
13
|
+
*/
|
|
14
|
+
var Decisions = class {
|
|
15
|
+
limit;
|
|
16
|
+
lines = [];
|
|
17
|
+
constructor(limit = 50) {
|
|
18
|
+
this.limit = limit;
|
|
19
|
+
}
|
|
20
|
+
/** Writes one down: the oldest goes once there are more than the log keeps */
|
|
21
|
+
add(decision) {
|
|
22
|
+
this.lines.push(decision);
|
|
23
|
+
if (this.lines.length > this.limit) this.lines.splice(0, this.lines.length - this.limit);
|
|
24
|
+
}
|
|
25
|
+
/** What it decided, oldest first */
|
|
26
|
+
list() {
|
|
27
|
+
return this.lines;
|
|
28
|
+
}
|
|
29
|
+
/** The last decision about a goal, or of a kind */
|
|
30
|
+
last(about) {
|
|
31
|
+
for (let i = this.lines.length - 1; i >= 0; i--) {
|
|
32
|
+
const line = this.lines[i];
|
|
33
|
+
if ((about.goal === void 0 || line.goal === about.goal) && (about.kind === void 0 || line.kind === about.kind)) return line;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** For a save: a copy */
|
|
37
|
+
save() {
|
|
38
|
+
return this.lines.map((line) => ({ ...line }));
|
|
39
|
+
}
|
|
40
|
+
/** Takes back what `save` gave: what is not a decision is passed over */
|
|
41
|
+
restore(lines) {
|
|
42
|
+
this.lines = Array.isArray(lines) ? lines.filter((line) => !!line && typeof line.line === "string" && typeof line.tick === "number").slice(-this.limit) : [];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** A number as the report writes it: two places */
|
|
46
|
+
var fixed = (x) => x.toFixed(2);
|
|
47
|
+
/** A goal's considerations in one line: "its time has come 1.00 · the wave is ready 0.50", what was not asked left out */
|
|
48
|
+
function considerationsLine(goal) {
|
|
49
|
+
return goal.considerations.filter((each) => each.asked !== false).map((each) => `${each.name} ${fixed(each.curved)}`).join(" · ");
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The consideration that held a goal back most: the one with the least curved value of those asked (a score is their
|
|
53
|
+
* product, so the least is what kept it low), and none for a goal with no considerations
|
|
54
|
+
*/
|
|
55
|
+
function weakest(goal) {
|
|
56
|
+
let least;
|
|
57
|
+
for (const each of goal.considerations) if (each.asked !== false && (!least || each.curved < least.curved)) least = each;
|
|
58
|
+
return least;
|
|
59
|
+
}
|
|
60
|
+
/** A raw value as a sentence writes it: a whole number as it is, the rest to two places */
|
|
61
|
+
var raw = (x) => Number.isInteger(x) ? String(x) : fixed(x);
|
|
62
|
+
/**
|
|
63
|
+
* A goal's row of the report as a sentence (`Brain.explain`): its score, what each question answered and how much that
|
|
64
|
+
* mattered, whether it runs and with what, or why not. `seconds` turns a tick into seconds of the game
|
|
65
|
+
*
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
function explainGoal(goal, seconds, now) {
|
|
69
|
+
const asked = goal.considerations.filter((each) => each.asked !== false);
|
|
70
|
+
const unasked = goal.considerations.length - asked.length;
|
|
71
|
+
const questions = asked.length ? `: ${asked.map((each) => `${each.name} is ${raw(each.value)} (${fixed(each.curved)})`).join(", ")}${unasked ? `; ${unasked} more not asked, the goal vetoed already` : ""}` : "";
|
|
72
|
+
const score = `${goal.id} scores ${fixed(goal.score)}${questions}.`;
|
|
73
|
+
if (goal.picked && goal.held) {
|
|
74
|
+
const left = Math.max(0, Math.round(seconds(goal.held.until) - now));
|
|
75
|
+
const since = Math.max(0, Math.round(now - seconds(goal.held.since)));
|
|
76
|
+
return `${score} It runs with ${goal.held.units === 1 ? "1 unit" : `${goal.held.units} units`} (strength ${Math.round(goal.held.strength)}), for ${since} s now${left ? `, committed for ${left} s more` : ""}${goal.urgent ? ", urgent" : ""}.`;
|
|
77
|
+
}
|
|
78
|
+
if (goal.picked) return `${score} It runs.`;
|
|
79
|
+
if (goal.why) return `${score} It does not run: ${goal.why}.`;
|
|
80
|
+
const limit = weakest(goal);
|
|
81
|
+
if (goal.score <= 0 && limit) return `${score} It does not run: ${limit.name} vetoes it.`;
|
|
82
|
+
return `${score} It does not run: it scores too little${limit ? `, held back most by ${limit.name}` : ""}.`;
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { DECISIONS_KEPT, Decisions, considerationsLine, explainGoal, weakest };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","names":[],"sources":["../../src/ai/report.ts"],"sourcesContent":["import type { PlayerId } from '#engine/entity'\nimport type { ComputerTiming } from './computer'\nimport type { ThinkBudgetOptions } from './budget'\nimport type { GoalReport } from './goals'\nimport type { PlansReport } from './plans/plans'\nimport type { SquadReport } from './squads'\nimport type { MicroReport } from './micro'\nimport type { DefenceReport } from './defence'\nimport type { EconomyReport } from './economy'\nimport type { ScoutingReport } from './scouting'\nimport type { TeamReport } from './team'\nimport type { AiProfile } from './profiles'\nimport type { WavesReport } from './waves'\n\n/*\n * What a computer player is thinking, written down (AI plan, E1): the answer to \"why did it do that\", read rather than\n * guessed. Two things live here:\n *\n * - **The report** (`AiReport`): plain data, put together from the brain when someone looks (`Brain.report`, what\n * `Brain.inspect` gives, and what the debug panel's AI tab draws). The brain writes its own parts (its goals with\n * every consideration's raw and curved value, what it knows, its roles, what it was told), and each module writes\n * its section: a module's `report` hook fills a part of the report the kit names (squads, plans, as those items\n * come), its `inspect` goes under its id in `sections`. Plain data, so it crosses a worker and could cross a wire:\n * the panel draws data, it never reaches a brain.\n * - **The decision log** (`Decisions`): the last fifty things it decided, as a line of text each, with the tick: \"attack\n * picked at 0.80: its time has come 1.00 · the wave is ready 1.00\". The goals' picker writes a line when a goal\n * starts or stops, and a module writes its own (`ai.decide`): a wave sent, a building put up. Each line goes to the\n * world's log too (`debug`, category `ai`) where the logger's level lets it through. The log is kept in a save, so\n * that a save sent with a bug report says what the computer had in mind.\n *\n * Nothing in here decides anything: the report is made only when asked, and the milliseconds in it are for reading.\n */\n\n/**\n * One thing a computer player decided, as a line of text: what it did and the reason that weighed most\n *\n * @beta\n */\nexport interface AiDecision {\n\t/** The tick of the think it was decided at */\n\ttick: number\n\t/** What it is about: `goal` for the goals' picker, or the module's word (`army`, `build`, `research`, `hero`) */\n\tkind: string\n\t/** What was decided, in words: \"attack picked at 0.80 (8 units): its time has come 1.00 · the wave is ready 1.00\" */\n\tline: string\n\t/** The goal it is about, where it is about one */\n\tgoal?: string\n}\n\n/**\n * What a computer player remembers of what it saw, in short, for the report: its rivals' bases and their army as last\n * seen, with how many seconds ago, and the tech seen\n *\n * @beta\n */\nexport interface KnowledgeReport {\n\t/** The enemy bases known, each with its owner, where, how many structures, how many seconds ago it was seen and whether it is gone */\n\tbases: { owner: PlayerId; at: [number, number]; structures: number; seen: number; gone?: true }[]\n\t/** The enemy armies as last seen, each with where, how many fighters and how many seconds ago */\n\tarmy: { at: [number, number]; count: number; seen: number }[]\n\t/** The enemy tech seen: the types of their finished buildings */\n\ttech: string[]\n\t/** How many of its own things were lost */\n\tlost: number\n}\n\n/**\n * What a computer player's play adds up to since it was seated (`Brain.stats`, `AiReport.stats`): the numbers\n * `simulate` reports beside who won, and a test reads to see that the squads send an order once and watch it. Counted,\n * never decided on\n *\n * @beta\n */\nexport interface AiStats {\n\t/** Commands sent */\n\tcommands: number\n\t/** Commands held back past what a think may send (`AiProfile.commandsPerThink`) */\n\theld: number\n\t/** Commands the game refused (a unit that could not do it, a place it could not build at) */\n\trefused: number\n\t/** Seconds its fighters stood idle, summed over the fighters: ten footmen idle for a minute are six hundred */\n\tidleArmySeconds: number\n\t/** Orders sent to a unit again for the same thing within a few seconds: a unit told the same every think stops and starts */\n\tchurn: number\n\t/** Seconds its building waited on money: a want saving up */\n\tblockedOnMoney: number\n\t/** Thinks counted */\n\tthinks: number\n}\n\n/**\n * The threat map as a computer player read it last think (`ThreatMap.cells`, on the ground, the enemy structures it\n * remembers counted): what the game view's AI overlay draws as heat over the ground. The size of a cell, the grid's\n * cells across and down, and each cell with something in it as `[col, row, friendly, enemy]`\n *\n * @beta\n */\nexport interface ThreatReport {\n\t/** The side of a grid cell, in cells of the map */\n\tcell: number\n\t/** How many grid cells across */\n\tcols: number\n\t/** How many grid cells down */\n\trows: number\n\t/** Each grid cell with something in it as `[col, row, friendly, enemy]`, the strength of each side */\n\tcells: [col: number, row: number, friendly: number, enemy: number][]\n}\n\n/**\n * What a computer player is thinking, as plain data (`Brain.report`, `Brain.inspect`): what the debug panel's AI tab\n * draws, and what a test reads. Each module adds its section (`AiModule.report`, `AiModule.inspect`)\n *\n * @beta\n */\nexport interface AiReport {\n\t/** The version of this shape */\n\tv: 1\n\t/** The brain's id (`core.melee`) */\n\tbrain: string\n\t/** The player it plays */\n\tplayer: PlayerId\n\t/** The tick of its last picture of the game */\n\ttick: number\n\t/** Seconds into the game, as of its last picture */\n\ttime: number\n\t/** Ticks a second: what turns a decision's tick into the game's time */\n\ttickRate: number\n\t/** How many times it has thought */\n\tthinks: number\n\t/** Whether it sits still (`world.computers.pause`) */\n\tpaused?: true\n\t/** What it was seated with: the data of its options (`AiOptions`: the difficulty, the numbers); code left out */\n\tprofile: Record<string, unknown>\n\t/** What it plays by (`Brain.profile`): the profile resolved, layer over layer; code (a flag's function) left out */\n\tplaying?: AiProfile\n\t/** The goal that scored highest above the minimum this think: what the army is on. None when nothing is worth doing */\n\tgoal?: string\n\t/** Every goal as the picker last saw it: its score, each consideration's raw and curved value, what it holds, why not */\n\tgoals: GoalReport[]\n\t/** What it remembers of the enemy: left out by a brain that keeps no knowledge */\n\tknowledge?: KnowledgeReport\n\t/** The roles it found among the types it can make: `{ worker: ['peasant'] }` */\n\troles: Record<string, string[]>\n\t/**\n\t * What it has to spend and how it comes in: its resources, its income a minute, its supply; and its economy's say\n\t * (`EconomyReport`): each base with its workers on each resource against what it wants and what is served, the\n\t * workers that fled a raid, the workers had against wanted, where the next hall stands\n\t */\n\teconomy: { resources: Record<string, number>; income: Record<string, number>; supply: [used: number, cap: number] } & Partial<EconomyReport>\n\t/** The raids on its bases with what answers each, every base's raids so far, the towers it wants (`DefenceReport`) */\n\tdefence?: DefenceReport\n\t/** Its plan of looks with how long since each was in sight and whether it is due, its scout and where it goes (`ScoutingReport`) */\n\tscouting?: ScoutingReport\n\t/** Its team: the computers of it, the requests on its board, the plan of an attack together (`TeamReport`) */\n\tteam?: TeamReport\n\t/** Its waves: the one whose turn it is, its group as it stands and when it may go, the waves sent (`WavesReport`) */\n\twaves?: WavesReport\n\t/** Its plans: the purse (what is free, promised, held), and every want of the build plan with what it waits for */\n\tplans: PlansReport\n\t/** Its squads: whose each is, its units and their strength, where it is, its task and how it goes, its last change */\n\tsquads: SquadReport[]\n\t/** Where the strength is, as its threat map read it last think (`ThreatReport`): what the AI overlay draws as heat */\n\tthreat?: ThreatReport\n\t/** Its fights: each squad in one and whom it hits, the units that fled, its heroes and what each learns next, who shops for what */\n\tmicro?: MicroReport\n\t/** The words the game told it that no module has taken yet */\n\ttold: { word: string; tick: number }[]\n\t/** Commands it sent its last think */\n\tsent: number\n\t/** Commands it would have sent its last think past what its profile lets a think send (`commandsPerThink`) */\n\theld?: number\n\t/** How much of a think one tick may do, where its budget slices it (`ThinkBudget`), and the ticks its last think took. Left out where a think is one tick */\n\tbudget?: ThinkBudgetOptions & { ticks: number }\n\t/** What its play adds up to since it was seated (`AiStats`): commands, idle army seconds, churn, seconds blocked on money */\n\tstats: AiStats\n\t/**\n\t * Milliseconds its thinks take, for reading only: the last, an average, the longest, and by module while the world\n\t * profiles. Given by the seat (`inspect` of the player), which times the thinks\n\t */\n\ttiming?: ComputerTiming\n\t/** What it decided, the last fifty, oldest first */\n\tdecisions: AiDecision[]\n\t/** What each module says of itself that the report has no part for (`AiModule.inspect`), under the module's id */\n\tsections: Record<string, unknown>\n}\n\n/**\n * How many decisions the log keeps\n *\n * @internal\n */\nexport const DECISIONS_KEPT = 50\n\n/**\n * The last fifty things a computer player decided (`Brain.decisions`, written by `ai.decide`), oldest first: kept in a\n * save, plain data\n *\n * @beta\n */\nexport class Decisions {\n\tprivate lines: AiDecision[] = []\n\n\tconstructor(private readonly limit = DECISIONS_KEPT) {}\n\n\t/** Writes one down: the oldest goes once there are more than the log keeps */\n\tadd(decision: AiDecision): void {\n\t\tthis.lines.push(decision)\n\t\tif (this.lines.length > this.limit) this.lines.splice(0, this.lines.length - this.limit)\n\t}\n\n\t/** What it decided, oldest first */\n\tlist(): readonly AiDecision[] {\n\t\treturn this.lines\n\t}\n\n\t/** The last decision about a goal, or of a kind */\n\tlast(about: { goal?: string; kind?: string }): AiDecision | undefined {\n\t\tfor (let i = this.lines.length - 1; i >= 0; i--) {\n\t\t\tconst line = this.lines[i]\n\t\t\tif ((about.goal === undefined || line.goal === about.goal) && (about.kind === undefined || line.kind === about.kind)) return line\n\t\t}\n\t\treturn undefined\n\t}\n\n\t/** For a save: a copy */\n\tsave(): AiDecision[] {\n\t\treturn this.lines.map((line) => ({ ...line }))\n\t}\n\n\t/** Takes back what `save` gave: what is not a decision is passed over */\n\trestore(lines: unknown): void {\n\t\tthis.lines = Array.isArray(lines)\n\t\t\t? lines.filter((line): line is AiDecision => !!line && typeof line.line === 'string' && typeof line.tick === 'number').slice(-this.limit)\n\t\t\t: []\n\t}\n}\n\n/** A number as the report writes it: two places */\nconst fixed = (x: number) => x.toFixed(2)\n\n/** A goal's considerations in one line: \"its time has come 1.00 · the wave is ready 0.50\", what was not asked left out */\nexport function considerationsLine(goal: Pick<GoalReport, 'considerations'>): string {\n\treturn goal.considerations\n\t\t.filter((each) => each.asked !== false)\n\t\t.map((each) => `${each.name} ${fixed(each.curved)}`)\n\t\t.join(' · ')\n}\n\n/**\n * The consideration that held a goal back most: the one with the least curved value of those asked (a score is their\n * product, so the least is what kept it low), and none for a goal with no considerations\n */\nexport function weakest(goal: GoalReport): GoalReport['considerations'][number] | undefined {\n\tlet least: GoalReport['considerations'][number] | undefined\n\tfor (const each of goal.considerations) if (each.asked !== false && (!least || each.curved < least.curved)) least = each\n\treturn least\n}\n\n/** A raw value as a sentence writes it: a whole number as it is, the rest to two places */\nconst raw = (x: number) => (Number.isInteger(x) ? String(x) : fixed(x))\n\n/**\n * A goal's row of the report as a sentence (`Brain.explain`): its score, what each question answered and how much that\n * mattered, whether it runs and with what, or why not. `seconds` turns a tick into seconds of the game\n *\n * @internal\n */\nexport function explainGoal(goal: GoalReport, seconds: (tick: number) => number, now: number): string {\n\tconst asked = goal.considerations.filter((each) => each.asked !== false)\n\tconst unasked = goal.considerations.length - asked.length\n\tconst questions = asked.length\n\t\t? `: ${asked.map((each) => `${each.name} is ${raw(each.value)} (${fixed(each.curved)})`).join(', ')}${unasked ? `; ${unasked} more not asked, the goal vetoed already` : ''}`\n\t\t: ''\n\tconst score = `${goal.id} scores ${fixed(goal.score)}${questions}.`\n\tif (goal.picked && goal.held) {\n\t\tconst left = Math.max(0, Math.round(seconds(goal.held.until) - now))\n\t\tconst since = Math.max(0, Math.round(now - seconds(goal.held.since)))\n\t\tconst units = goal.held.units === 1 ? '1 unit' : `${goal.held.units} units`\n\t\treturn `${score} It runs with ${units} (strength ${Math.round(goal.held.strength)}), for ${since} s now${left ? `, committed for ${left} s more` : ''}${goal.urgent ? ', urgent' : ''}.`\n\t}\n\tif (goal.picked) return `${score} It runs.`\n\tif (goal.why) return `${score} It does not run: ${goal.why}.`\n\tconst limit = weakest(goal)\n\tif (goal.score <= 0 && limit) return `${score} It does not run: ${limit.name} vetoes it.`\n\treturn `${score} It does not run: it scores too little${limit ? `, held back most by ${limit.name}` : ''}.`\n}\n"],"mappings":"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"}
|
package/dist/ai/roles.d.ts
CHANGED
|
@@ -56,8 +56,11 @@ export interface AiHints {
|
|
|
56
56
|
* @beta
|
|
57
57
|
*/
|
|
58
58
|
export interface RoleEntry {
|
|
59
|
+
/** The unit type's roles, such as fighter or worker */
|
|
59
60
|
roles: AiRole[];
|
|
61
|
+
/** The unit type's tags, the game's own names for what it is */
|
|
60
62
|
tags: string[];
|
|
63
|
+
/** A line for each role that was inferred, saying why; none for declared ones */
|
|
61
64
|
why?: string[];
|
|
62
65
|
}
|
|
63
66
|
/**
|
|
@@ -73,6 +76,7 @@ export type RoleTable = Record<string, RoleEntry>;
|
|
|
73
76
|
* @beta
|
|
74
77
|
*/
|
|
75
78
|
export interface RolesPlayer {
|
|
79
|
+
/** The player's id */
|
|
76
80
|
id: PlayerId;
|
|
77
81
|
/** The race it plays, where the game has races */
|
|
78
82
|
race?: string;
|
package/dist/ai/roles.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { baseStats, supplyGivenOf, upgradesOf } from "../defs.js";
|
|
2
|
+
import { availableToPlayer } from "../shared.js";
|
|
3
|
+
//#region src/ai/roles.ts
|
|
4
|
+
/** The tags the kit infers from an attack: for a brain that asks for the ranged or for what hits the air */
|
|
5
|
+
var RANGED = "ranged";
|
|
6
|
+
var MELEE = "melee";
|
|
7
|
+
var HITS_AIR = "hitsAir";
|
|
8
|
+
/** What fights: a unit with an attack that is not a worker (a worker that builds does not fight; a ghoul, which only gathers, does) */
|
|
9
|
+
var fights = (def) => def.kind === "unit" && !!def.attacks?.length && !(def.harvester && def.builds?.length);
|
|
10
|
+
/** Whether a building takes deposits of a resource: all of them, or that one among those it lists */
|
|
11
|
+
var takes = (def, kind) => kind !== void 0 && (def.dropOff === true || Array.isArray(def.dropOff) && def.dropOff.includes(kind));
|
|
12
|
+
/** What a race's types are, for the rules that look across a race: those of its race, and those of none */
|
|
13
|
+
var ofRace = (def, race) => def.race === void 0 || def.race === race;
|
|
14
|
+
/**
|
|
15
|
+
* Infers what every unit type of the game is for, from its definition: the rules, written down once, each with its
|
|
16
|
+
* reason (`RoleEntry.why`). What a game declares (`UnitTypeDef.ai.role`) is not looked at here: `findRoles` puts it
|
|
17
|
+
* over what is inferred
|
|
18
|
+
*
|
|
19
|
+
* @beta
|
|
20
|
+
*/
|
|
21
|
+
function inferRoles(registry) {
|
|
22
|
+
const table = {};
|
|
23
|
+
const all = registry.units.all();
|
|
24
|
+
const money = registry.currency ?? registry.resources[0]?.id;
|
|
25
|
+
const heals = (def) => (def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === "heal"));
|
|
26
|
+
const detects = (def) => (def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === "detect"));
|
|
27
|
+
const workers = all.filter((def) => def.kind === "unit" && def.harvester && def.builds?.length);
|
|
28
|
+
const trainsWorker = (def) => !!def.trains?.some((id) => workers.some((worker) => worker.id === id));
|
|
29
|
+
const hallsOf = (race) => all.filter((def) => def.kind === "building" && def.dropOff && !def.builtOn && ofRace(def, race) && trainsWorker(def));
|
|
30
|
+
const soldiers = all.filter((def) => fights(def) && !def.hero);
|
|
31
|
+
const speed = (def) => baseStats(def, registry).moveSpeed;
|
|
32
|
+
const scoutOf = (race) => {
|
|
33
|
+
let best;
|
|
34
|
+
for (const def of soldiers) if (def.race === race && (!best || speed(def) > speed(best))) best = def;
|
|
35
|
+
return best;
|
|
36
|
+
};
|
|
37
|
+
for (const def of all) {
|
|
38
|
+
const roles = [];
|
|
39
|
+
const why = [];
|
|
40
|
+
const tags = [];
|
|
41
|
+
const give = (role, reason) => {
|
|
42
|
+
roles.push(role);
|
|
43
|
+
why.push(`${role}: ${reason}`);
|
|
44
|
+
};
|
|
45
|
+
if (def.kind === "unit") {
|
|
46
|
+
if (def.harvester && def.builds?.length) give("worker", "gathers and builds");
|
|
47
|
+
if (def.harvester) give("gatherer", "gathers");
|
|
48
|
+
if (def.hero) give("hero", "a hero");
|
|
49
|
+
else if (fights(def)) give("soldier", "fights and is no hero");
|
|
50
|
+
if (fights(def) && !def.hero && def.abilities?.length && baseStats(def, registry).mana > 0) give("caster", "fights with mana and abilities");
|
|
51
|
+
if (heals(def)) give("healer", "has an ability that heals");
|
|
52
|
+
if (def.attacks?.some((attack) => attack.splash || attack.fells || attack.ground)) give("siege", "its attacks splash, fell or are aimed at the ground");
|
|
53
|
+
if (def.flying) give("air", "flies");
|
|
54
|
+
if (!def.hero && fights(def) && scoutOf(def.race) === def) give("scout", "the fastest of its soldiers");
|
|
55
|
+
if (detects(def)) give("detector", "has an ability that finds the invisible");
|
|
56
|
+
} else if (def.kind === "building") {
|
|
57
|
+
if (def.builtOn !== void 0 && def.builtOn === money && takes(def, money)) give("topper", "put up on a deposit of the money, where it is gathered");
|
|
58
|
+
else if (def.dropOff && !def.builtOn) {
|
|
59
|
+
const halls = hallsOf(def.race);
|
|
60
|
+
if (trainsWorker(def)) give("hall", "takes deposits and trains workers");
|
|
61
|
+
else if (halls.length === 0) give("hall", "takes deposits, and nothing of its race takes them and trains workers");
|
|
62
|
+
}
|
|
63
|
+
if (supplyGivenOf(def) && !def.trains?.length) give("supply", "provides supply and trains nothing");
|
|
64
|
+
if (def.trains?.some((id) => registry.units.has(id) && fights(registry.unit(id)) && !registry.unit(id).hero)) give("barracks", "trains soldiers");
|
|
65
|
+
if (def.revives || def.trains?.some((id) => registry.units.has(id) && registry.unit(id).hero)) give("altar", "trains or revives heroes");
|
|
66
|
+
if (def.researches?.length) give("workshop", "researches");
|
|
67
|
+
if (def.attacks?.length && !def.transport?.armed) give("tower", "a building that attacks by itself");
|
|
68
|
+
if (def.sells?.length || def.hires?.length) give("shop", "sells or hires");
|
|
69
|
+
if (detects(def)) give("detector", "has an ability that finds the invisible");
|
|
70
|
+
}
|
|
71
|
+
const attacks = def.attacks ?? [];
|
|
72
|
+
if (attacks.some((attack) => attack.projectileSpeed)) tags.push(RANGED);
|
|
73
|
+
if (attacks.some((attack) => !attack.projectileSpeed)) tags.push(MELEE);
|
|
74
|
+
if (attacks.some((attack) => attack.targets?.includes("air"))) tags.push(HITS_AIR);
|
|
75
|
+
table[def.id] = {
|
|
76
|
+
roles,
|
|
77
|
+
tags,
|
|
78
|
+
why
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return table;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* What the unit types of a game are for (`AiView.roles`): the inferred roles (`inferRoles`, or a game's own finder
|
|
85
|
+
* in its place) with what the game declares on a type over them (`UnitTypeDef.ai`), and the queries over them
|
|
86
|
+
*
|
|
87
|
+
* @beta
|
|
88
|
+
*/
|
|
89
|
+
var Roles = class {
|
|
90
|
+
table;
|
|
91
|
+
registry;
|
|
92
|
+
byRole = /* @__PURE__ */ new Map();
|
|
93
|
+
byTag = /* @__PURE__ */ new Map();
|
|
94
|
+
constructor(table, registry) {
|
|
95
|
+
this.table = table;
|
|
96
|
+
this.registry = registry;
|
|
97
|
+
}
|
|
98
|
+
/** The roles of a unit type: none for one that has none, or is not a unit type at all */
|
|
99
|
+
of(type) {
|
|
100
|
+
return this.table[type]?.roles ?? NONE;
|
|
101
|
+
}
|
|
102
|
+
/** Whether a unit type has a role */
|
|
103
|
+
has(type, role) {
|
|
104
|
+
return this.of(type).includes(role);
|
|
105
|
+
}
|
|
106
|
+
/** The tags of a unit type: the kit's (`ranged`, `melee`, `hitsAir`) and the game's (`UnitTypeDef.ai.tags`) */
|
|
107
|
+
tags(type) {
|
|
108
|
+
return this.table[type]?.tags ?? NONE;
|
|
109
|
+
}
|
|
110
|
+
/** Whether a unit type has a tag */
|
|
111
|
+
hasTag(type, tag) {
|
|
112
|
+
return this.tags(type).includes(tag);
|
|
113
|
+
}
|
|
114
|
+
/** The unit types with a role, in the game's order (the first of a kind is the one meant first) */
|
|
115
|
+
types(role) {
|
|
116
|
+
let found = this.byRole.get(role);
|
|
117
|
+
if (!found) this.byRole.set(role, found = this.registry.units.all().filter((def) => this.has(def.id, role)));
|
|
118
|
+
return found;
|
|
119
|
+
}
|
|
120
|
+
/** The unit types with a tag, in the game's order */
|
|
121
|
+
tagged(tag) {
|
|
122
|
+
let found = this.byTag.get(tag);
|
|
123
|
+
if (!found) this.byTag.set(tag, found = this.registry.units.all().filter((def) => this.hasTag(def.id, tag)));
|
|
124
|
+
return found;
|
|
125
|
+
}
|
|
126
|
+
/** What a game declared of a type (`UnitTypeDef.ai`): nothing where it declared nothing */
|
|
127
|
+
hints(type) {
|
|
128
|
+
return this.registry.units.has(type) ? this.registry.unit(type).ai : void 0;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Why a type has the roles it has, in words, for the report: `declared: worker` for what the game said, a line per
|
|
132
|
+
* inferred role otherwise
|
|
133
|
+
*/
|
|
134
|
+
explain(type) {
|
|
135
|
+
const entry = this.table[type];
|
|
136
|
+
if (!entry) return "no roles";
|
|
137
|
+
if (!entry.roles.length) return "none";
|
|
138
|
+
return entry.why?.length ? entry.why.join("; ") : `declared: ${entry.roles.join(", ")}`;
|
|
139
|
+
}
|
|
140
|
+
/** Every role and the types that have it, for the report (the debug tools) */
|
|
141
|
+
report() {
|
|
142
|
+
const report = {};
|
|
143
|
+
for (const [type, entry] of Object.entries(this.table)) for (const role of entry.roles) (report[role] ??= []).push(type);
|
|
144
|
+
return report;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
var NONE = [];
|
|
148
|
+
/**
|
|
149
|
+
* Finds what the unit types of a game are for, for a player: inferred from the definitions (`inferRoles`), or by
|
|
150
|
+
* the game's own finder where it gives one (`AiOptions.roles`), with what the game declares on a type
|
|
151
|
+
* (`UnitTypeDef.ai.role`) over either, and the game's tags beside the inferred ones. What the view does once per
|
|
152
|
+
* brain (`AiView.roles`), again only when the game's definitions change
|
|
153
|
+
*
|
|
154
|
+
* @internal
|
|
155
|
+
*/
|
|
156
|
+
function findRoles(registry, player, finder) {
|
|
157
|
+
const table = finder ? finder(registry, player) : inferRoles(registry);
|
|
158
|
+
for (const def of registry.units.all()) {
|
|
159
|
+
const hints = def.ai;
|
|
160
|
+
if (!hints) continue;
|
|
161
|
+
const entry = table[def.id] ??= {
|
|
162
|
+
roles: [],
|
|
163
|
+
tags: []
|
|
164
|
+
};
|
|
165
|
+
if (hints.role !== void 0) {
|
|
166
|
+
entry.roles = Array.isArray(hints.role) ? [...hints.role] : [hints.role];
|
|
167
|
+
delete entry.why;
|
|
168
|
+
}
|
|
169
|
+
if (hints.tags) entry.tags = [.../* @__PURE__ */ new Set([...entry.tags, ...hints.tags])];
|
|
170
|
+
}
|
|
171
|
+
return new Roles(table, registry);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* The unit types a player has or can come to make, from what it has (`owned`): what its units build, its buildings
|
|
175
|
+
* train and what they turn into, followed through, of what its race and the game's `available` hook let it make.
|
|
176
|
+
* Of the whole game, for a player with nothing yet. What the view narrows the roles to for the player (`AiView.typesOf`)
|
|
177
|
+
*
|
|
178
|
+
* @internal
|
|
179
|
+
*/
|
|
180
|
+
function reachableTypes(registry, player, owned) {
|
|
181
|
+
const mine = new Set(owned);
|
|
182
|
+
const may = (def) => availableToPlayer(def, {
|
|
183
|
+
race: player.race,
|
|
184
|
+
availability: player.availability
|
|
185
|
+
}, def.id);
|
|
186
|
+
const reach = /* @__PURE__ */ new Set();
|
|
187
|
+
const next = [...mine];
|
|
188
|
+
while (next.length) {
|
|
189
|
+
const id = next.pop();
|
|
190
|
+
if (reach.has(id) || !registry.units.has(id)) continue;
|
|
191
|
+
const def = registry.unit(id);
|
|
192
|
+
if (!mine.has(id) && !may(def)) continue;
|
|
193
|
+
reach.add(id);
|
|
194
|
+
for (const made of [
|
|
195
|
+
...def.builds ?? [],
|
|
196
|
+
...def.trains ?? [],
|
|
197
|
+
...upgradesOf(def)
|
|
198
|
+
]) if (!reach.has(made)) next.push(made);
|
|
199
|
+
}
|
|
200
|
+
if (reach.size) return reach;
|
|
201
|
+
for (const def of registry.units.all()) if (may(def)) reach.add(def.id);
|
|
202
|
+
return reach;
|
|
203
|
+
}
|
|
204
|
+
//#endregion
|
|
205
|
+
export { Roles, findRoles, inferRoles, reachableTypes };
|
|
206
|
+
|
|
207
|
+
//# sourceMappingURL=roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.js","names":[],"sources":["../../src/ai/roles.ts"],"sourcesContent":["import { baseStats, supplyGivenOf, type UnitTypeDef, upgradesOf } from '#engine/defs'\nimport type { PlayerId } from '#engine/entity'\nimport type { Registry } from '#engine/registry'\nimport { availableToPlayer } from '#engine/shared'\nimport type { PlacementName } from './plans/placement'\nimport type { CounterHint } from './strength'\n\n/*\n * What unit types are for, to a computer player (AI plan, A2). The kit knows nothing of any one game: it does not know what\n * a \"farm\" or a \"town hall\" is. It knows roles: the worker is what gathers and builds, the hall is where what is\n * gathered is brought and workers come from, supply is the cheapest building that provides supply and trains nothing,\n * and so on. A game declares a type's roles where it wants to (`UnitTypeDef.ai.role`), and what it does not declare is\n * inferred here from the definition, by the rules written down in `inferRoles`, each with its reason, the one place\n * those inferences live. When a role is wrong in a game, the fix is a declaration in the game, not a special case in\n * the kit. The inferences are visible in the report (`Roles.explain`), so that a wrong one is seen, not guessed at.\n *\n * Roles are of a type, not of a player: an enemy's hall is a hall. What of the roles is a player's own (the types it\n * has or can make, as its race and the game's `available` hook say) is the view's to say (`AiView.typesOf`)\n */\n\n/**\n * What a unit type is for, to a computer player: the engine's roles, or a word of the game's own. A type can have\n * several (a ghoul is a `gatherer` and a `soldier`)\n *\n * - `worker`: gathers and builds; `gatherer`: gathers (a worker is one too); `topper`: what is put up on a deposit of\n * the money to gather it there (`builtOn`)\n * - `hall`: takes deposits and trains workers; `supply`: provides supply and trains nothing; `barracks`: trains\n * soldiers; `altar`: trains or revives heroes; `workshop`: researches; `tower`: a building that attacks; `shop`:\n * sells or hires\n * - `soldier`: a unit that fights and is no hero; `hero`; `caster`: fights with mana; `healer`: has an ability that\n * heals; `siege`: attacks that splash, fell or are aimed at the ground; `air`: flies; `scout`: the fastest of the\n * soldiers; `detector`: finds the invisible\n *\n * @beta\n */\nexport type AiRole =\n\t| 'worker'\n\t| 'gatherer'\n\t| 'topper'\n\t| 'hall'\n\t| 'supply'\n\t| 'barracks'\n\t| 'altar'\n\t| 'workshop'\n\t| 'tower'\n\t| 'shop'\n\t| 'soldier'\n\t| 'hero'\n\t| 'caster'\n\t| 'healer'\n\t| 'siege'\n\t| 'air'\n\t| 'scout'\n\t| 'detector'\n\t| (string & {})\n\n/**\n * What a game declares of a unit type for the computer player (`UnitTypeDef.ai`), where what the kit infers from the\n * definition is wrong or cannot be known: its roles, words of the game's own about it, what it answers, how much it\n * is worth hitting. A declared role is in place of the inferred ones, not beside them\n *\n * @beta\n */\nexport interface AiHints {\n\t/** What it is for (`AiRole`), one or several: in place of what the kit would infer */\n\trole?: AiRole | AiRole[]\n\t/** Words of the game's own about it (`'ranged'`, `'cavalry'`), for a brain's queries (`UnitSet.withTag`). Beside the inferred ones */\n\ttags?: string[]\n\t/**\n\t * What it is good against: tags, roles or type ids (`['air', 'siege']`), each with a weight where a word is not enough\n\t * (`{ target: 'air', weight: 1 }`). Read by the matchups (`Strength.matchup`, `odds`, `counterFor`)\n\t */\n\tcounters?: CounterHint[]\n\t/**\n\t * How strong it is at full health, in place of the kit's formula (`defaultStrength`) and of any formula the brain was\n\t * given: for a type whose numbers mislead (a unit that is all spells). Scaled by the health a unit has left\n\t */\n\tstrength?: number\n\t/** How much it is worth hitting first, in a fight: 1 when left out. Read by the micro of C2 */\n\tpriority?: number\n\t/**\n\t * Where the build plan puts it (`PlacementName`): `atEdge` for a tower, `behind` for supply, `cluster` beside its\n\t * own kind. Over the brain's table; the role's default when left out\n\t */\n\tplacement?: PlacementName\n}\n\n/**\n * The roles and tags of one unit type, with why (`why`: a line per inferred role, for the report; none for a declared\n * one)\n *\n * @beta\n */\nexport interface RoleEntry {\n\t/** The unit type's roles, such as fighter or worker */\n\troles: AiRole[]\n\t/** The unit type's tags, the game's own names for what it is */\n\ttags: string[]\n\t/** A line for each role that was inferred, saying why; none for declared ones */\n\twhy?: string[]\n}\n\n/**\n * The roles and tags of every unit type of a game, by type id: what `inferRoles` gives, and what a game's own\n * `AiOptions.roles` gives in its place\n *\n * @beta\n */\nexport type RoleTable = Record<string, RoleEntry>\n\n/**\n * The player the roles are found for, where finding them depends on who asks (`AiOptions.roles`)\n *\n * @beta\n */\nexport interface RolesPlayer {\n\t/** The player's id */\n\tid: PlayerId\n\t/** The race it plays, where the game has races */\n\trace?: string\n\t/** What the game's `available` hook decided for it, by type (`PlayerState.own.availability`) */\n\tavailability?: Record<string, boolean>\n}\n\n/**\n * A game's own way of saying what unit types are for, in place of the kit's inference (`AiOptions.roles`): every type\n * it has a role for, with its roles and tags. What is declared on a type (`UnitTypeDef.ai`) still goes over it\n *\n * @beta\n */\nexport type RolesFinder = (registry: Registry, player: RolesPlayer) => RoleTable\n\n/** The tags the kit infers from an attack: for a brain that asks for the ranged or for what hits the air */\nconst RANGED = 'ranged'\nconst MELEE = 'melee'\nconst HITS_AIR = 'hitsAir'\n\n/** What fights: a unit with an attack that is not a worker (a worker that builds does not fight; a ghoul, which only gathers, does) */\nconst fights = (def: UnitTypeDef): boolean => def.kind === 'unit' && !!def.attacks?.length && !(def.harvester && def.builds?.length)\n\n/** Whether a building takes deposits of a resource: all of them, or that one among those it lists */\nconst takes = (def: UnitTypeDef, kind: string | undefined): boolean =>\n\tkind !== undefined && (def.dropOff === true || (Array.isArray(def.dropOff) && def.dropOff.includes(kind)))\n\n/** What a race's types are, for the rules that look across a race: those of its race, and those of none */\nconst ofRace = (def: UnitTypeDef, race: string | undefined): boolean => def.race === undefined || def.race === race\n\n/**\n * Infers what every unit type of the game is for, from its definition: the rules, written down once, each with its\n * reason (`RoleEntry.why`). What a game declares (`UnitTypeDef.ai.role`) is not looked at here: `findRoles` puts it\n * over what is inferred\n *\n * @beta\n */\nexport function inferRoles(registry: Registry): RoleTable {\n\tconst table: RoleTable = {}\n\tconst all = registry.units.all()\n\tconst money = registry.currency ?? registry.resources[0]?.id\n\tconst heals = (def: UnitTypeDef) =>\n\t\t(def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === 'heal'))\n\tconst detects = (def: UnitTypeDef) =>\n\t\t(def.abilities ?? []).some((id) => registry.abilities.has(id) && registry.ability(id).effects.some((effect) => effect.type === 'detect'))\n\t// a worker's kind: the units that gather and build. A race has one; the rules about halls look for it\n\tconst workers = all.filter((def) => def.kind === 'unit' && def.harvester && def.builds?.length)\n\tconst trainsWorker = (def: UnitTypeDef) => !!def.trains?.some((id) => workers.some((worker) => worker.id === id))\n\t// a hall is where deposits go and workers come from. A race with no building that does both (a lanes game with a\n\t// drop-off and no workers) has its drop-offs for halls, whatever they train\n\tconst hallsOf = (race: string | undefined) =>\n\t\tall.filter((def) => def.kind === 'building' && def.dropOff && !def.builtOn && ofRace(def, race) && trainsWorker(def))\n\t// the soldiers of a race, for the scout: the fastest of them\n\tconst soldiers = all.filter((def) => fights(def) && !def.hero)\n\tconst speed = (def: UnitTypeDef) => baseStats(def, registry).moveSpeed\n\t// of its own race alone: a creep of no race is no one's scout\n\tconst scoutOf = (race: string | undefined): UnitTypeDef | undefined => {\n\t\tlet best: UnitTypeDef | undefined\n\t\tfor (const def of soldiers) if (def.race === race && (!best || speed(def) > speed(best))) best = def\n\t\treturn best\n\t}\n\n\tfor (const def of all) {\n\t\tconst roles: AiRole[] = []\n\t\tconst why: string[] = []\n\t\tconst tags: string[] = []\n\t\tconst give = (role: AiRole, reason: string) => {\n\t\t\troles.push(role)\n\t\t\twhy.push(`${role}: ${reason}`)\n\t\t}\n\t\tif (def.kind === 'unit') {\n\t\t\tif (def.harvester && def.builds?.length) give('worker', 'gathers and builds')\n\t\t\tif (def.harvester) give('gatherer', 'gathers')\n\t\t\tif (def.hero) give('hero', 'a hero')\n\t\t\telse if (fights(def)) give('soldier', 'fights and is no hero')\n\t\t\tif (fights(def) && !def.hero && def.abilities?.length && baseStats(def, registry).mana > 0) give('caster', 'fights with mana and abilities')\n\t\t\tif (heals(def)) give('healer', 'has an ability that heals')\n\t\t\tif (def.attacks?.some((attack) => attack.splash || attack.fells || attack.ground))\n\t\t\t\tgive('siege', 'its attacks splash, fell or are aimed at the ground')\n\t\t\tif (def.flying) give('air', 'flies')\n\t\t\tif (!def.hero && fights(def) && scoutOf(def.race) === def) give('scout', 'the fastest of its soldiers')\n\t\t\tif (detects(def)) give('detector', 'has an ability that finds the invisible')\n\t\t} else if (def.kind === 'building') {\n\t\t\tif (def.builtOn !== undefined && def.builtOn === money && takes(def, money))\n\t\t\t\tgive('topper', 'put up on a deposit of the money, where it is gathered')\n\t\t\telse if (def.dropOff && !def.builtOn) {\n\t\t\t\tconst halls = hallsOf(def.race)\n\t\t\t\tif (trainsWorker(def)) give('hall', 'takes deposits and trains workers')\n\t\t\t\telse if (halls.length === 0) give('hall', 'takes deposits, and nothing of its race takes them and trains workers')\n\t\t\t}\n\t\t\tif (supplyGivenOf(def) && !def.trains?.length) give('supply', 'provides supply and trains nothing')\n\t\t\tif (def.trains?.some((id) => registry.units.has(id) && fights(registry.unit(id)) && !registry.unit(id).hero))\n\t\t\t\tgive('barracks', 'trains soldiers')\n\t\t\tif (def.revives || def.trains?.some((id) => registry.units.has(id) && registry.unit(id).hero)) give('altar', 'trains or revives heroes')\n\t\t\tif (def.researches?.length) give('workshop', 'researches')\n\t\t\t// not one that shoots only with units inside it (a burrow): that is shelter, not a defence to put up\n\t\t\tif (def.attacks?.length && !def.transport?.armed) give('tower', 'a building that attacks by itself')\n\t\t\tif (def.sells?.length || def.hires?.length) give('shop', 'sells or hires')\n\t\t\tif (detects(def)) give('detector', 'has an ability that finds the invisible')\n\t\t}\n\t\t// of each of its attacks: one that shoots, one that strikes, one that hits the air\n\t\tconst attacks = def.attacks ?? []\n\t\tif (attacks.some((attack) => attack.projectileSpeed)) tags.push(RANGED)\n\t\tif (attacks.some((attack) => !attack.projectileSpeed)) tags.push(MELEE)\n\t\tif (attacks.some((attack) => attack.targets?.includes('air'))) tags.push(HITS_AIR)\n\t\ttable[def.id] = { roles, tags, why }\n\t}\n\treturn table\n}\n\n/**\n * What the unit types of a game are for (`AiView.roles`): the inferred roles (`inferRoles`, or a game's own finder\n * in its place) with what the game declares on a type over them (`UnitTypeDef.ai`), and the queries over them\n *\n * @beta\n */\nexport class Roles {\n\tprivate readonly byRole = new Map<string, UnitTypeDef[]>()\n\tprivate readonly byTag = new Map<string, UnitTypeDef[]>()\n\n\tconstructor(\n\t\t/** Every unit type's roles and tags, by id */\n\t\treadonly table: RoleTable,\n\t\tprivate readonly registry: Registry\n\t) {}\n\n\t/** The roles of a unit type: none for one that has none, or is not a unit type at all */\n\tof(type: string): readonly AiRole[] {\n\t\treturn this.table[type]?.roles ?? NONE\n\t}\n\n\t/** Whether a unit type has a role */\n\thas(type: string, role: AiRole): boolean {\n\t\treturn this.of(type).includes(role)\n\t}\n\n\t/** The tags of a unit type: the kit's (`ranged`, `melee`, `hitsAir`) and the game's (`UnitTypeDef.ai.tags`) */\n\ttags(type: string): readonly string[] {\n\t\treturn this.table[type]?.tags ?? NONE\n\t}\n\n\t/** Whether a unit type has a tag */\n\thasTag(type: string, tag: string): boolean {\n\t\treturn this.tags(type).includes(tag)\n\t}\n\n\t/** The unit types with a role, in the game's order (the first of a kind is the one meant first) */\n\ttypes(role: AiRole): readonly UnitTypeDef[] {\n\t\tlet found = this.byRole.get(role)\n\t\tif (!found) this.byRole.set(role, (found = this.registry.units.all().filter((def) => this.has(def.id, role))))\n\t\treturn found\n\t}\n\n\t/** The unit types with a tag, in the game's order */\n\ttagged(tag: string): readonly UnitTypeDef[] {\n\t\tlet found = this.byTag.get(tag)\n\t\tif (!found) this.byTag.set(tag, (found = this.registry.units.all().filter((def) => this.hasTag(def.id, tag))))\n\t\treturn found\n\t}\n\n\t/** What a game declared of a type (`UnitTypeDef.ai`): nothing where it declared nothing */\n\thints(type: string): AiHints | undefined {\n\t\treturn this.registry.units.has(type) ? this.registry.unit(type).ai : undefined\n\t}\n\n\t/**\n\t * Why a type has the roles it has, in words, for the report: `declared: worker` for what the game said, a line per\n\t * inferred role otherwise\n\t */\n\texplain(type: string): string {\n\t\tconst entry = this.table[type]\n\t\tif (!entry) return 'no roles'\n\t\tif (!entry.roles.length) return 'none'\n\t\treturn entry.why?.length ? entry.why.join('; ') : `declared: ${entry.roles.join(', ')}`\n\t}\n\n\t/** Every role and the types that have it, for the report (the debug tools) */\n\treport(): Record<string, string[]> {\n\t\tconst report: Record<string, string[]> = {}\n\t\tfor (const [type, entry] of Object.entries(this.table)) for (const role of entry.roles) (report[role] ??= []).push(type)\n\t\treturn report\n\t}\n}\n\nconst NONE: readonly never[] = []\n\n/**\n * Finds what the unit types of a game are for, for a player: inferred from the definitions (`inferRoles`), or by\n * the game's own finder where it gives one (`AiOptions.roles`), with what the game declares on a type\n * (`UnitTypeDef.ai.role`) over either, and the game's tags beside the inferred ones. What the view does once per\n * brain (`AiView.roles`), again only when the game's definitions change\n *\n * @internal\n */\nexport function findRoles(registry: Registry, player: RolesPlayer, finder?: RolesFinder): Roles {\n\tconst table = finder ? finder(registry, player) : inferRoles(registry)\n\tfor (const def of registry.units.all()) {\n\t\tconst hints = def.ai\n\t\tif (!hints) continue\n\t\tconst entry = (table[def.id] ??= { roles: [], tags: [] })\n\t\tif (hints.role !== undefined) {\n\t\t\tentry.roles = Array.isArray(hints.role) ? [...hints.role] : [hints.role]\n\t\t\tdelete entry.why\n\t\t}\n\t\tif (hints.tags) entry.tags = [...new Set([...entry.tags, ...hints.tags])]\n\t}\n\treturn new Roles(table, registry)\n}\n\n/**\n * The unit types a player has or can come to make, from what it has (`owned`): what its units build, its buildings\n * train and what they turn into, followed through, of what its race and the game's `available` hook let it make.\n * Of the whole game, for a player with nothing yet. What the view narrows the roles to for the player (`AiView.typesOf`)\n *\n * @internal\n */\nexport function reachableTypes(registry: Registry, player: RolesPlayer, owned: Iterable<string>): Set<string> {\n\tconst mine = new Set(owned)\n\tconst may = (def: UnitTypeDef) => availableToPlayer(def, { race: player.race, availability: player.availability }, def.id)\n\tconst reach = new Set<string>()\n\tconst next = [...mine]\n\twhile (next.length) {\n\t\tconst id = next.pop()!\n\t\tif (reach.has(id) || !registry.units.has(id)) continue\n\t\tconst def = registry.unit(id)\n\t\t// what it may not make (another race's) is not reached through, but what it has is its own\n\t\tif (!mine.has(id) && !may(def)) continue\n\t\treach.add(id)\n\t\tfor (const made of [...(def.builds ?? []), ...(def.trains ?? []), ...upgradesOf(def)]) if (!reach.has(made)) next.push(made)\n\t}\n\tif (reach.size) return reach\n\tfor (const def of registry.units.all()) if (may(def)) reach.add(def.id)\n\treturn reach\n}\n"],"mappings":";;;;AAqIA,IAAM,SAAS;AACf,IAAM,QAAQ;AACd,IAAM,WAAW;;AAGjB,IAAM,UAAU,QAA8B,IAAI,SAAS,UAAU,CAAC,CAAC,IAAI,SAAS,UAAU,EAAE,IAAI,aAAa,IAAI,QAAQ;;AAG7H,IAAM,SAAS,KAAkB,SAChC,SAAS,KAAA,MAAc,IAAI,YAAY,QAAS,MAAM,QAAQ,IAAI,OAAO,KAAK,IAAI,QAAQ,SAAS,IAAI;;AAGxG,IAAM,UAAU,KAAkB,SAAsC,IAAI,SAAS,KAAA,KAAa,IAAI,SAAS;;;;;;;;AAS/G,SAAgB,WAAW,UAA+B;CACzD,MAAM,QAAmB,CAAC;CAC1B,MAAM,MAAM,SAAS,MAAM,IAAI;CAC/B,MAAM,QAAQ,SAAS,YAAY,SAAS,UAAU,EAAE,EAAE;CAC1D,MAAM,SAAS,SACb,IAAI,aAAa,CAAC,EAAA,CAAG,MAAM,OAAO,SAAS,UAAU,IAAI,EAAE,KAAK,SAAS,QAAQ,EAAE,CAAC,CAAC,QAAQ,MAAM,WAAW,OAAO,SAAS,MAAM,CAAC;CACvI,MAAM,WAAW,SACf,IAAI,aAAa,CAAC,EAAA,CAAG,MAAM,OAAO,SAAS,UAAU,IAAI,EAAE,KAAK,SAAS,QAAQ,EAAE,CAAC,CAAC,QAAQ,MAAM,WAAW,OAAO,SAAS,QAAQ,CAAC;CAEzI,MAAM,UAAU,IAAI,QAAQ,QAAQ,IAAI,SAAS,UAAU,IAAI,aAAa,IAAI,QAAQ,MAAM;CAC9F,MAAM,gBAAgB,QAAqB,CAAC,CAAC,IAAI,QAAQ,MAAM,OAAO,QAAQ,MAAM,WAAW,OAAO,OAAO,EAAE,CAAC;CAGhH,MAAM,WAAW,SAChB,IAAI,QAAQ,QAAQ,IAAI,SAAS,cAAc,IAAI,WAAW,CAAC,IAAI,WAAW,OAAO,KAAK,IAAI,KAAK,aAAa,GAAG,CAAC;CAErH,MAAM,WAAW,IAAI,QAAQ,QAAQ,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI;CAC7D,MAAM,SAAS,QAAqB,UAAU,KAAK,QAAQ,CAAC,CAAC;CAE7D,MAAM,WAAW,SAAsD;EACtE,IAAI;EACJ,KAAK,MAAM,OAAO,UAAU,IAAI,IAAI,SAAS,SAAS,CAAC,QAAQ,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,OAAO;EACjG,OAAO;CACR;CAEA,KAAK,MAAM,OAAO,KAAK;EACtB,MAAM,QAAkB,CAAC;EACzB,MAAM,MAAgB,CAAC;EACvB,MAAM,OAAiB,CAAC;EACxB,MAAM,QAAQ,MAAc,WAAmB;GAC9C,MAAM,KAAK,IAAI;GACf,IAAI,KAAK,GAAG,KAAK,IAAI,QAAQ;EAC9B;EACA,IAAI,IAAI,SAAS,QAAQ;GACxB,IAAI,IAAI,aAAa,IAAI,QAAQ,QAAQ,KAAK,UAAU,oBAAoB;GAC5E,IAAI,IAAI,WAAW,KAAK,YAAY,SAAS;GAC7C,IAAI,IAAI,MAAM,KAAK,QAAQ,QAAQ;QAC9B,IAAI,OAAO,GAAG,GAAG,KAAK,WAAW,uBAAuB;GAC7D,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,QAAQ,IAAI,WAAW,UAAU,UAAU,KAAK,QAAQ,CAAC,CAAC,OAAO,GAAG,KAAK,UAAU,gCAAgC;GAC3I,IAAI,MAAM,GAAG,GAAG,KAAK,UAAU,2BAA2B;GAC1D,IAAI,IAAI,SAAS,MAAM,WAAW,OAAO,UAAU,OAAO,SAAS,OAAO,MAAM,GAC/E,KAAK,SAAS,qDAAqD;GACpE,IAAI,IAAI,QAAQ,KAAK,OAAO,OAAO;GACnC,IAAI,CAAC,IAAI,QAAQ,OAAO,GAAG,KAAK,QAAQ,IAAI,IAAI,MAAM,KAAK,KAAK,SAAS,6BAA6B;GACtG,IAAI,QAAQ,GAAG,GAAG,KAAK,YAAY,yCAAyC;EAC7E,OAAO,IAAI,IAAI,SAAS,YAAY;GACnC,IAAI,IAAI,YAAY,KAAA,KAAa,IAAI,YAAY,SAAS,MAAM,KAAK,KAAK,GACzE,KAAK,UAAU,wDAAwD;QACnE,IAAI,IAAI,WAAW,CAAC,IAAI,SAAS;IACrC,MAAM,QAAQ,QAAQ,IAAI,IAAI;IAC9B,IAAI,aAAa,GAAG,GAAG,KAAK,QAAQ,mCAAmC;SAClE,IAAI,MAAM,WAAW,GAAG,KAAK,QAAQ,uEAAuE;GAClH;GACA,IAAI,cAAc,GAAG,KAAK,CAAC,IAAI,QAAQ,QAAQ,KAAK,UAAU,oCAAoC;GAClG,IAAI,IAAI,QAAQ,MAAM,OAAO,SAAS,MAAM,IAAI,EAAE,KAAK,OAAO,SAAS,KAAK,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,IAAI,GAC1G,KAAK,YAAY,iBAAiB;GACnC,IAAI,IAAI,WAAW,IAAI,QAAQ,MAAM,OAAO,SAAS,MAAM,IAAI,EAAE,KAAK,SAAS,KAAK,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,SAAS,0BAA0B;GACvI,IAAI,IAAI,YAAY,QAAQ,KAAK,YAAY,YAAY;GAEzD,IAAI,IAAI,SAAS,UAAU,CAAC,IAAI,WAAW,OAAO,KAAK,SAAS,mCAAmC;GACnG,IAAI,IAAI,OAAO,UAAU,IAAI,OAAO,QAAQ,KAAK,QAAQ,gBAAgB;GACzE,IAAI,QAAQ,GAAG,GAAG,KAAK,YAAY,yCAAyC;EAC7E;EAEA,MAAM,UAAU,IAAI,WAAW,CAAC;EAChC,IAAI,QAAQ,MAAM,WAAW,OAAO,eAAe,GAAG,KAAK,KAAK,MAAM;EACtE,IAAI,QAAQ,MAAM,WAAW,CAAC,OAAO,eAAe,GAAG,KAAK,KAAK,KAAK;EACtE,IAAI,QAAQ,MAAM,WAAW,OAAO,SAAS,SAAS,KAAK,CAAC,GAAG,KAAK,KAAK,QAAQ;EACjF,MAAM,IAAI,MAAM;GAAE;GAAO;GAAM;EAAI;CACpC;CACA,OAAO;AACR;;;;;;;AAQA,IAAa,QAAb,MAAmB;CAMR;CACQ;CANlB,yBAA0B,IAAI,IAA2B;CACzD,wBAAyB,IAAI,IAA2B;CAExD,YAEC,OACA,UACC;EAFQ,KAAA,QAAA;EACQ,KAAA,WAAA;CACf;;CAGH,GAAG,MAAiC;EACnC,OAAO,KAAK,MAAM,KAAK,EAAE,SAAS;CACnC;;CAGA,IAAI,MAAc,MAAuB;EACxC,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC,SAAS,IAAI;CACnC;;CAGA,KAAK,MAAiC;EACrC,OAAO,KAAK,MAAM,KAAK,EAAE,QAAQ;CAClC;;CAGA,OAAO,MAAc,KAAsB;EAC1C,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,SAAS,GAAG;CACpC;;CAGA,MAAM,MAAsC;EAC3C,IAAI,QAAQ,KAAK,OAAO,IAAI,IAAI;EAChC,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,MAAO,QAAQ,KAAK,SAAS,MAAM,IAAI,CAAC,CAAC,QAAQ,QAAQ,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,CAAE;EAC7G,OAAO;CACR;;CAGA,OAAO,KAAqC;EAC3C,IAAI,QAAQ,KAAK,MAAM,IAAI,GAAG;EAC9B,IAAI,CAAC,OAAO,KAAK,MAAM,IAAI,KAAM,QAAQ,KAAK,SAAS,MAAM,IAAI,CAAC,CAAC,QAAQ,QAAQ,KAAK,OAAO,IAAI,IAAI,GAAG,CAAC,CAAE;EAC7G,OAAO;CACR;;CAGA,MAAM,MAAmC;EACxC,OAAO,KAAK,SAAS,MAAM,IAAI,IAAI,IAAI,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,KAAA;CACtE;;;;;CAMA,QAAQ,MAAsB;EAC7B,MAAM,QAAQ,KAAK,MAAM;EACzB,IAAI,CAAC,OAAO,OAAO;EACnB,IAAI,CAAC,MAAM,MAAM,QAAQ,OAAO;EAChC,OAAO,MAAM,KAAK,SAAS,MAAM,IAAI,KAAK,IAAI,IAAI,aAAa,MAAM,MAAM,KAAK,IAAI;CACrF;;CAGA,SAAmC;EAClC,MAAM,SAAmC,CAAC;EAC1C,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,KAAK,KAAK,GAAG,KAAK,MAAM,QAAQ,MAAM,OAAO,CAAC,OAAO,UAAU,CAAC,EAAA,CAAG,KAAK,IAAI;EACvH,OAAO;CACR;AACD;AAEA,IAAM,OAAyB,CAAC;;;;;;;;;AAUhC,SAAgB,UAAU,UAAoB,QAAqB,QAA6B;CAC/F,MAAM,QAAQ,SAAS,OAAO,UAAU,MAAM,IAAI,WAAW,QAAQ;CACrE,KAAK,MAAM,OAAO,SAAS,MAAM,IAAI,GAAG;EACvC,MAAM,QAAQ,IAAI;EAClB,IAAI,CAAC,OAAO;EACZ,MAAM,QAAS,MAAM,IAAI,QAAQ;GAAE,OAAO,CAAC;GAAG,MAAM,CAAC;EAAE;EACvD,IAAI,MAAM,SAAS,KAAA,GAAW;GAC7B,MAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,IAAI,CAAC,GAAG,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI;GACvE,OAAO,MAAM;EACd;EACA,IAAI,MAAM,MAAM,MAAM,OAAO,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC;CACzE;CACA,OAAO,IAAI,MAAM,OAAO,QAAQ;AACjC;;;;;;;;AASA,SAAgB,eAAe,UAAoB,QAAqB,OAAsC;CAC7G,MAAM,OAAO,IAAI,IAAI,KAAK;CAC1B,MAAM,OAAO,QAAqB,kBAAkB,KAAK;EAAE,MAAM,OAAO;EAAM,cAAc,OAAO;CAAa,GAAG,IAAI,EAAE;CACzH,MAAM,wBAAQ,IAAI,IAAY;CAC9B,MAAM,OAAO,CAAC,GAAG,IAAI;CACrB,OAAO,KAAK,QAAQ;EACnB,MAAM,KAAK,KAAK,IAAI;EACpB,IAAI,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS,MAAM,IAAI,EAAE,GAAG;EAC9C,MAAM,MAAM,SAAS,KAAK,EAAE;EAE5B,IAAI,CAAC,KAAK,IAAI,EAAE,KAAK,CAAC,IAAI,GAAG,GAAG;EAChC,MAAM,IAAI,EAAE;EACZ,KAAK,MAAM,QAAQ;GAAC,GAAI,IAAI,UAAU,CAAC;GAAI,GAAI,IAAI,UAAU,CAAC;GAAI,GAAG,WAAW,GAAG;EAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,GAAG,KAAK,KAAK,IAAI;CAC5H;CACA,IAAI,MAAM,MAAM,OAAO;CACvB,KAAK,MAAM,OAAO,SAAS,MAAM,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,MAAM,IAAI,IAAI,EAAE;CACtE,OAAO;AACR"}
|
package/dist/ai/rules.d.ts
CHANGED
|
@@ -9,7 +9,9 @@ import type { AiRole } from './roles';
|
|
|
9
9
|
* @beta
|
|
10
10
|
*/
|
|
11
11
|
export interface AiRange {
|
|
12
|
+
/** The lowest it may be; no lower bound when left out */
|
|
12
13
|
min?: number;
|
|
14
|
+
/** The highest it may be; no upper bound when left out */
|
|
13
15
|
max?: number;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
@@ -20,7 +22,7 @@ export interface AiRange {
|
|
|
20
22
|
export type AiWhose = 'mine' | 'enemy' | 'ally';
|
|
21
23
|
/**
|
|
22
24
|
* A condition as plain data: what a map's file, a mission's JSON or the editor holds. Each form is one question; the
|
|
23
|
-
* table in `docs/ai.md` says what each asks
|
|
25
|
+
* table in `docs/ai/scripting.md` says what each asks
|
|
24
26
|
*
|
|
25
27
|
* @beta
|
|
26
28
|
*/
|
|
@@ -125,7 +127,7 @@ export type AiConditionData =
|
|
|
125
127
|
status: ObjectiveStatus | ObjectiveStatus[];
|
|
126
128
|
};
|
|
127
129
|
}
|
|
128
|
-
/** A value of the game's report to this player (`
|
|
130
|
+
/** A value of the game's report to this player (`Rules.report`), by its path (`'waves.next'`): equal to, or within */
|
|
129
131
|
| {
|
|
130
132
|
report: {
|
|
131
133
|
path: string;
|
|
@@ -187,7 +189,9 @@ export declare function evaluate(condition: AiCondition, ai: Brain): boolean;
|
|
|
187
189
|
* @beta
|
|
188
190
|
*/
|
|
189
191
|
export interface AiActionData {
|
|
192
|
+
/** The word the brain tells itself, which the `words()` module or a rule of its own answers */
|
|
190
193
|
say: string;
|
|
194
|
+
/** What goes with the word, for whoever answers it; nothing when left out */
|
|
191
195
|
data?: unknown;
|
|
192
196
|
}
|
|
193
197
|
/**
|
|
@@ -264,7 +268,9 @@ export declare const rules: (list: AiRule[], options?: {
|
|
|
264
268
|
* @beta
|
|
265
269
|
*/
|
|
266
270
|
export interface WordData {
|
|
271
|
+
/** Where: a point, or the name an entity or region was given by the map or the rules */
|
|
267
272
|
at?: Vec2 | string;
|
|
273
|
+
/** For how many seconds the army is the word's rather than the goals' */
|
|
268
274
|
seconds?: number;
|
|
269
275
|
}
|
|
270
276
|
/**
|