@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
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import {
|
|
1
|
+
import "./map/types.js";
|
|
2
|
+
import { createWorldFromMap } from "./game.js";
|
|
3
3
|
//#region src/simulate.ts
|
|
4
4
|
/** A simulation, as a module that a worker imports gives it: as it is written, for its type *
|
|
5
5
|
* @beta
|
|
6
6
|
*/
|
|
7
|
-
var defineSimulation = (simulation) => simulation;
|
|
8
7
|
/** Plays one game of a simulation from a seed, in this thread *
|
|
9
8
|
* @beta
|
|
10
9
|
*/
|
|
11
10
|
async function playGame(simulation, seed) {
|
|
12
11
|
const began = performance.now();
|
|
13
|
-
const { game, map } = simulation;
|
|
12
|
+
const { rules: game, map } = simulation;
|
|
14
13
|
const world = await createWorldFromMap({
|
|
15
14
|
map: structuredClone(map),
|
|
16
|
-
game,
|
|
15
|
+
rules: game,
|
|
17
16
|
seed,
|
|
18
17
|
onError: "end"
|
|
19
18
|
});
|
|
20
19
|
try {
|
|
21
20
|
const starts = map.players.filter((player) => player.start && player.id !== 90);
|
|
22
21
|
const computers = simulation.computers ?? starts.map((player) => player.id);
|
|
23
|
-
simulation.
|
|
22
|
+
simulation.onStart?.(world);
|
|
24
23
|
for (const player of computers) {
|
|
25
24
|
const enemyBases = starts.filter((other) => other.id !== player && world.areEnemies(player, other.id)).map((other) => other.start);
|
|
26
25
|
const named = simulation.brains?.[player];
|
|
27
26
|
const brain = typeof named === "string" ? world.computers.brain(named) : named;
|
|
28
|
-
if (typeof named === "string" && !brain) throw new Error(`No brain is called "${named}": list it in
|
|
27
|
+
if (typeof named === "string" && !brain) throw new Error(`No brain is called "${named}": list it in Rules.brains, or give the brain itself`);
|
|
29
28
|
const difficulty = simulation.difficulties?.[player];
|
|
30
29
|
const options = {
|
|
31
30
|
enemyBases,
|
|
@@ -112,10 +111,10 @@ function winRates(games) {
|
|
|
112
111
|
/**
|
|
113
112
|
* Plays games of a simulation, one from each seed, and gives what each ended in, in the order of the seeds. Given as
|
|
114
113
|
* it is, they are played in this thread. Given as the address of a file (a module whose `default`, or `simulation`, is
|
|
115
|
-
* one: `
|
|
114
|
+
* one: a `Simulation`), each worker thread imports it and plays its share: in Node, from the built packages (a
|
|
116
115
|
* worker loads JavaScript, not the TypeScript of this repository)
|
|
117
116
|
*
|
|
118
|
-
* @
|
|
117
|
+
* @public
|
|
119
118
|
*/
|
|
120
119
|
async function simulate(simulation, options) {
|
|
121
120
|
if (typeof simulation !== "string" && !(simulation instanceof URL)) {
|
|
@@ -162,6 +161,6 @@ async function simulate(simulation, options) {
|
|
|
162
161
|
return options.seeds.map((seed) => results.get(seed));
|
|
163
162
|
}
|
|
164
163
|
//#endregion
|
|
165
|
-
export {
|
|
164
|
+
export { playGame, simulate, winRates };
|
|
166
165
|
|
|
167
|
-
//# sourceMappingURL=simulate
|
|
166
|
+
//# sourceMappingURL=simulate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulate.js","names":[],"sources":["../src/simulate.ts"],"sourcesContent":["import type { AiOptions } from './ai/options'\nimport type { AiStats } from './ai/report'\nimport type { BrainDef } from './ai/brain'\nimport type { PlayerId } from './entity'\nimport { createWorldFromMap, type Rules } from './game'\nimport { type GameMap, MAP_CREEPS } from './map'\nimport type { World } from './world'\n\n/*\n * Many games at once, for balance (S43): games of a game played at full speed by the computer, from seeds, each\n * ending in plain data (who won, how long it took, what the game asked to count). The same seed gives the same game.\n * In this thread (`simulate(simulation, …)`), or in worker threads, each of which imports the game itself from a file\n * (`simulate(url, { workers })`): a game's rules are functions, which cannot be sent to another thread.\n */\n\n/**\n * What a value counted at the end of a game may be: plain data, which comes back from a worker as it went\n *\n * @beta\n */\nexport type Counted = number | string | boolean | null\n\n/**\n * A game to play many times (`simulate`): the rules, the map, who the computer plays and how, and what to count\n *\n * @public\n */\nexport interface Simulation {\n\t/** The game module's rules each simulated game is played with */\n\trules: Rules\n\t/** The map each simulated game is made from */\n\tmap: GameMap\n\t/**\n\t * The players the computer plays: every player of the map with a start, the creeps apart, when left out. One left\n\t * out is the game's own (`start`) to move, or stands\n\t */\n\tcomputers?: PlayerId[]\n\t/**\n\t * The brain each player is played by, or its id (one the game lists in `Rules.brains`, or the engine's\n\t * `core.melee`): two brains against each other, for a balance run. A player not named here is played by the first\n\t * brain the game lists\n\t */\n\tbrains?: Record<number, BrainDef | string>\n\t/**\n\t * How hard each player's computer plays, by name (`'hard'`): under what `ai` gives. The seat's own when left out\n\t */\n\tdifficulties?: Record<number, string>\n\t/** How the computer plays a player, over what it is given (`enemyBases`: where the others start) */\n\tai?: (player: PlayerId, world: World) => Partial<AiOptions>\n\t/** What the game does once a world is made, before the first tick: units of its own, a rule turned on */\n\tonStart?: (world: World) => void\n\t/** Seconds of the game at most: twenty minutes when left out */\n\tseconds?: number\n\t/** Whether the game is over before that: once there is a winner, when left out */\n\tuntil?: (world: World) => boolean\n\t/** What to count at the end of each game, by name: units alive, gold gathered, the hour */\n\tmeasure?: (world: World) => Record<string, Counted>\n}\n\n/**\n * How a computer player played one game, beside who won (`SimulatedGame.computers`): the numbers that say whether a\n * brain plays well, not only whether it won (`AiStats`, the brain's own counts, by the minute where it says so)\n *\n * @beta\n */\nexport interface ComputerMeasures {\n\t/** The brain that played the seat, by id: none for the first the game lists, seated by none named */\n\tbrain?: string\n\t/** The team the seat played for */\n\tteam: number\n\t/** Whether its team won: false for a draw too */\n\twon: boolean\n\t/** Commands sent a minute of the game */\n\tcommandsAMinute: number\n\t/** Seconds its fighters stood idle, summed over the fighters */\n\tidleArmySeconds: number\n\t/** Orders sent to a unit again for the same thing within a few seconds */\n\tchurn: number\n\t/** Seconds its building waited on money */\n\tblockedOnMoney: number\n\t/** Commands the game refused */\n\trefused: number\n\t/** Commands held back past what a think may send */\n\theld: number\n}\n\n/**\n * How one game ended\n *\n * @beta\n */\nexport interface SimulatedGame {\n\t/** The seed the game was played with */\n\tseed: number\n\t/** The winning team, or null for none in the time given */\n\twinner: number | null\n\t/** Seconds of the game it lasted, and ticks */\n\tseconds: number\n\t/** How many ticks the game lasted */\n\tticks: number\n\t/** Why it stopped on an error of its rules, where it did (`World.failure`) */\n\tfailed?: string\n\t/** What `measure` counted */\n\tmeasured: Record<string, Counted>\n\t/** How each computer player played, by player: commands a minute, idle army seconds, churn, seconds blocked on money, commands refused */\n\tcomputers: Record<string, ComputerMeasures>\n\t/** Milliseconds it took to play here */\n\ttook: number\n}\n\n/** A simulation, as a module that a worker imports gives it: as it is written, for its type *\n * @beta\n */\n\n/** Plays one game of a simulation from a seed, in this thread *\n * @beta\n */\nexport async function playGame(simulation: Simulation, seed: number): Promise<SimulatedGame> {\n\tconst began = performance.now()\n\tconst { rules: game, map } = simulation\n\tconst world = await createWorldFromMap({ map: structuredClone(map), rules: game, seed, onError: 'end' })\n\ttry {\n\t\tconst starts = map.players.filter((player) => player.start && player.id !== MAP_CREEPS)\n\t\tconst computers = simulation.computers ?? starts.map((player) => player.id)\n\t\tsimulation.onStart?.(world)\n\t\tfor (const player of computers) {\n\t\t\tconst enemyBases = starts.filter((other) => other.id !== player && world.areEnemies(player, other.id)).map((other) => other.start!)\n\t\t\tconst named = simulation.brains?.[player]\n\t\t\tconst brain = typeof named === 'string' ? world.computers.brain(named) : named\n\t\t\tif (typeof named === 'string' && !brain)\n\t\t\t\tthrow new Error(`No brain is called \"${named}\": list it in Rules.brains, or give the brain itself`)\n\t\t\tconst difficulty = simulation.difficulties?.[player]\n\t\t\tconst options: AiOptions = { enemyBases, ...(difficulty !== undefined && { difficulty }), ...simulation.ai?.(player, world) }\n\t\t\tworld.computers.seat(player, { ...options, brain })\n\t\t}\n\t\tconst until = simulation.until ?? ((done: World) => done.winner !== null)\n\t\tconst ticks = Math.ceil((simulation.seconds ?? 1200) * world.tickRate)\n\t\tlet tick = 0\n\t\twhile (tick < ticks && !world.failure && !until(world)) {\n\t\t\tworld.step()\n\t\t\ttick++\n\t\t}\n\t\tconst seconds = tick / world.tickRate\n\t\tconst measures: Record<string, ComputerMeasures> = {}\n\t\tfor (const player of computers) {\n\t\t\tconst computer = world.computers.get(player)?.computer as { stats?: AiStats; def?: { id: string } } | undefined\n\t\t\tconst stats = computer?.stats\n\t\t\tif (!stats) continue\n\t\t\tconst team = world.players.get(player)?.team ?? player\n\t\t\tmeasures[player] = {\n\t\t\t\t...(computer?.def?.id !== undefined && { brain: computer.def.id }),\n\t\t\t\tteam,\n\t\t\t\twon: world.winner !== null && world.winner === team,\n\t\t\t\tcommandsAMinute: seconds > 0 ? (stats.commands / seconds) * 60 : 0,\n\t\t\t\tidleArmySeconds: stats.idleArmySeconds,\n\t\t\t\tchurn: stats.churn,\n\t\t\t\tblockedOnMoney: stats.blockedOnMoney,\n\t\t\t\trefused: stats.refused,\n\t\t\t\theld: stats.held\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tseed,\n\t\t\twinner: world.winner,\n\t\t\tseconds,\n\t\t\tticks: tick,\n\t\t\t...(world.failure && { failed: world.failure.message }),\n\t\t\tmeasured: simulation.measure?.(world) ?? {},\n\t\t\tcomputers: measures,\n\t\t\ttook: performance.now() - began\n\t\t}\n\t} finally {\n\t\tworld.dispose()\n\t}\n}\n\n/**\n * How a brain did over some games (`winRates`): by seat, so a brain that played both sides of a game counts twice\n *\n * @beta\n */\nexport interface BrainResults {\n\t/** Seats it played */\n\tgames: number\n\t/** Seats whose team won */\n\twins: number\n\t/** Seats whose team another team beat */\n\tlosses: number\n\t/** Seats of games with no winner in the time given */\n\tdraws: number\n\t/** Wins over seats played */\n\trate: number\n\t/** Wins over games decided either way: draws left out */\n\tdecided: number\n}\n\n/**\n * The win rate of each brain over games of `simulate`, by brain id (`ComputerMeasures.brain`): what a balance run of two\n * brains reads. A seat that named no brain is left out\n *\n * const games = await simulate({ ...duel, brains: { 1: meleeBrain, 2: myBrain } }, { seeds })\n * winRates(games) // { 'core.melee': { rate: 0.4, … }, 'mygame.brain': { rate: 0.55, … } }\n *\n * @beta\n */\nexport function winRates(games: readonly SimulatedGame[]): Record<string, BrainResults> {\n\tconst results: Record<string, BrainResults> = {}\n\tfor (const game of games)\n\t\tfor (const measures of Object.values(game.computers)) {\n\t\t\tif (measures.brain === undefined) continue\n\t\t\tconst result = (results[measures.brain] ??= { games: 0, wins: 0, losses: 0, draws: 0, rate: 0, decided: 0 })\n\t\t\tresult.games++\n\t\t\tif (measures.won) result.wins++\n\t\t\telse if (game.winner === null) result.draws++\n\t\t\telse result.losses++\n\t\t}\n\tfor (const result of Object.values(results)) {\n\t\tresult.rate = result.games ? result.wins / result.games : 0\n\t\tresult.decided = result.wins + result.losses ? result.wins / (result.wins + result.losses) : 0\n\t}\n\treturn results\n}\n\n/**\n * How `simulate` plays its games\n *\n * @beta\n */\nexport interface SimulateOptions {\n\t/** The seeds to play from, a game each */\n\tseeds: number[]\n\t/**\n\t * Worker threads to play them in at once, where the simulation is given as a file: as many as the machine has\n\t * cores less one, when left out. In this thread, one after the other, for a simulation given as it is\n\t */\n\tworkers?: number\n\t/** Told of each game as it ends, in the order they end */\n\tonGame?: (game: SimulatedGame) => void\n}\n\n/**\n * Plays games of a simulation, one from each seed, and gives what each ended in, in the order of the seeds. Given as\n * it is, they are played in this thread. Given as the address of a file (a module whose `default`, or `simulation`, is\n * one: a `Simulation`), each worker thread imports it and plays its share: in Node, from the built packages (a\n * worker loads JavaScript, not the TypeScript of this repository)\n *\n * @public\n */\nexport async function simulate(simulation: Simulation | string | URL, options: SimulateOptions): Promise<SimulatedGame[]> {\n\tif (typeof simulation !== 'string' && !(simulation instanceof URL)) {\n\t\tconst games: SimulatedGame[] = []\n\t\tfor (const seed of options.seeds) {\n\t\t\tconst game = await playGame(simulation, seed)\n\t\t\toptions.onGame?.(game)\n\t\t\tgames.push(game)\n\t\t}\n\t\treturn games\n\t}\n\tconst { Worker } = await import('node:worker_threads')\n\tconst { availableParallelism } = await import('node:os')\n\tconst module = String(simulation)\n\tconst count = Math.max(1, Math.min(options.workers ?? availableParallelism() - 1, options.seeds.length))\n\t// the worker's file sits next to this one in the build: named so, a bundler leaves the address alone\n\tconst file = 'simulate-worker.js'\n\tconst script = new URL(file, import.meta.url)\n\tconst results = new Map<number, SimulatedGame>()\n\tconst queue = [...options.seeds]\n\tawait Promise.all(\n\t\tArray.from(\n\t\t\t{ length: count },\n\t\t\t() =>\n\t\t\t\tnew Promise<void>((resolve, reject) => {\n\t\t\t\t\tconst worker = new Worker(script)\n\t\t\t\t\tconst next = () => {\n\t\t\t\t\t\tconst seed = queue.shift()\n\t\t\t\t\t\tif (seed === undefined) {\n\t\t\t\t\t\t\tvoid worker.terminate()\n\t\t\t\t\t\t\treturn resolve()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tworker.postMessage({ module, seed })\n\t\t\t\t\t}\n\t\t\t\t\tworker.on('message', (message: { game?: SimulatedGame; error?: string }) => {\n\t\t\t\t\t\tif (message.error !== undefined) {\n\t\t\t\t\t\t\tvoid worker.terminate()\n\t\t\t\t\t\t\treturn reject(new Error(message.error))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresults.set(message.game!.seed, message.game!)\n\t\t\t\t\t\toptions.onGame?.(message.game!)\n\t\t\t\t\t\tnext()\n\t\t\t\t\t})\n\t\t\t\t\tworker.on('error', reject)\n\t\t\t\t\tnext()\n\t\t\t\t})\n\t\t)\n\t)\n\treturn options.seeds.map((seed) => results.get(seed)!)\n}\n"],"mappings":"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"}
|
package/dist/smart.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { constructionOf } from "./defs.js";
|
|
2
|
+
import { constructionSite } from "./systems/construction.js";
|
|
3
|
+
import { deposit, moving } from "./entity.js";
|
|
4
|
+
import { canAttack } from "./systems/combat.js";
|
|
5
|
+
import { canHarvest, harvesterOf } from "./orders/harvest.js";
|
|
6
|
+
import { canRepair } from "./orders/build.js";
|
|
7
|
+
import { canBoard } from "./transport.js";
|
|
8
|
+
//#region src/smart.ts
|
|
9
|
+
/**
|
|
10
|
+
* The right-click: picks the order a unit should get for whatever was clicked.
|
|
11
|
+
* Returns undefined when there is nothing sensible for this unit to do.
|
|
12
|
+
*/
|
|
13
|
+
function smartOrder(world, entity, point, target) {
|
|
14
|
+
if (!entity.get(moving)) return void 0;
|
|
15
|
+
if (target && target !== entity) {
|
|
16
|
+
if (canAttack(world, entity, target)) return {
|
|
17
|
+
type: "attack",
|
|
18
|
+
target: target.id
|
|
19
|
+
};
|
|
20
|
+
if (target.def.fellable && entity.def.attacks?.some((attack) => attack.fells && attack.ground)) return {
|
|
21
|
+
type: "attackGround",
|
|
22
|
+
target: target.id
|
|
23
|
+
};
|
|
24
|
+
const harvester = harvesterOf(entity);
|
|
25
|
+
if (harvester) {
|
|
26
|
+
if (target.get(deposit)) return {
|
|
27
|
+
type: "harvest",
|
|
28
|
+
target: target.id
|
|
29
|
+
};
|
|
30
|
+
const under = world.get(target.on);
|
|
31
|
+
if (under?.get(deposit) && canHarvest(world, entity, under)) return {
|
|
32
|
+
type: "harvest",
|
|
33
|
+
target: under.id
|
|
34
|
+
};
|
|
35
|
+
if (target.def.dropOff && target.owner === entity.owner && target.operational && harvester.carrying > 0) return { type: "return" };
|
|
36
|
+
}
|
|
37
|
+
if (entity.def.builds?.length && target.has(constructionSite) && constructionOf(target.def) === "builder" && world.areAllies(entity.owner, target.owner)) return {
|
|
38
|
+
type: "construct",
|
|
39
|
+
target: target.id
|
|
40
|
+
};
|
|
41
|
+
if (entity.def.builds?.length && canRepair(world, entity.owner, target)) return {
|
|
42
|
+
type: "repair",
|
|
43
|
+
target: target.id
|
|
44
|
+
};
|
|
45
|
+
if (world.areEnemies(entity.owner, target.owner)) return {
|
|
46
|
+
type: "move",
|
|
47
|
+
point: {
|
|
48
|
+
x: target.pos.x,
|
|
49
|
+
z: target.pos.z
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
if (target.def.transport && canBoard(world, entity, target)) return {
|
|
53
|
+
type: "board",
|
|
54
|
+
target: target.id
|
|
55
|
+
};
|
|
56
|
+
if (entity.def.transport && canBoard(world, target, entity)) return {
|
|
57
|
+
type: "load",
|
|
58
|
+
target: target.id
|
|
59
|
+
};
|
|
60
|
+
if (target.get(moving) && world.areAllies(entity.owner, target.owner)) return {
|
|
61
|
+
type: "follow",
|
|
62
|
+
target: target.id
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
type: "move",
|
|
66
|
+
target: target.id
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
type: "move",
|
|
71
|
+
point
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { smartOrder };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=smart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart.js","names":[],"sources":["../src/smart.ts"],"sourcesContent":["import { constructionOf } from './defs'\nimport { constructionSite } from './systems/construction'\nimport type { Entity } from './entity'\nimport type { Vec2 } from './math'\nimport { canRepair } from './orders/build'\nimport { canHarvest, harvesterOf } from './orders/harvest'\nimport type { OrderInit } from './registry'\nimport { canAttack } from './systems/combat'\nimport { canBoard } from './transport'\nimport type { World } from './world'\nimport { moving, deposit } from './entity'\n\n/**\n * The right-click: picks the order a unit should get for whatever was clicked.\n * Returns undefined when there is nothing sensible for this unit to do.\n */\nexport function smartOrder(world: World, entity: Entity, point: Vec2, target?: Entity): OrderInit | undefined {\n\tif (!entity.get(moving)) return undefined\n\tif (target && target !== entity) {\n\t\tif (canAttack(world, entity, target)) return { type: 'attack', target: target.id }\n\t\t// trees are in the way of those who can bring them down\n\t\tif (target.def.fellable && entity.def.attacks?.some((attack) => attack.fells && attack.ground)) return { type: 'attackGround', target: target.id }\n\t\tconst harvester = harvesterOf(entity)\n\t\tif (harvester) {\n\t\t\tif (target.get(deposit)) return { type: 'harvest', target: target.id }\n\t\t\t// what stands on a resource (a cursed mine) is clicked for it: what is drawn over the mine is what is clicked\n\t\t\tconst under = world.get(target.on)\n\t\t\tif (under?.get(deposit) && canHarvest(world, entity, under)) return { type: 'harvest', target: under.id }\n\t\t\tif (target.def.dropOff && target.owner === entity.owner && target.operational && harvester.carrying > 0) return { type: 'return' }\n\t\t}\n\t\tif (\n\t\t\tentity.def.builds?.length &&\n\t\t\ttarget.has(constructionSite) &&\n\t\t\tconstructionOf(target.def) === 'builder' &&\n\t\t\tworld.areAllies(entity.owner, target.owner)\n\t\t) {\n\t\t\treturn { type: 'construct', target: target.id }\n\t\t}\n\t\tif (entity.def.builds?.length && canRepair(world, entity.owner, target)) return { type: 'repair', target: target.id }\n\t\tif (world.areEnemies(entity.owner, target.owner)) return { type: 'move', point: { x: target.pos.x, z: target.pos.z } }\n\t\t// a transport of their side with room: in they get\n\t\tif (target.def.transport && canBoard(world, entity, target)) return { type: 'board', target: target.id }\n\t\t// a transport clicking one of its side's that can get in: it goes and takes it in\n\t\tif (entity.def.transport && canBoard(world, target, entity)) return { type: 'load', target: target.id }\n\t\t// friends that walk are stayed with, everything else is walked up to\n\t\tif (target.get(moving) && world.areAllies(entity.owner, target.owner)) return { type: 'follow', target: target.id }\n\t\treturn { type: 'move', target: target.id }\n\t}\n\treturn { type: 'move', point }\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,SAAgB,WAAW,OAAc,QAAgB,OAAa,QAAwC;CAC7G,IAAI,CAAC,OAAO,IAAI,MAAM,GAAG,OAAO,KAAA;CAChC,IAAI,UAAU,WAAW,QAAQ;EAChC,IAAI,UAAU,OAAO,QAAQ,MAAM,GAAG,OAAO;GAAE,MAAM;GAAU,QAAQ,OAAO;EAAG;EAEjF,IAAI,OAAO,IAAI,YAAY,OAAO,IAAI,SAAS,MAAM,WAAW,OAAO,SAAS,OAAO,MAAM,GAAG,OAAO;GAAE,MAAM;GAAgB,QAAQ,OAAO;EAAG;EACjJ,MAAM,YAAY,YAAY,MAAM;EACpC,IAAI,WAAW;GACd,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO;IAAE,MAAM;IAAW,QAAQ,OAAO;GAAG;GAErE,MAAM,QAAQ,MAAM,IAAI,OAAO,EAAE;GACjC,IAAI,OAAO,IAAI,OAAO,KAAK,WAAW,OAAO,QAAQ,KAAK,GAAG,OAAO;IAAE,MAAM;IAAW,QAAQ,MAAM;GAAG;GACxG,IAAI,OAAO,IAAI,WAAW,OAAO,UAAU,OAAO,SAAS,OAAO,eAAe,UAAU,WAAW,GAAG,OAAO,EAAE,MAAM,SAAS;EAClI;EACA,IACC,OAAO,IAAI,QAAQ,UACnB,OAAO,IAAI,gBAAgB,KAC3B,eAAe,OAAO,GAAG,MAAM,aAC/B,MAAM,UAAU,OAAO,OAAO,OAAO,KAAK,GAE1C,OAAO;GAAE,MAAM;GAAa,QAAQ,OAAO;EAAG;EAE/C,IAAI,OAAO,IAAI,QAAQ,UAAU,UAAU,OAAO,OAAO,OAAO,MAAM,GAAG,OAAO;GAAE,MAAM;GAAU,QAAQ,OAAO;EAAG;EACpH,IAAI,MAAM,WAAW,OAAO,OAAO,OAAO,KAAK,GAAG,OAAO;GAAE,MAAM;GAAQ,OAAO;IAAE,GAAG,OAAO,IAAI;IAAG,GAAG,OAAO,IAAI;GAAE;EAAE;EAErH,IAAI,OAAO,IAAI,aAAa,SAAS,OAAO,QAAQ,MAAM,GAAG,OAAO;GAAE,MAAM;GAAS,QAAQ,OAAO;EAAG;EAEvG,IAAI,OAAO,IAAI,aAAa,SAAS,OAAO,QAAQ,MAAM,GAAG,OAAO;GAAE,MAAM;GAAQ,QAAQ,OAAO;EAAG;EAEtG,IAAI,OAAO,IAAI,MAAM,KAAK,MAAM,UAAU,OAAO,OAAO,OAAO,KAAK,GAAG,OAAO;GAAE,MAAM;GAAU,QAAQ,OAAO;EAAG;EAClH,OAAO;GAAE,MAAM;GAAQ,QAAQ,OAAO;EAAG;CAC1C;CACA,OAAO;EAAE,MAAM;EAAQ;CAAM;AAC9B"}
|
package/dist/spatial.d.ts
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
import type { Entity, PlayerId } from './entity';
|
|
2
|
-
/**
|
|
3
|
-
* Uniform grid for "what is near this point" queries. The map is cut into square cells and every entity is
|
|
4
|
-
* filed under the cells it is in, so a query only looks at the few cells around the point instead of at every
|
|
5
|
-
* entity in the world.
|
|
6
|
-
*
|
|
7
|
-
* There are two layers:
|
|
8
|
-
* - Units move, so they are filed again from scratch every tick (`rebuild`), which is simpler and cheaper than
|
|
9
|
-
* following every unit from cell to cell. A unit is filed by its center only, so queries look a little
|
|
10
|
-
* further than asked, by the radius of the biggest unit, not to miss one whose edge is in range.
|
|
11
|
-
* - Structures (buildings, trees, mines) never move, so they are filed once when they appear and taken out when
|
|
12
|
-
* they go (`insertStatic`, `removeStatic`). They are filed under every cell their footprint covers, so a query
|
|
13
|
-
* finds them by any part of them without looking further than asked. That matters: padding queries by the
|
|
14
|
-
* size of the biggest building would make every query near a forest go through far more trees.
|
|
15
|
-
*/
|
|
16
2
|
export declare class SpatialIndex {
|
|
17
3
|
private readonly cellSize;
|
|
18
4
|
private readonly cols;
|
|
@@ -25,16 +11,38 @@ export declare class SpatialIndex {
|
|
|
25
11
|
* since (`ownerChanged`), until the next filing
|
|
26
12
|
*/
|
|
27
13
|
private readonly soleOwner;
|
|
14
|
+
/** By cell, how many units were filed in it so far this filing (`rebuild`) */
|
|
15
|
+
private readonly filed;
|
|
28
16
|
private ownersMoved;
|
|
29
17
|
/** Radius of the biggest unit filed this tick */
|
|
30
18
|
private maxRadius;
|
|
19
|
+
/** Radius of the biggest unit filed this tick that is not big (`BIG_RADIUS`) */
|
|
20
|
+
private maxSmallRadius;
|
|
21
|
+
/**
|
|
22
|
+
* The big units filed this tick (they are in `cells` as well), in the order a query finds them: by cell, then
|
|
23
|
+
* as filed. Each one's cell, column and row alongside. Only up to `MAX_BIG`: `bigCount` counts them all
|
|
24
|
+
*/
|
|
25
|
+
private readonly big;
|
|
26
|
+
private readonly bigAt;
|
|
27
|
+
private readonly bigCol;
|
|
28
|
+
private readonly bigRow;
|
|
29
|
+
private bigCount;
|
|
30
|
+
/** In a query, the first big unit in the list not yet gone by */
|
|
31
|
+
private bigNext;
|
|
31
32
|
/** Counts queries. A structure that covers several cells is marked with it when found, so it is only found once */
|
|
32
33
|
private stamp;
|
|
33
34
|
constructor(width: number, depth: number, cellSize?: number);
|
|
34
35
|
private col;
|
|
35
36
|
private row;
|
|
36
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* Files every unit again. Called once per tick, before the systems run. Structures in `entities` are passed over.
|
|
39
|
+
*
|
|
40
|
+
* Each cell is written over from its start and cut to what it got at the end, not emptied first: a list emptied
|
|
41
|
+
* (`length = 0`) lets go of its room, and filling it again would make it all anew, every cell, every tick
|
|
42
|
+
*/
|
|
37
43
|
rebuild(entities: Iterable<Entity>): void;
|
|
44
|
+
/** Into the list of big units, after every one in a cell before its own or in the same: as it is in the cells */
|
|
45
|
+
private fileBig;
|
|
38
46
|
/** A unit filed this tick has another owner now: no cell's one owner is gone by until the next filing */
|
|
39
47
|
ownerChanged(): void;
|
|
40
48
|
/** Files a structure under every cell it covers, for as long as it stands */
|
|
@@ -45,7 +53,8 @@ export declare class SpatialIndex {
|
|
|
45
53
|
* Entities that could be within `radius` of the point: every structure that has a part in the square around it,
|
|
46
54
|
* and every unit whose center is close enough for its edge to be. Callers do the exact distance check.
|
|
47
55
|
*
|
|
48
|
-
* The answer is written into `out`, which callers keep around and pass again so that nothing is allocated
|
|
56
|
+
* The answer is written into `out`, which callers keep around and pass again so that nothing is allocated: over what
|
|
57
|
+
* it held, then cut to the answer (emptied first, a list lets go of its room and grows it again). While going
|
|
49
58
|
* through the answer, a caller that does something which can lead to another query with the same `out` (dealing damage
|
|
50
59
|
* can set off effects that look around) has to go through a copy instead: the other query would overwrite it.
|
|
51
60
|
*
|
|
@@ -53,6 +62,13 @@ export declare class SpatialIndex {
|
|
|
53
62
|
* one such owner alone is left out. What is left is what the full answer had, in the same order, less some of theirs
|
|
54
63
|
*/
|
|
55
64
|
query(x: number, z: number, radius: number, out?: Entity[], skip?: (owner: PlayerId) => boolean): Entity[];
|
|
65
|
+
/**
|
|
66
|
+
* Adds to a query's answer, from `bigNext` on, the big units in cells before `before` that the cells it goes
|
|
67
|
+
* through (`minX`..`maxZ`) leave out but that reach within `radius` of the point by their own radius: where they would
|
|
68
|
+
* have been in an answer that went through more cells. Those in a cell it goes through are found there. Returns how
|
|
69
|
+
* many the answer has now
|
|
70
|
+
*/
|
|
71
|
+
private addBigs;
|
|
56
72
|
/**
|
|
57
73
|
* Only the structures that have a part in the square around the point: buildings, trees, mines, every kind but a
|
|
58
74
|
* unit. For who looks for those alone, among crowds of units that would otherwise all be gone through. Into `out`,
|
package/dist/spatial.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
//#region src/spatial.ts
|
|
2
|
+
/**
|
|
3
|
+
* Uniform grid for "what is near this point" queries. The map is cut into square cells and every entity is
|
|
4
|
+
* filed under the cells it is in, so a query only looks at the few cells around the point instead of at every
|
|
5
|
+
* entity in the world.
|
|
6
|
+
*
|
|
7
|
+
* There are two layers:
|
|
8
|
+
* - Units move, so they are filed again from scratch every tick (`rebuild`), which is simpler and cheaper than
|
|
9
|
+
* following every unit from cell to cell. A unit is filed by its center only, so queries look a little
|
|
10
|
+
* further than asked, by the radius of the biggest ordinary unit, not to miss one whose edge is in range. The
|
|
11
|
+
* few units bigger than that (`BIG_RADIUS`: a boss, a siege engine) are kept in a short list besides, which
|
|
12
|
+
* every query goes through, each looked for as far as its own radius: one of them on the map does not make every
|
|
13
|
+
* query near a crowd of small ones go through more cells. Above `MAX_BIG` of them, it is not worth it, and
|
|
14
|
+
* queries look as far as the biggest unit again. Either way an answer is in the same order: by cell, and by
|
|
15
|
+
* filing within a cell.
|
|
16
|
+
* - Structures (buildings, trees, mines) never move, so they are filed once when they appear and taken out when
|
|
17
|
+
* they go (`insertStatic`, `removeStatic`). They are filed under every cell their footprint covers, so a query
|
|
18
|
+
* finds them by any part of them without looking further than asked. That matters: padding queries by the
|
|
19
|
+
* size of the biggest building would make every query near a forest go through far more trees.
|
|
20
|
+
*/
|
|
21
|
+
/** Units with a bigger radius than this are big: kept besides in a short list, not making every query look further */
|
|
22
|
+
var BIG_RADIUS = 1;
|
|
23
|
+
/** Above so many big units filed in a tick, queries look as far as the biggest one instead, as though there were none */
|
|
24
|
+
var MAX_BIG = 32;
|
|
25
|
+
var SpatialIndex = class {
|
|
26
|
+
cellSize;
|
|
27
|
+
cols;
|
|
28
|
+
rows;
|
|
29
|
+
cells;
|
|
30
|
+
staticCells;
|
|
31
|
+
/**
|
|
32
|
+
* By cell, the one owner of every unit filed in it this tick, or -1 for none or more than one: what a search that
|
|
33
|
+
* passes over a side's own leaves out cell by cell (`query`'s `skip`). Not to be gone by once an owner changed
|
|
34
|
+
* since (`ownerChanged`), until the next filing
|
|
35
|
+
*/
|
|
36
|
+
soleOwner;
|
|
37
|
+
/** By cell, how many units were filed in it so far this filing (`rebuild`) */
|
|
38
|
+
filed;
|
|
39
|
+
ownersMoved = false;
|
|
40
|
+
/** Radius of the biggest unit filed this tick */
|
|
41
|
+
maxRadius = 0;
|
|
42
|
+
/** Radius of the biggest unit filed this tick that is not big (`BIG_RADIUS`) */
|
|
43
|
+
maxSmallRadius = 0;
|
|
44
|
+
/**
|
|
45
|
+
* The big units filed this tick (they are in `cells` as well), in the order a query finds them: by cell, then
|
|
46
|
+
* as filed. Each one's cell, column and row alongside. Only up to `MAX_BIG`: `bigCount` counts them all
|
|
47
|
+
*/
|
|
48
|
+
big = [];
|
|
49
|
+
bigAt = new Int32Array(MAX_BIG);
|
|
50
|
+
bigCol = new Int32Array(MAX_BIG);
|
|
51
|
+
bigRow = new Int32Array(MAX_BIG);
|
|
52
|
+
bigCount = 0;
|
|
53
|
+
/** In a query, the first big unit in the list not yet gone by */
|
|
54
|
+
bigNext = 0;
|
|
55
|
+
/** Counts queries. A structure that covers several cells is marked with it when found, so it is only found once */
|
|
56
|
+
stamp = 0;
|
|
57
|
+
constructor(width, depth, cellSize = 4) {
|
|
58
|
+
this.cellSize = cellSize;
|
|
59
|
+
this.cols = Math.ceil(width / cellSize);
|
|
60
|
+
this.rows = Math.ceil(depth / cellSize);
|
|
61
|
+
this.cells = Array.from({ length: this.cols * this.rows }, () => []);
|
|
62
|
+
this.staticCells = Array.from({ length: this.cols * this.rows }, () => []);
|
|
63
|
+
this.soleOwner = new Int32Array(this.cols * this.rows).fill(-1);
|
|
64
|
+
this.filed = new Int32Array(this.cols * this.rows);
|
|
65
|
+
}
|
|
66
|
+
col(x) {
|
|
67
|
+
return Math.min(Math.max(Math.floor(x / this.cellSize), 0), this.cols - 1);
|
|
68
|
+
}
|
|
69
|
+
row(z) {
|
|
70
|
+
return Math.min(Math.max(Math.floor(z / this.cellSize), 0), this.rows - 1);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Files every unit again. Called once per tick, before the systems run. Structures in `entities` are passed over.
|
|
74
|
+
*
|
|
75
|
+
* Each cell is written over from its start and cut to what it got at the end, not emptied first: a list emptied
|
|
76
|
+
* (`length = 0`) lets go of its room, and filling it again would make it all anew, every cell, every tick
|
|
77
|
+
*/
|
|
78
|
+
rebuild(entities) {
|
|
79
|
+
this.maxRadius = 0;
|
|
80
|
+
this.maxSmallRadius = 0;
|
|
81
|
+
this.bigCount = 0;
|
|
82
|
+
this.ownersMoved = false;
|
|
83
|
+
const sole = this.soleOwner;
|
|
84
|
+
sole.fill(-1);
|
|
85
|
+
const filed = this.filed;
|
|
86
|
+
filed.fill(0);
|
|
87
|
+
for (const entity of entities) {
|
|
88
|
+
if (!entity.alive || entity.hidden || entity.isStructure) continue;
|
|
89
|
+
const at = this.row(entity.pos.z) * this.cols + this.col(entity.pos.x);
|
|
90
|
+
sole[at] = filed[at] === 0 || sole[at] === entity.owner ? entity.owner : -1;
|
|
91
|
+
this.cells[at][filed[at]++] = entity;
|
|
92
|
+
const radius = entity.def.radius;
|
|
93
|
+
if (radius > this.maxRadius) this.maxRadius = radius;
|
|
94
|
+
if (radius <= BIG_RADIUS) {
|
|
95
|
+
if (radius > this.maxSmallRadius) this.maxSmallRadius = radius;
|
|
96
|
+
} else if (this.bigCount++ < MAX_BIG) this.fileBig(entity, at);
|
|
97
|
+
}
|
|
98
|
+
const { cells } = this;
|
|
99
|
+
for (let i = 0; i < cells.length; i++) if (cells[i].length !== filed[i]) cells[i].length = filed[i];
|
|
100
|
+
this.big.length = Math.min(this.bigCount, MAX_BIG);
|
|
101
|
+
}
|
|
102
|
+
/** Into the list of big units, after every one in a cell before its own or in the same: as it is in the cells */
|
|
103
|
+
fileBig(entity, at) {
|
|
104
|
+
const { big, bigAt, bigCol, bigRow } = this;
|
|
105
|
+
let i = this.bigCount - 1;
|
|
106
|
+
for (; i > 0 && bigAt[i - 1] > at; i--) {
|
|
107
|
+
big[i] = big[i - 1];
|
|
108
|
+
bigAt[i] = bigAt[i - 1];
|
|
109
|
+
bigCol[i] = bigCol[i - 1];
|
|
110
|
+
bigRow[i] = bigRow[i - 1];
|
|
111
|
+
}
|
|
112
|
+
big[i] = entity;
|
|
113
|
+
bigAt[i] = at;
|
|
114
|
+
bigCol[i] = at % this.cols;
|
|
115
|
+
bigRow[i] = (at - bigCol[i]) / this.cols;
|
|
116
|
+
}
|
|
117
|
+
/** A unit filed this tick has another owner now: no cell's one owner is gone by until the next filing */
|
|
118
|
+
ownerChanged() {
|
|
119
|
+
this.ownersMoved = true;
|
|
120
|
+
}
|
|
121
|
+
/** Files a structure under every cell it covers, for as long as it stands */
|
|
122
|
+
insertStatic(entity) {
|
|
123
|
+
this.forCellsOf(entity, (cell) => cell.push(entity));
|
|
124
|
+
}
|
|
125
|
+
removeStatic(entity) {
|
|
126
|
+
this.forCellsOf(entity, (cell) => {
|
|
127
|
+
const index = cell.indexOf(entity);
|
|
128
|
+
if (index < 0) return;
|
|
129
|
+
cell.splice(index, 1);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
forCellsOf(entity, fn) {
|
|
133
|
+
const { x, z, hw, hd } = entity.rect;
|
|
134
|
+
const maxX = this.col(x + hw);
|
|
135
|
+
const maxZ = this.row(z + hd);
|
|
136
|
+
for (let cz = this.row(z - hd); cz <= maxZ; cz++) for (let cx = this.col(x - hw); cx <= maxX; cx++) fn(this.staticCells[cz * this.cols + cx]);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Entities that could be within `radius` of the point: every structure that has a part in the square around it,
|
|
140
|
+
* and every unit whose center is close enough for its edge to be. Callers do the exact distance check.
|
|
141
|
+
*
|
|
142
|
+
* The answer is written into `out`, which callers keep around and pass again so that nothing is allocated: over what
|
|
143
|
+
* it held, then cut to the answer (emptied first, a list lets go of its room and grows it again). While going
|
|
144
|
+
* through the answer, a caller that does something which can lead to another query with the same `out` (dealing damage
|
|
145
|
+
* can set off effects that look around) has to go through a copy instead: the other query would overwrite it.
|
|
146
|
+
*
|
|
147
|
+
* `skip`: owners whose units the caller passes over anyway (a side's own, as it picks a target): a cell of units of
|
|
148
|
+
* one such owner alone is left out. What is left is what the full answer had, in the same order, less some of theirs
|
|
149
|
+
*/
|
|
150
|
+
query(x, z, radius, out = [], skip) {
|
|
151
|
+
let found = 0;
|
|
152
|
+
const stamp = ++this.stamp;
|
|
153
|
+
const sole = skip && !this.ownersMoved ? this.soleOwner : void 0;
|
|
154
|
+
const bigs = this.bigCount <= MAX_BIG ? this.bigCount : 0;
|
|
155
|
+
let r = radius + (bigs ? this.maxSmallRadius : this.maxRadius);
|
|
156
|
+
const minX = this.col(x - r);
|
|
157
|
+
const minZ = this.row(z - r);
|
|
158
|
+
let maxX = this.col(x + r);
|
|
159
|
+
let maxZ = this.row(z + r);
|
|
160
|
+
this.bigNext = 0;
|
|
161
|
+
for (let cz = minZ; cz <= maxZ; cz++) for (let cx = minX; cx <= maxX; cx++) {
|
|
162
|
+
const at = cz * this.cols + cx;
|
|
163
|
+
if (this.bigNext < bigs && this.bigAt[this.bigNext] < at) found = this.addBigs(x, z, radius, minX, maxX, minZ, maxZ, at, out, found, skip);
|
|
164
|
+
if (sole && sole[at] >= 0 && skip(sole[at])) continue;
|
|
165
|
+
const cell = this.cells[at];
|
|
166
|
+
for (let i = 0; i < cell.length; i++) out[found++] = cell[i];
|
|
167
|
+
}
|
|
168
|
+
if (this.bigNext < bigs) found = this.addBigs(x, z, radius, minX, maxX, minZ, maxZ, Infinity, out, found, skip);
|
|
169
|
+
r = radius;
|
|
170
|
+
maxX = this.col(x + r);
|
|
171
|
+
maxZ = this.row(z + r);
|
|
172
|
+
for (let cz = this.row(z - r); cz <= maxZ; cz++) for (let cx = this.col(x - r); cx <= maxX; cx++) {
|
|
173
|
+
const cell = this.staticCells[cz * this.cols + cx];
|
|
174
|
+
for (let i = 0; i < cell.length; i++) {
|
|
175
|
+
const entity = cell[i];
|
|
176
|
+
if (entity.spatialStamp === stamp) continue;
|
|
177
|
+
entity.spatialStamp = stamp;
|
|
178
|
+
out[found++] = entity;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
out.length = found;
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Adds to a query's answer, from `bigNext` on, the big units in cells before `before` that the cells it goes
|
|
186
|
+
* through (`minX`..`maxZ`) leave out but that reach within `radius` of the point by their own radius: where they would
|
|
187
|
+
* have been in an answer that went through more cells. Those in a cell it goes through are found there. Returns how
|
|
188
|
+
* many the answer has now
|
|
189
|
+
*/
|
|
190
|
+
addBigs(x, z, radius, minX, maxX, minZ, maxZ, before, out, found, skip) {
|
|
191
|
+
const { big, bigAt, bigCol, bigRow, soleOwner } = this;
|
|
192
|
+
const sole = skip && !this.ownersMoved ? soleOwner : void 0;
|
|
193
|
+
const count = Math.min(this.bigCount, MAX_BIG);
|
|
194
|
+
let i = this.bigNext;
|
|
195
|
+
for (; i < count && bigAt[i] < before; i++) {
|
|
196
|
+
const cx = bigCol[i];
|
|
197
|
+
const cz = bigRow[i];
|
|
198
|
+
if (cx >= minX && cx <= maxX && cz >= minZ && cz <= maxZ) continue;
|
|
199
|
+
const r = radius + big[i].def.radius;
|
|
200
|
+
if (cx < this.col(x - r) || cx > this.col(x + r) || cz < this.row(z - r) || cz > this.row(z + r)) continue;
|
|
201
|
+
const at = bigAt[i];
|
|
202
|
+
if (sole && sole[at] >= 0 && skip(sole[at])) continue;
|
|
203
|
+
out[found++] = big[i];
|
|
204
|
+
}
|
|
205
|
+
this.bigNext = i;
|
|
206
|
+
return found;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Only the structures that have a part in the square around the point: buildings, trees, mines, every kind but a
|
|
210
|
+
* unit. For who looks for those alone, among crowds of units that would otherwise all be gone through. Into `out`,
|
|
211
|
+
* as `query`
|
|
212
|
+
*/
|
|
213
|
+
queryStatic(x, z, radius, out = []) {
|
|
214
|
+
let found = 0;
|
|
215
|
+
const stamp = ++this.stamp;
|
|
216
|
+
const maxX = this.col(x + radius);
|
|
217
|
+
const maxZ = this.row(z + radius);
|
|
218
|
+
for (let cz = this.row(z - radius); cz <= maxZ; cz++) for (let cx = this.col(x - radius); cx <= maxX; cx++) {
|
|
219
|
+
const cell = this.staticCells[cz * this.cols + cx];
|
|
220
|
+
for (let i = 0; i < cell.length; i++) {
|
|
221
|
+
const entity = cell[i];
|
|
222
|
+
if (entity.spatialStamp === stamp) continue;
|
|
223
|
+
entity.spatialStamp = stamp;
|
|
224
|
+
out[found++] = entity;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
out.length = found;
|
|
228
|
+
return out;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
//#endregion
|
|
232
|
+
export { SpatialIndex };
|
|
233
|
+
|
|
234
|
+
//# sourceMappingURL=spatial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spatial.js","names":[],"sources":["../src/spatial.ts"],"sourcesContent":["import type { Entity, PlayerId } from './entity'\n\n/**\n * Uniform grid for \"what is near this point\" queries. The map is cut into square cells and every entity is\n * filed under the cells it is in, so a query only looks at the few cells around the point instead of at every\n * entity in the world.\n *\n * There are two layers:\n * - Units move, so they are filed again from scratch every tick (`rebuild`), which is simpler and cheaper than\n * following every unit from cell to cell. A unit is filed by its center only, so queries look a little\n * further than asked, by the radius of the biggest ordinary unit, not to miss one whose edge is in range. The\n * few units bigger than that (`BIG_RADIUS`: a boss, a siege engine) are kept in a short list besides, which\n * every query goes through, each looked for as far as its own radius: one of them on the map does not make every\n * query near a crowd of small ones go through more cells. Above `MAX_BIG` of them, it is not worth it, and\n * queries look as far as the biggest unit again. Either way an answer is in the same order: by cell, and by\n * filing within a cell.\n * - Structures (buildings, trees, mines) never move, so they are filed once when they appear and taken out when\n * they go (`insertStatic`, `removeStatic`). They are filed under every cell their footprint covers, so a query\n * finds them by any part of them without looking further than asked. That matters: padding queries by the\n * size of the biggest building would make every query near a forest go through far more trees.\n */\n/** Units with a bigger radius than this are big: kept besides in a short list, not making every query look further */\nconst BIG_RADIUS = 1\n/** Above so many big units filed in a tick, queries look as far as the biggest one instead, as though there were none */\nconst MAX_BIG = 32\n\nexport class SpatialIndex {\n\tprivate readonly cols: number\n\tprivate readonly rows: number\n\tprivate readonly cells: Entity[][]\n\tprivate readonly staticCells: Entity[][]\n\t/**\n\t * By cell, the one owner of every unit filed in it this tick, or -1 for none or more than one: what a search that\n\t * passes over a side's own leaves out cell by cell (`query`'s `skip`). Not to be gone by once an owner changed\n\t * since (`ownerChanged`), until the next filing\n\t */\n\tprivate readonly soleOwner: Int32Array\n\t/** By cell, how many units were filed in it so far this filing (`rebuild`) */\n\tprivate readonly filed: Int32Array\n\tprivate ownersMoved = false\n\t/** Radius of the biggest unit filed this tick */\n\tprivate maxRadius = 0\n\t/** Radius of the biggest unit filed this tick that is not big (`BIG_RADIUS`) */\n\tprivate maxSmallRadius = 0\n\t/**\n\t * The big units filed this tick (they are in `cells` as well), in the order a query finds them: by cell, then\n\t * as filed. Each one's cell, column and row alongside. Only up to `MAX_BIG`: `bigCount` counts them all\n\t */\n\tprivate readonly big: Entity[] = []\n\tprivate readonly bigAt = new Int32Array(MAX_BIG)\n\tprivate readonly bigCol = new Int32Array(MAX_BIG)\n\tprivate readonly bigRow = new Int32Array(MAX_BIG)\n\tprivate bigCount = 0\n\t/** In a query, the first big unit in the list not yet gone by */\n\tprivate bigNext = 0\n\t/** Counts queries. A structure that covers several cells is marked with it when found, so it is only found once */\n\tprivate stamp = 0\n\n\tconstructor(\n\t\twidth: number,\n\t\tdepth: number,\n\t\tprivate readonly cellSize = 4\n\t) {\n\t\tthis.cols = Math.ceil(width / cellSize)\n\t\tthis.rows = Math.ceil(depth / cellSize)\n\t\tthis.cells = Array.from({ length: this.cols * this.rows }, () => [])\n\t\tthis.staticCells = Array.from({ length: this.cols * this.rows }, () => [])\n\t\tthis.soleOwner = new Int32Array(this.cols * this.rows).fill(-1)\n\t\tthis.filed = new Int32Array(this.cols * this.rows)\n\t}\n\n\tprivate col(x: number): number {\n\t\treturn Math.min(Math.max(Math.floor(x / this.cellSize), 0), this.cols - 1)\n\t}\n\n\tprivate row(z: number): number {\n\t\treturn Math.min(Math.max(Math.floor(z / this.cellSize), 0), this.rows - 1)\n\t}\n\n\t/**\n\t * Files every unit again. Called once per tick, before the systems run. Structures in `entities` are passed over.\n\t *\n\t * Each cell is written over from its start and cut to what it got at the end, not emptied first: a list emptied\n\t * (`length = 0`) lets go of its room, and filling it again would make it all anew, every cell, every tick\n\t */\n\trebuild(entities: Iterable<Entity>): void {\n\t\tthis.maxRadius = 0\n\t\tthis.maxSmallRadius = 0\n\t\tthis.bigCount = 0\n\t\tthis.ownersMoved = false\n\t\tconst sole = this.soleOwner\n\t\tsole.fill(-1)\n\t\tconst filed = this.filed\n\t\tfiled.fill(0)\n\t\tfor (const entity of entities) {\n\t\t\tif (!entity.alive || entity.hidden || entity.isStructure) continue\n\t\t\tconst at = this.row(entity.pos.z) * this.cols + this.col(entity.pos.x)\n\t\t\tsole[at] = filed[at] === 0 || sole[at] === entity.owner ? entity.owner : -1\n\t\t\tthis.cells[at][filed[at]++] = entity\n\t\t\tconst radius = entity.def.radius\n\t\t\tif (radius > this.maxRadius) this.maxRadius = radius\n\t\t\tif (radius <= BIG_RADIUS) {\n\t\t\t\tif (radius > this.maxSmallRadius) this.maxSmallRadius = radius\n\t\t\t} else if (this.bigCount++ < MAX_BIG) this.fileBig(entity, at)\n\t\t}\n\t\tconst { cells } = this\n\t\tfor (let i = 0; i < cells.length; i++) if (cells[i].length !== filed[i]) cells[i].length = filed[i]\n\t\tthis.big.length = Math.min(this.bigCount, MAX_BIG)\n\t}\n\n\t/** Into the list of big units, after every one in a cell before its own or in the same: as it is in the cells */\n\tprivate fileBig(entity: Entity, at: number): void {\n\t\tconst { big, bigAt, bigCol, bigRow } = this\n\t\tlet i = this.bigCount - 1\n\t\tfor (; i > 0 && bigAt[i - 1] > at; i--) {\n\t\t\tbig[i] = big[i - 1]\n\t\t\tbigAt[i] = bigAt[i - 1]\n\t\t\tbigCol[i] = bigCol[i - 1]\n\t\t\tbigRow[i] = bigRow[i - 1]\n\t\t}\n\t\tbig[i] = entity\n\t\tbigAt[i] = at\n\t\tbigCol[i] = at % this.cols\n\t\tbigRow[i] = (at - bigCol[i]) / this.cols\n\t}\n\n\t/** A unit filed this tick has another owner now: no cell's one owner is gone by until the next filing */\n\townerChanged(): void {\n\t\tthis.ownersMoved = true\n\t}\n\n\t/** Files a structure under every cell it covers, for as long as it stands */\n\tinsertStatic(entity: Entity): void {\n\t\tthis.forCellsOf(entity, (cell) => cell.push(entity))\n\t}\n\n\tremoveStatic(entity: Entity): void {\n\t\tthis.forCellsOf(entity, (cell) => {\n\t\t\tconst index = cell.indexOf(entity)\n\t\t\tif (index < 0) return\n\t\t\t// the others keep their order (insertion order, which a load restores): ties between targets break by it\n\t\t\tcell.splice(index, 1)\n\t\t})\n\t}\n\n\tprivate forCellsOf(entity: Entity, fn: (cell: Entity[]) => void): void {\n\t\tconst { x, z, hw, hd } = entity.rect\n\t\tconst maxX = this.col(x + hw)\n\t\tconst maxZ = this.row(z + hd)\n\t\tfor (let cz = this.row(z - hd); cz <= maxZ; cz++) {\n\t\t\tfor (let cx = this.col(x - hw); cx <= maxX; cx++) fn(this.staticCells[cz * this.cols + cx])\n\t\t}\n\t}\n\n\t/**\n\t * Entities that could be within `radius` of the point: every structure that has a part in the square around it,\n\t * and every unit whose center is close enough for its edge to be. Callers do the exact distance check.\n\t *\n\t * The answer is written into `out`, which callers keep around and pass again so that nothing is allocated: over what\n\t * it held, then cut to the answer (emptied first, a list lets go of its room and grows it again). While going\n\t * through the answer, a caller that does something which can lead to another query with the same `out` (dealing damage\n\t * can set off effects that look around) has to go through a copy instead: the other query would overwrite it.\n\t *\n\t * `skip`: owners whose units the caller passes over anyway (a side's own, as it picks a target): a cell of units of\n\t * one such owner alone is left out. What is left is what the full answer had, in the same order, less some of theirs\n\t */\n\tquery(x: number, z: number, radius: number, out: Entity[] = [], skip?: (owner: PlayerId) => boolean): Entity[] {\n\t\tlet found = 0\n\t\tconst stamp = ++this.stamp\n\t\tconst sole = skip && !this.ownersMoved ? this.soleOwner : undefined\n\n\t\t// a few big units: the cells as far as the biggest of the others, and the big ones each as far as its own radius,\n\t\t// found among them in the cells' order. Many: as far as the biggest of all\n\t\tconst bigs = this.bigCount <= MAX_BIG ? this.bigCount : 0\n\t\tlet r = radius + (bigs ? this.maxSmallRadius : this.maxRadius)\n\t\tconst minX = this.col(x - r)\n\t\tconst minZ = this.row(z - r)\n\t\tlet maxX = this.col(x + r)\n\t\tlet maxZ = this.row(z + r)\n\t\tthis.bigNext = 0\n\t\tfor (let cz = minZ; cz <= maxZ; cz++) {\n\t\t\tfor (let cx = minX; cx <= maxX; cx++) {\n\t\t\t\tconst at = cz * this.cols + cx\n\t\t\t\tif (this.bigNext < bigs && this.bigAt[this.bigNext] < at) found = this.addBigs(x, z, radius, minX, maxX, minZ, maxZ, at, out, found, skip)\n\t\t\t\tif (sole && sole[at] >= 0 && skip!(sole[at])) continue\n\t\t\t\tconst cell = this.cells[at]\n\t\t\t\tfor (let i = 0; i < cell.length; i++) out[found++] = cell[i]\n\t\t\t}\n\t\t}\n\t\tif (this.bigNext < bigs) found = this.addBigs(x, z, radius, minX, maxX, minZ, maxZ, Infinity, out, found, skip)\n\n\t\tr = radius\n\t\tmaxX = this.col(x + r)\n\t\tmaxZ = this.row(z + r)\n\t\tfor (let cz = this.row(z - r); cz <= maxZ; cz++) {\n\t\t\tfor (let cx = this.col(x - r); cx <= maxX; cx++) {\n\t\t\t\tconst cell = this.staticCells[cz * this.cols + cx]\n\t\t\t\tfor (let i = 0; i < cell.length; i++) {\n\t\t\t\t\tconst entity = cell[i]\n\t\t\t\t\tif (entity.spatialStamp === stamp) continue\n\t\t\t\t\tentity.spatialStamp = stamp\n\t\t\t\t\tout[found++] = entity\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tout.length = found\n\t\treturn out\n\t}\n\n\t/**\n\t * Adds to a query's answer, from `bigNext` on, the big units in cells before `before` that the cells it goes\n\t * through (`minX`..`maxZ`) leave out but that reach within `radius` of the point by their own radius: where they would\n\t * have been in an answer that went through more cells. Those in a cell it goes through are found there. Returns how\n\t * many the answer has now\n\t */\n\tprivate addBigs(\n\t\tx: number,\n\t\tz: number,\n\t\tradius: number,\n\t\tminX: number,\n\t\tmaxX: number,\n\t\tminZ: number,\n\t\tmaxZ: number,\n\t\tbefore: number,\n\t\tout: Entity[],\n\t\tfound: number,\n\t\tskip: ((owner: PlayerId) => boolean) | undefined\n\t): number {\n\t\tconst { big, bigAt, bigCol, bigRow, soleOwner } = this\n\t\tconst sole = skip && !this.ownersMoved ? soleOwner : undefined\n\t\tconst count = Math.min(this.bigCount, MAX_BIG)\n\t\tlet i = this.bigNext\n\t\tfor (; i < count && bigAt[i] < before; i++) {\n\t\t\tconst cx = bigCol[i]\n\t\t\tconst cz = bigRow[i]\n\t\t\tif (cx >= minX && cx <= maxX && cz >= minZ && cz <= maxZ) continue\n\t\t\tconst r = radius + big[i].def.radius\n\t\t\tif (cx < this.col(x - r) || cx > this.col(x + r) || cz < this.row(z - r) || cz > this.row(z + r)) continue\n\t\t\tconst at = bigAt[i]\n\t\t\tif (sole && sole[at] >= 0 && skip!(sole[at])) continue\n\t\t\tout[found++] = big[i]\n\t\t}\n\t\tthis.bigNext = i\n\t\treturn found\n\t}\n\n\t/**\n\t * Only the structures that have a part in the square around the point: buildings, trees, mines, every kind but a\n\t * unit. For who looks for those alone, among crowds of units that would otherwise all be gone through. Into `out`,\n\t * as `query`\n\t */\n\tqueryStatic(x: number, z: number, radius: number, out: Entity[] = []): Entity[] {\n\t\tlet found = 0\n\t\tconst stamp = ++this.stamp\n\t\tconst maxX = this.col(x + radius)\n\t\tconst maxZ = this.row(z + radius)\n\t\tfor (let cz = this.row(z - radius); cz <= maxZ; cz++) {\n\t\t\tfor (let cx = this.col(x - radius); cx <= maxX; cx++) {\n\t\t\t\tconst cell = this.staticCells[cz * this.cols + cx]\n\t\t\t\tfor (let i = 0; i < cell.length; i++) {\n\t\t\t\t\tconst entity = cell[i]\n\t\t\t\t\tif (entity.spatialStamp === stamp) continue\n\t\t\t\t\tentity.spatialStamp = stamp\n\t\t\t\t\tout[found++] = entity\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tout.length = found\n\t\treturn out\n\t}\n}\n"],"mappings":"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"}
|
package/dist/spawning.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare class Spawning {
|
|
|
13
13
|
/**
|
|
14
14
|
* Turns scenery into an actor, for good: something gave it a reason to be looked at every tick, like a buff
|
|
15
15
|
* that has to run out. Whatever does that to an entity calls this.world; the debug checks catch what forgets to.
|
|
16
|
+
* It joins `World.units` at the end, out of id order (see `World.units`), which a save keeps as it is
|
|
16
17
|
*/
|
|
17
18
|
wake(entity: Entity): void;
|
|
18
19
|
/** Puts a unit somewhere else, where it stands: the way through is not its concern. Structures stay where they were built */
|