@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,518 +0,0 @@
|
|
|
1
|
-
import { Cc as xpWorth, Gc as engineMessage, Ju as unitHired, Kn as worthless, Ml as teamMemory, Na as index, Qr as defineHook, Rn as corpseSystem, Ua as string, Wd as distSq, aa as buy, ac as defaultHeroRules, cl as fighting, cr as producers, dc as heroesOf, el as shortOf, fc as learn, ga as shopStock, ia as atShop, ir as leastBusy, ja as id, lc as heroState, li as enqueueRevive, ma as sell, mc as maxLevelOf, oc as grantXp, or as owned, qd as hashText, rc as HEROES, rr as known, sc as heroOf, tl as spend, tr as defineCommand, za as optional } from "./debugCommands-CzjrSm66.js";
|
|
2
|
-
import { o as loadWorld } from "./game-DiJEN-Ks.js";
|
|
3
|
-
import { _t as campHooks, ct as saveWorld, it as encodeSave, rt as decodeSave, xt as campRespawnSystem } from "./coreComponents-syuh2fPG.js";
|
|
4
|
-
//#region src/packs/heroes/hire.ts
|
|
5
|
-
/**
|
|
6
|
-
* Whether someone of a player's stands at a place that hires (`UnitTypeDef.hires`) to hire there: any unit of theirs
|
|
7
|
-
* close enough, as at a shop. The first one found
|
|
8
|
-
*
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
11
|
-
function hirerAt(world, shop, player) {
|
|
12
|
-
for (const entity of world.index.ownedBy(player)) if (entity.alive && !entity.hidden && entity.def.kind === "unit" && atShop(entity, shop)) return entity;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Why a player cannot hire a unit at a place now, as the message the player is told: none of theirs there, a hero
|
|
16
|
-
* they have already (a hero is hired once), what it costs. Nothing when they can
|
|
17
|
-
*
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
function hireRefusal(world, shop, unit, player) {
|
|
21
|
-
if (!shop.def.hires?.includes(unit) || !world.registry.units.has(unit)) return engineMessage("cannotDoThat");
|
|
22
|
-
if (!shop.alive || !shop.operational || world.areEnemies(shop.owner, player)) return engineMessage("cannotDoThat");
|
|
23
|
-
const def = world.registry.unit(unit);
|
|
24
|
-
if (def.hero && heroesOf(world, player).some((hero) => hero.def.id === unit)) return engineMessage("alreadyHired", { unit });
|
|
25
|
-
if (!hirerAt(world, shop, player)) return engineMessage("unitAtShop");
|
|
26
|
-
const short = shortOf(world.player(player).resources, def.cost);
|
|
27
|
-
if (short) return engineMessage("notEnough", { resource: short });
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Hires a unit at a place that hires for a player: a tavern's hero, a dock's boat. Paid for, and made next to the
|
|
31
|
-
* place, a boat on the water nearest it. The unit, or nothing with the player told why
|
|
32
|
-
*
|
|
33
|
-
* @beta
|
|
34
|
-
*/
|
|
35
|
-
function hire(world, shop, unit, player) {
|
|
36
|
-
const refusal = hireRefusal(world, shop, unit, player);
|
|
37
|
-
if (refusal) {
|
|
38
|
-
world.message(player, refusal);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
const def = world.registry.unit(unit);
|
|
42
|
-
spend(world, player, def.cost, "hire", unit);
|
|
43
|
-
const hired = world.spawn(unit, player, {
|
|
44
|
-
x: shop.pos.x,
|
|
45
|
-
z: shop.pos.z + shop.def.radius + def.radius + .5
|
|
46
|
-
});
|
|
47
|
-
world.events.emit(unitHired, {
|
|
48
|
-
shop,
|
|
49
|
-
unit: hired,
|
|
50
|
-
player
|
|
51
|
-
});
|
|
52
|
-
return hired;
|
|
53
|
-
}
|
|
54
|
-
//#endregion
|
|
55
|
-
//#region src/packs/heroes/commands.ts
|
|
56
|
-
/**
|
|
57
|
-
* The heroes pack's commands: buying and selling at a shop, hiring, putting a point into an ability, bringing a hero
|
|
58
|
-
* back at an altar. Taken by a world whose game has the pack on (`withHeroes`); a game without it refuses them as it
|
|
59
|
-
* does any command it does not know. Their type is among `Command`s, as the pack adds it (`Commands`)
|
|
60
|
-
*/
|
|
61
|
-
/**
|
|
62
|
-
* Buys from a shop, for the hero that is named, or else the one of the player that stands closest to it
|
|
63
|
-
*
|
|
64
|
-
* @internal
|
|
65
|
-
*/
|
|
66
|
-
var buyCommand = defineCommand("buy", {
|
|
67
|
-
shop: id,
|
|
68
|
-
item: string,
|
|
69
|
-
hero: optional(id)
|
|
70
|
-
}, (world, player, command) => {
|
|
71
|
-
const shop = known(world, player, command.shop);
|
|
72
|
-
const [buyer] = command.hero === void 0 ? [] : owned(world, player, [command.hero]);
|
|
73
|
-
if (shop && !world.areEnemies(shop.owner, player)) buy(world, shop, command.item, player, buyer);
|
|
74
|
-
});
|
|
75
|
-
/**
|
|
76
|
-
* Hires a unit at a place that hires, a tavern or a dock: someone of the player's has to be there
|
|
77
|
-
*
|
|
78
|
-
* @internal
|
|
79
|
-
*/
|
|
80
|
-
var hireCommand = defineCommand("hire", {
|
|
81
|
-
shop: id,
|
|
82
|
-
unit: string
|
|
83
|
-
}, (world, player, command) => {
|
|
84
|
-
const shop = known(world, player, command.shop);
|
|
85
|
-
if (shop) hire(world, shop, command.unit, player);
|
|
86
|
-
});
|
|
87
|
-
/**
|
|
88
|
-
* Gives something a hero carries back at a shop nearby, for a part of its price
|
|
89
|
-
*
|
|
90
|
-
* @internal
|
|
91
|
-
*/
|
|
92
|
-
var sellCommand = defineCommand("sell", {
|
|
93
|
-
entity: id,
|
|
94
|
-
item: index
|
|
95
|
-
}, (world, player, command) => {
|
|
96
|
-
const [seller] = owned(world, player, [command.entity]);
|
|
97
|
-
if (seller) sell(world, seller, command.item);
|
|
98
|
-
});
|
|
99
|
-
/**
|
|
100
|
-
* Puts a point a hero has to spend into an ability
|
|
101
|
-
*
|
|
102
|
-
* @internal
|
|
103
|
-
*/
|
|
104
|
-
var learnCommand = defineCommand("learn", {
|
|
105
|
-
entity: id,
|
|
106
|
-
ability: string
|
|
107
|
-
}, (world, player, command) => {
|
|
108
|
-
const [hero] = owned(world, player, [command.entity]);
|
|
109
|
-
if (hero) learn(world, hero, command.ability);
|
|
110
|
-
});
|
|
111
|
-
/** @internal */
|
|
112
|
-
var reviveCommand = defineCommand("revive", {
|
|
113
|
-
...producers,
|
|
114
|
-
hero: id
|
|
115
|
-
}, (world, player, command) => {
|
|
116
|
-
const building = leastBusy(world, player, command, (entity) => !!entity.def.revives);
|
|
117
|
-
if (building) enqueueRevive(world, building, command.hero);
|
|
118
|
-
});
|
|
119
|
-
/**
|
|
120
|
-
* The commands of the heroes pack (`withHeroes`): buying, hiring, selling, learning, bringing a hero back. A game
|
|
121
|
-
* without the pack refuses them as it does any command it does not know
|
|
122
|
-
*
|
|
123
|
-
* @internal
|
|
124
|
-
*/
|
|
125
|
-
var heroCommands = [
|
|
126
|
-
buyCommand,
|
|
127
|
-
hireCommand,
|
|
128
|
-
sellCommand,
|
|
129
|
-
learnCommand,
|
|
130
|
-
reviveCommand
|
|
131
|
-
];
|
|
132
|
-
//#endregion
|
|
133
|
-
//#region src/packs/heroes/making.ts
|
|
134
|
-
/**
|
|
135
|
-
* Makes a unit just made a hero, as its type says (`UnitTypeDef.hero`): level 1, a point to spend, the abilities it can
|
|
136
|
-
* learn (none learned) and the spells it starts with, those it has not got already. What `World.spawn` does for a
|
|
137
|
-
* hero's type, and `morph` for what becomes one
|
|
138
|
-
*
|
|
139
|
-
* @beta
|
|
140
|
-
*/
|
|
141
|
-
function makeHero(world, entity) {
|
|
142
|
-
const def = entity.def.hero;
|
|
143
|
-
if (!def) return;
|
|
144
|
-
entity.set(heroState, {
|
|
145
|
-
level: 1,
|
|
146
|
-
xp: 0,
|
|
147
|
-
points: 1
|
|
148
|
-
});
|
|
149
|
-
const add = (id, level) => {
|
|
150
|
-
if (!entity.abilities.some((state) => state.id === id)) entity.addAbility({
|
|
151
|
-
id: world.registry.ability(id).id,
|
|
152
|
-
level,
|
|
153
|
-
cooldown: 0,
|
|
154
|
-
autocast: false
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
for (const id of def.learns) add(id, 0);
|
|
158
|
-
for (const id of def.spells ?? []) add(id, 1);
|
|
159
|
-
}
|
|
160
|
-
/** Shares the experience for a kill between the heroes of the killer's side that were around */
|
|
161
|
-
function awardKill(world, dead, killer) {
|
|
162
|
-
if (!killer || !world.areEnemies(killer.owner, dead.owner)) return;
|
|
163
|
-
const worth = xpWorth(world, dead);
|
|
164
|
-
if (worth <= 0) return;
|
|
165
|
-
const heroes = [];
|
|
166
|
-
const { xpRange } = world.rules.heroes;
|
|
167
|
-
for (const player of world.players.values()) {
|
|
168
|
-
if (!world.areAllies(player.id, killer.owner)) continue;
|
|
169
|
-
for (const entity of world.index.with(heroState, player.id)) {
|
|
170
|
-
if (!entity.alive || heroOf(entity).level >= maxLevelOf(world, entity)) continue;
|
|
171
|
-
if (distSq(entity.pos, dead.pos) <= xpRange * xpRange) heroes.push(entity);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
for (const hero of heroes) grantXp(world, hero, worth / heroes.length, dead);
|
|
175
|
-
}
|
|
176
|
-
//#endregion
|
|
177
|
-
//#region src/packs/heroes/index.ts
|
|
178
|
-
/** A shop's wares, each as many as it stocks; what it stocked already as it was, where it sells it still */
|
|
179
|
-
function stockShop(world, entity) {
|
|
180
|
-
const sells = entity.def.sells ?? [];
|
|
181
|
-
const had = entity.get(shopStock);
|
|
182
|
-
if (!sells.length) {
|
|
183
|
-
if (had) entity.remove(shopStock);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
entity.set(shopStock, sells.map((item) => {
|
|
187
|
-
const kept = had?.find((stock) => stock.item === item);
|
|
188
|
-
if (kept) return kept;
|
|
189
|
-
const stock = world.registry.item(item).stock;
|
|
190
|
-
return {
|
|
191
|
-
item,
|
|
192
|
-
count: stock?.max ?? 1,
|
|
193
|
-
restock: stock?.restock ?? 60
|
|
194
|
-
};
|
|
195
|
-
}));
|
|
196
|
-
}
|
|
197
|
-
/** What the pack does as things are made, change type, die and fall: heroes, their experience, shops' wares */
|
|
198
|
-
var heroHooks = [
|
|
199
|
-
defineHook({
|
|
200
|
-
hook: "made",
|
|
201
|
-
id: "hero",
|
|
202
|
-
run(world, entity) {
|
|
203
|
-
if (entity.def.hero) makeHero(world, entity);
|
|
204
|
-
stockShop(world, entity);
|
|
205
|
-
}
|
|
206
|
-
}),
|
|
207
|
-
defineHook({
|
|
208
|
-
hook: "morphed",
|
|
209
|
-
id: "hero",
|
|
210
|
-
run(world, { entity }) {
|
|
211
|
-
if (entity.def.hero && !entity.has(heroState)) makeHero(world, entity);
|
|
212
|
-
if (entity.def.sells?.length || entity.has(shopStock)) stockShop(world, entity);
|
|
213
|
-
}
|
|
214
|
-
}),
|
|
215
|
-
defineHook({
|
|
216
|
-
hook: "death",
|
|
217
|
-
id: "experience",
|
|
218
|
-
run(world, { entity, killer }) {
|
|
219
|
-
if (worthless(entity)) return;
|
|
220
|
-
awardKill(world, entity, killer);
|
|
221
|
-
}
|
|
222
|
-
}),
|
|
223
|
-
defineHook({
|
|
224
|
-
hook: "fallenHero",
|
|
225
|
-
id: "heroesStay",
|
|
226
|
-
run(_world, event) {
|
|
227
|
-
if (event.entity.has(heroState)) event.stays = true;
|
|
228
|
-
}
|
|
229
|
-
}),
|
|
230
|
-
...campHooks
|
|
231
|
-
];
|
|
232
|
-
/**
|
|
233
|
-
* A hero's stats grow with its level, as its type says (`UnitTypeDef.hero.growth`): stamped with the level past the
|
|
234
|
-
* first, so that a level set however it is set is added up again
|
|
235
|
-
*/
|
|
236
|
-
var heroGrowth = {
|
|
237
|
-
id: "heroGrowth",
|
|
238
|
-
stamp(entity) {
|
|
239
|
-
if (!entity.def.hero) return 0;
|
|
240
|
-
const level = heroOf(entity)?.level ?? 1;
|
|
241
|
-
return level > 1 ? level : 0;
|
|
242
|
-
},
|
|
243
|
-
add(_world, entity, sum) {
|
|
244
|
-
const growth = entity.def.hero?.growth;
|
|
245
|
-
const hero = growth && heroOf(entity);
|
|
246
|
-
if (hero && hero.level > 1) sum.add(growth, hero.level - 1);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
/** Camps come back as the engine's own did: in the clean-up, before the corpses go */
|
|
250
|
-
var campsComeBack = {
|
|
251
|
-
...campRespawnSystem,
|
|
252
|
-
before: [corpseSystem.name]
|
|
253
|
-
};
|
|
254
|
-
/**
|
|
255
|
-
* The heroes pack: what makes a game a classic hero RTS, opted into (`GameModule.packs: [withHeroes()]`). Heroes, with
|
|
256
|
-
* their experience, levels, points and abilities to learn, brought back at an altar (`revive`); creeps' camps that guard
|
|
257
|
-
* their ground, sleep at night and come back (`Camp.respawn`); shops that sell (`buy`, `sell`) and places that hire
|
|
258
|
-
* (`hire`). `rules` change its numbers (`HeroRules`: how many heroes, the experience a level takes), the classic RTS numbers for
|
|
259
|
-
* those left out. A game without it pays nothing for any of it: no hero is made of a hero's type, no command of these
|
|
260
|
-
* is taken, no camp is looked at
|
|
261
|
-
*
|
|
262
|
-
* @beta
|
|
263
|
-
*/
|
|
264
|
-
function withHeroes(rules = {}) {
|
|
265
|
-
for (const key of Object.keys(rules)) if (!(key in defaultHeroRules)) throw new Error(`"${key}" is not a rule of the heroes pack`);
|
|
266
|
-
return {
|
|
267
|
-
id: HEROES,
|
|
268
|
-
options: rules,
|
|
269
|
-
rules: () => ({ heroes: rules }),
|
|
270
|
-
commands: [...heroCommands],
|
|
271
|
-
systems: [campsComeBack],
|
|
272
|
-
hooks: heroHooks,
|
|
273
|
-
statParts: [heroGrowth]
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
//#endregion
|
|
277
|
-
//#region src/determinism.ts
|
|
278
|
-
/**
|
|
279
|
-
* Whether a game comes out the same (determinism plan D1): the simulation's state as data and as a hash, and a check
|
|
280
|
-
* that runs a world twice, and on from a save, and says the first tick and the first thing they differ at. What a
|
|
281
|
-
* replay of commands, a save that goes on exactly and a game the same in every browser stand on
|
|
282
|
-
*/
|
|
283
|
-
/**
|
|
284
|
-
* The simulation's state as plain data: its save, which holds all of it, but what each team's screens remember of the
|
|
285
|
-
* map, which is the watchers' (`teamMemory`)
|
|
286
|
-
*
|
|
287
|
-
* @beta
|
|
288
|
-
*/
|
|
289
|
-
function worldState(world) {
|
|
290
|
-
return decided(saveWorld(world, { reseat: false }), world.registry);
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* A save as what decides the game: without what each team's screens remember of the map (`teamMemory`: kept in the
|
|
294
|
-
* world for who comes back, written by whoever watches it, and read by nothing that decides), and, with the rules, the
|
|
295
|
-
* components nobody would have made had nobody asked for them (`unasked`)
|
|
296
|
-
*/
|
|
297
|
-
function decided(save, registry) {
|
|
298
|
-
const { [teamMemory.id]: _memory, ...state } = save.state;
|
|
299
|
-
const kept = (components) => registry ? unasked(registry, components) : components;
|
|
300
|
-
return {
|
|
301
|
-
...save,
|
|
302
|
-
state: kept(state),
|
|
303
|
-
players: save.players.map((player) => ({
|
|
304
|
-
...player,
|
|
305
|
-
state: kept(player.state)
|
|
306
|
-
})),
|
|
307
|
-
entities: save.entities.map((entity) => entity.components ? {
|
|
308
|
-
...entity,
|
|
309
|
-
components: kept(entity.components)
|
|
310
|
-
} : entity)
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Where two saves of a game first differ, as `checkDeterminism` looks (what decides first: the tick, the random state,
|
|
315
|
-
* the players, the entities): the path to it (`entities[id 11].pos.x`) and what each holds there, or nothing when they
|
|
316
|
-
* are the same. What the screens remember of the map, and the hash of the rules they were made with, are left out;
|
|
317
|
-
* with the game's `registry`, so are components that hold what they are made with (a screen asking for one makes it).
|
|
318
|
-
* What a replay that came apart says at its checkpoints (`runReplay`), and `v12 save diff`
|
|
319
|
-
*
|
|
320
|
-
* @beta
|
|
321
|
-
*/
|
|
322
|
-
function saveDifference(a, b, registry) {
|
|
323
|
-
const ordered = (save) => {
|
|
324
|
-
const { hash: _rules, ...state } = decided(save, registry);
|
|
325
|
-
return {
|
|
326
|
-
...Object.fromEntries(FIRST.map((key) => [key, state[key]])),
|
|
327
|
-
...state
|
|
328
|
-
};
|
|
329
|
-
};
|
|
330
|
-
return firstDifference(ordered(a), ordered(b));
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Components as they would be had nobody asked for one that was not there: one that holds what its component makes
|
|
334
|
-
* when asked for (its `default`) is left out. Asking makes one, and a watcher's screen asks for what it shows (a
|
|
335
|
-
* player's objectives), so a world watched and the same world unwatched differ in that alone
|
|
336
|
-
*/
|
|
337
|
-
function unasked(registry, components) {
|
|
338
|
-
const kept = {};
|
|
339
|
-
for (const [id, value] of Object.entries(components)) {
|
|
340
|
-
const made = registry.component(id)?.default?.();
|
|
341
|
-
if (made !== void 0 && JSON.stringify(made) === JSON.stringify(value)) continue;
|
|
342
|
-
kept[id] = value;
|
|
343
|
-
}
|
|
344
|
-
return kept;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* The simulation's state as a hash: two worlds with the same hash are, to all that is saved of them, the same. Fourteen
|
|
348
|
-
* hex digits (cyrb53, of the save as JSON, but the hash of the rules, which another build of the same code writes
|
|
349
|
-
* otherwise): enough to tell drift, not to stand against someone forging a state
|
|
350
|
-
*
|
|
351
|
-
* @beta
|
|
352
|
-
*/
|
|
353
|
-
var worldHash = (world) => {
|
|
354
|
-
const { hash: _rules, ...state } = worldState(world);
|
|
355
|
-
return hashText(canonical(state));
|
|
356
|
-
};
|
|
357
|
-
/**
|
|
358
|
-
* JSON with the keys of every object in order: the same state as text however it was put together (a component a
|
|
359
|
-
* watcher made early comes first in its object, and later where nobody watched)
|
|
360
|
-
*/
|
|
361
|
-
function canonical(value) {
|
|
362
|
-
return JSON.stringify(value, (_key, each) => {
|
|
363
|
-
if (!each || typeof each !== "object" || Array.isArray(each)) return each;
|
|
364
|
-
const sorted = {};
|
|
365
|
-
for (const key of Object.keys(each).sort()) sorted[key] = each[key];
|
|
366
|
-
return sorted;
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* A quick hash of what a game that came apart differs in first: the tick, the random state, each player's resources,
|
|
371
|
-
* upgrades and supply, and each entity's id, type, owner, place, facing, health, mana, whether it lives, its orders (how
|
|
372
|
-
* many, and the first's kind and target), its buffs (which, and the time left) and its attack's cooldown and swing. Read
|
|
373
|
-
* off the world as it is, with no save: 0.4 ms at 1000 units a side, where `worldHash` takes 66. What a
|
|
374
|
-
* replay of commands keeps every few seconds and checks as it plays (`recordCommands`), and what `checkDeterminism`
|
|
375
|
-
* compares every tick, for the tick a game came apart at; what it leaves out (components, areas, the fog) the whole
|
|
376
|
-
* state, compared every so often, has
|
|
377
|
-
*
|
|
378
|
-
* @beta
|
|
379
|
-
*/
|
|
380
|
-
function worldFingerprint(world) {
|
|
381
|
-
const values = [world.tick, world.rng.save()];
|
|
382
|
-
for (const player of world.players.values()) {
|
|
383
|
-
values.push(player.id, player.supplyUsed, player.supplyCap);
|
|
384
|
-
for (const key of Object.keys(player.resources).sort()) values.push(player.resources[key] ?? 0);
|
|
385
|
-
for (const [upgrade, level] of player.upgrades) values.push(wordOf(upgrade), level);
|
|
386
|
-
}
|
|
387
|
-
for (const entity of world.entities.values()) {
|
|
388
|
-
values.push(entity.id, wordOf(entity.def.id), entity.owner, entity.pos.x, entity.pos.z, entity.facing, entity.hp, entity.mana, entity.alive ? 1 : 0);
|
|
389
|
-
const order = entity.orders[0];
|
|
390
|
-
values.push(entity.orders.length, order ? wordOf(order.type) : 0, order?.init.target ?? 0);
|
|
391
|
-
values.push(entity.buffs.length);
|
|
392
|
-
for (const buff of entity.buffs) values.push(wordOf(buff.id), buff.remaining);
|
|
393
|
-
if (entity.get(fighting)) values.push(entity.get(fighting).cooldown, entity.get(fighting).swing);
|
|
394
|
-
}
|
|
395
|
-
return hashWords(new Uint32Array(Float64Array.from(values).buffer));
|
|
396
|
-
}
|
|
397
|
-
/** A short text as a number, for the fingerprint: FNV-1a of its characters */
|
|
398
|
-
function wordOf(text) {
|
|
399
|
-
let h = 2166136261;
|
|
400
|
-
for (let i = 0; i < text.length; i++) h = Math.imul(h ^ text.charCodeAt(i), 16777619);
|
|
401
|
-
return h >>> 0;
|
|
402
|
-
}
|
|
403
|
-
/** cyrb53 of 32-bit words: the bits of numbers, hashed as they are */
|
|
404
|
-
function hashWords(words) {
|
|
405
|
-
let h1 = 3735928559;
|
|
406
|
-
let h2 = 1103547991;
|
|
407
|
-
for (const word of words) {
|
|
408
|
-
h1 = Math.imul(h1 ^ word, 2654435761);
|
|
409
|
-
h2 = Math.imul(h2 ^ word, 1597334677);
|
|
410
|
-
}
|
|
411
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
|
|
412
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
|
|
413
|
-
return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, "0");
|
|
414
|
-
}
|
|
415
|
-
/**
|
|
416
|
-
* Where two states first differ: the path to it (`entities[id 11].pos.x`) and what each holds there. Nothing when they
|
|
417
|
-
* are the same. Lists of things with an `id` are named by it, the rest by their place
|
|
418
|
-
*
|
|
419
|
-
* @beta
|
|
420
|
-
*/
|
|
421
|
-
function firstDifference(a, b, path = "") {
|
|
422
|
-
if (Object.is(a, b)) return void 0;
|
|
423
|
-
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null || Array.isArray(a) !== Array.isArray(b)) return {
|
|
424
|
-
path,
|
|
425
|
-
a,
|
|
426
|
-
b
|
|
427
|
-
};
|
|
428
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
429
|
-
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
430
|
-
const each = a[i] ?? b[i];
|
|
431
|
-
const named = each && typeof each === "object" && "id" in each ? `[id ${String(each.id)}]` : `[${i}]`;
|
|
432
|
-
const found = firstDifference(a[i], b[i], `${path}${named}`);
|
|
433
|
-
if (found) return found;
|
|
434
|
-
}
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
438
|
-
for (const key of keys) {
|
|
439
|
-
const found = firstDifference(a[key], b[key], path ? `${path}.${key}` : key);
|
|
440
|
-
if (found) return found;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
/**
|
|
444
|
-
* Makes a world twice with `make` (the same seed, the same commands given in it, as a replay would) and runs them side
|
|
445
|
-
* by side, comparing their fingerprints every tick and their states (and the order each player's entities are filed
|
|
446
|
-
* in) every `every` ticks; with `from`, a third is saved at that tick and a fourth loaded
|
|
447
|
-
* from the save, and the two run on side by side. Says, for each, the first tick and thing it differs at, or that it does not. A test of a game's
|
|
448
|
-
* own systems: one that reads `Math.random`, the clock, or the order of something unordered is found here
|
|
449
|
-
*
|
|
450
|
-
* const report = await checkDeterminism(() => makeMyGame(1), { ticks: 1800, from: 300, game: rules })
|
|
451
|
-
* expect(report).toEqual({ twice: null, fromSave: null })
|
|
452
|
-
*
|
|
453
|
-
* @beta
|
|
454
|
-
*/
|
|
455
|
-
async function checkDeterminism(make, options) {
|
|
456
|
-
const { ticks, every = 30, from } = options;
|
|
457
|
-
if (from !== void 0 && !options.game) throw new Error("checkDeterminism: a check from a save needs the game to load it with (game)");
|
|
458
|
-
const first = await make();
|
|
459
|
-
const second = await make();
|
|
460
|
-
const saved = from === void 0 ? void 0 : await make();
|
|
461
|
-
let loaded;
|
|
462
|
-
const report = {
|
|
463
|
-
twice: null,
|
|
464
|
-
...from !== void 0 && { fromSave: null }
|
|
465
|
-
};
|
|
466
|
-
try {
|
|
467
|
-
for (let tick = 1; tick <= ticks; tick++) {
|
|
468
|
-
first.step();
|
|
469
|
-
if (!report.twice) second.step();
|
|
470
|
-
if (saved && !report.fromSave) {
|
|
471
|
-
saved.step();
|
|
472
|
-
loaded?.step();
|
|
473
|
-
if (saved.tick === from) loaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { game: options.game });
|
|
474
|
-
}
|
|
475
|
-
const whole = tick % every === 0;
|
|
476
|
-
if (!report.twice && (whole || worldFingerprint(first) !== worldFingerprint(second))) report.twice = apartAt(first.tick, compared(first), compared(second));
|
|
477
|
-
if (loaded && !report.fromSave && saved.tick > from && (whole || worldFingerprint(saved) !== worldFingerprint(loaded))) report.fromSave = apartAt(saved.tick, compared(saved), compared(loaded));
|
|
478
|
-
if (report.twice && (from === void 0 || report.fromSave)) break;
|
|
479
|
-
}
|
|
480
|
-
} finally {
|
|
481
|
-
first.dispose();
|
|
482
|
-
second.dispose();
|
|
483
|
-
saved?.dispose();
|
|
484
|
-
loaded?.dispose();
|
|
485
|
-
}
|
|
486
|
-
return report;
|
|
487
|
-
}
|
|
488
|
-
var compared = (world) => ({
|
|
489
|
-
...worldState(world),
|
|
490
|
-
owned: Object.fromEntries([...world.players.keys()].map((player) => [player, [...world.index.ownedBy(player)].map((entity) => entity.id)]))
|
|
491
|
-
});
|
|
492
|
-
/**
|
|
493
|
-
* What is looked at first: what is decided (the random state, the players, the entities, the order they are filed in)
|
|
494
|
-
* before what follows from it (the fog, which units see), so that what is said is where it began
|
|
495
|
-
*/
|
|
496
|
-
var FIRST = [
|
|
497
|
-
"tick",
|
|
498
|
-
"rng",
|
|
499
|
-
"players",
|
|
500
|
-
"entities",
|
|
501
|
-
"owned",
|
|
502
|
-
"actors"
|
|
503
|
-
];
|
|
504
|
-
var apartAt = (tick, a, b) => {
|
|
505
|
-
const ordered = (state) => ({
|
|
506
|
-
...Object.fromEntries(FIRST.map((key) => [key, state[key]])),
|
|
507
|
-
...state
|
|
508
|
-
});
|
|
509
|
-
const found = firstDifference(ordered(a), ordered(b));
|
|
510
|
-
return found ? {
|
|
511
|
-
tick,
|
|
512
|
-
...found
|
|
513
|
-
} : null;
|
|
514
|
-
};
|
|
515
|
-
//#endregion
|
|
516
|
-
export { hirerAt as _, worldHash as a, makeHero as c, hireCommand as d, learnCommand as f, hireRefusal as g, hire as h, worldFingerprint as i, buyCommand as l, sellCommand as m, firstDifference as n, worldState as o, reviveCommand as p, saveDifference as r, withHeroes as s, checkDeterminism as t, heroCommands as u };
|
|
517
|
-
|
|
518
|
-
//# sourceMappingURL=determinism-BCymQwiE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"determinism-BCymQwiE.js","names":[],"sources":["../src/packs/heroes/hire.ts","../src/packs/heroes/commands.ts","../src/packs/heroes/making.ts","../src/packs/heroes/index.ts","../src/determinism.ts"],"sourcesContent":["import { unitHired } from '#engine/engineEvents'\nimport type { Entity, PlayerId } from '#engine/entity'\nimport { heroesOf } from '#engine/hero'\nimport { atShop } from '#engine/items'\nimport { engineMessage } from '#engine/messages'\nimport { shortOf, spend } from '#engine/player'\nimport type { World } from '#engine/world'\n\n/**\n * Whether someone of a player's stands at a place that hires (`UnitTypeDef.hires`) to hire there: any unit of theirs\n * close enough, as at a shop. The first one found\n *\n * @internal\n */\nexport function hirerAt(world: World, shop: Entity, player: PlayerId): Entity | undefined {\n\tfor (const entity of world.index.ownedBy(player))\n\t\tif (entity.alive && !entity.hidden && entity.def.kind === 'unit' && atShop(entity, shop)) return entity\n\treturn undefined\n}\n\n/**\n * Why a player cannot hire a unit at a place now, as the message the player is told: none of theirs there, a hero\n * they have already (a hero is hired once), what it costs. Nothing when they can\n *\n * @internal\n */\nexport function hireRefusal(world: World, shop: Entity, unit: string, player: PlayerId) {\n\tif (!shop.def.hires?.includes(unit) || !world.registry.units.has(unit)) return engineMessage('cannotDoThat')\n\tif (!shop.alive || !shop.operational || world.areEnemies(shop.owner, player)) return engineMessage('cannotDoThat')\n\tconst def = world.registry.unit(unit)\n\tif (def.hero && heroesOf(world, player).some((hero) => hero.def.id === unit)) return engineMessage('alreadyHired', { unit })\n\tif (!hirerAt(world, shop, player)) return engineMessage('unitAtShop')\n\tconst short = shortOf(world.player(player).resources, def.cost)\n\tif (short) return engineMessage('notEnough', { resource: short })\n\treturn undefined\n}\n\n/**\n * Hires a unit at a place that hires for a player: a tavern's hero, a dock's boat. Paid for, and made next to the\n * place, a boat on the water nearest it. The unit, or nothing with the player told why\n *\n * @beta\n */\nexport function hire(world: World, shop: Entity, unit: string, player: PlayerId): Entity | undefined {\n\tconst refusal = hireRefusal(world, shop, unit, player)\n\tif (refusal) {\n\t\tworld.message(player, refusal)\n\t\treturn undefined\n\t}\n\tconst def = world.registry.unit(unit)\n\tspend(world, player, def.cost, 'hire', unit)\n\tconst hired = world.spawn(unit, player, { x: shop.pos.x, z: shop.pos.z + shop.def.radius + def.radius + 0.5 })\n\tworld.events.emit(unitHired, { shop, unit: hired, player })\n\treturn hired\n}\n","/**\n * The heroes pack's commands: buying and selling at a shop, hiring, putting a point into an ability, bringing a hero\n * back at an altar. Taken by a world whose game has the pack on (`withHeroes`); a game without it refuses them as it\n * does any command it does not know. Their type is among `Command`s, as the pack adds it (`Commands`)\n */\nimport { defineCommand, known, leastBusy, owned, producers } from '#engine/commands'\nimport { id, index, optional, string } from '#engine/fields'\nimport { learn } from '#engine/hero'\nimport { buy, sell } from '#engine/items'\nimport { enqueueRevive } from '#engine/systems/production'\nimport { hire } from './hire'\n\n/**\n * Buys from a shop, for the hero that is named, or else the one of the player that stands closest to it\n *\n * @internal\n */\nexport const buyCommand = defineCommand('buy', { shop: id, item: string, hero: optional(id) }, (world, player, command) => {\n\t// shops sell to whoever comes by, not only to their owner\n\tconst shop = known(world, player, command.shop)\n\tconst [buyer] = command.hero === undefined ? [] : owned(world, player, [command.hero])\n\tif (shop && !world.areEnemies(shop.owner, player)) buy(world, shop, command.item, player, buyer)\n})\n\n/**\n * Hires a unit at a place that hires, a tavern or a dock: someone of the player's has to be there\n *\n * @internal\n */\nexport const hireCommand = defineCommand('hire', { shop: id, unit: string }, (world, player, command) => {\n\tconst shop = known(world, player, command.shop)\n\tif (shop) hire(world, shop, command.unit, player)\n})\n\n/**\n * Gives something a hero carries back at a shop nearby, for a part of its price\n *\n * @internal\n */\nexport const sellCommand = defineCommand('sell', { entity: id, item: index }, (world, player, command) => {\n\tconst [seller] = owned(world, player, [command.entity])\n\tif (seller) sell(world, seller, command.item)\n})\n\n/**\n * Puts a point a hero has to spend into an ability\n *\n * @internal\n */\nexport const learnCommand = defineCommand('learn', { entity: id, ability: string }, (world, player, command) => {\n\tconst [hero] = owned(world, player, [command.entity])\n\tif (hero) learn(world, hero, command.ability)\n})\n\n/** @internal */\nexport const reviveCommand = defineCommand('revive', { ...producers, hero: id }, (world, player, command) => {\n\tconst building = leastBusy(world, player, command, (entity) => !!entity.def.revives)\n\tif (building) enqueueRevive(world, building, command.hero)\n})\n\n/**\n * The commands of the heroes pack (`withHeroes`): buying, hiring, selling, learning, bringing a hero back. A game\n * without the pack refuses them as it does any command it does not know\n *\n * @internal\n */\nexport const heroCommands = [buyCommand, hireCommand, sellCommand, learnCommand, reviveCommand] as const\n\ndeclare module '#engine/commands' {\n\tinterface Commands {\n\t\theroes: (typeof heroCommands)[number]\n\t}\n}\n","/**\n * What the heroes pack does as heroes are made and as things die: a hero of a hero's type made one, and the\n * experience of a kill shared out (the pack's `made` and `death` handlers)\n */\nimport type { Entity } from '#engine/entity'\nimport { grantXp, heroOf, heroState, maxLevelOf, xpWorth } from '#engine/hero'\nimport { distSq } from '#engine/math'\nimport type { World } from '#engine/world'\n\n/**\n * Makes a unit just made a hero, as its type says (`UnitTypeDef.hero`): level 1, a point to spend, the abilities it can\n * learn (none learned) and the spells it starts with, those it has not got already. What `World.spawn` does for a\n * hero's type, and `morph` for what becomes one\n *\n * @beta\n */\nexport function makeHero(world: World, entity: Entity): void {\n\tconst def = entity.def.hero\n\tif (!def) return\n\tentity.set(heroState, { level: 1, xp: 0, points: 1 })\n\t// what it has already (a unit turned into a hero, `morph`) as it was\n\tconst add = (id: string, level: number) => {\n\t\tif (!entity.abilities.some((state) => state.id === id))\n\t\t\tentity.addAbility({ id: world.registry.ability(id).id, level, cooldown: 0, autocast: false })\n\t}\n\tfor (const id of def.learns) add(id, 0)\n\tfor (const id of def.spells ?? []) add(id, 1)\n}\n\n/** Shares the experience for a kill between the heroes of the killer's side that were around */\nexport function awardKill(world: World, dead: Entity, killer: Entity | undefined): void {\n\tif (!killer || !world.areEnemies(killer.owner, dead.owner)) return\n\tconst worth = xpWorth(world, dead)\n\tif (worth <= 0) return\n\tconst heroes: Entity[] = []\n\tconst { xpRange } = world.rules.heroes\n\tfor (const player of world.players.values()) {\n\t\tif (!world.areAllies(player.id, killer.owner)) continue\n\t\tfor (const entity of world.index.with(heroState, player.id)) {\n\t\t\tif (!entity.alive || heroOf(entity)!.level >= maxLevelOf(world, entity)) continue\n\t\t\tif (distSq(entity.pos, dead.pos) <= xpRange * xpRange) heroes.push(entity)\n\t\t}\n\t}\n\tfor (const hero of heroes) grantXp(world, hero, worth / heroes.length, dead)\n}\n","import type { CommandDef } from '#engine/commands'\nimport { heroCommands } from './commands'\nimport { campHooks, campRespawnSystem } from '#engine/camps'\nimport { defineHook, type HookDef } from '#engine/hooks'\nimport { defaultHeroRules, HEROES, type HeroesPack, type HeroRules, heroOf, heroState } from '#engine/hero'\nimport { awardKill, makeHero } from './making'\nimport { shopStock } from '#engine/items'\nimport { corpseSystem, worthless } from '#engine/summons'\nimport type { System } from '#engine/registry'\nimport type { StatPart } from '#engine/stats'\nimport type { Entity } from '#engine/entity'\nimport type { World } from '#engine/world'\n\n/** A shop's wares, each as many as it stocks; what it stocked already as it was, where it sells it still */\nfunction stockShop(world: World, entity: Entity): void {\n\tconst sells = entity.def.sells ?? []\n\tconst had = entity.get(shopStock)\n\tif (!sells.length) {\n\t\tif (had) entity.remove(shopStock)\n\t\treturn\n\t}\n\tentity.set(\n\t\tshopStock,\n\t\tsells.map((item) => {\n\t\t\tconst kept = had?.find((stock) => stock.item === item)\n\t\t\tif (kept) return kept\n\t\t\tconst stock = world.registry.item(item).stock\n\t\t\treturn { item, count: stock?.max ?? 1, restock: stock?.restock ?? 60 }\n\t\t})\n\t)\n}\n\n/** What the pack does as things are made, change type, die and fall: heroes, their experience, shops' wares */\nconst heroHooks: HookDef[] = [\n\tdefineHook({\n\t\thook: 'made',\n\t\tid: 'hero',\n\t\trun(world, entity) {\n\t\t\t// a hero of a hero's type: level 1, a point to spend, what it learns\n\t\t\tif (entity.def.hero) makeHero(world, entity)\n\t\t\tstockShop(world, entity)\n\t\t}\n\t}),\n\tdefineHook({\n\t\thook: 'morphed',\n\t\tid: 'hero',\n\t\trun(world, { entity }) {\n\t\t\t// what became a hero's type is a hero from level 1; a hero that stays one keeps its level and what it learned\n\t\t\tif (entity.def.hero && !entity.has(heroState)) makeHero(world, entity)\n\t\t\t// what became a shop stocks its wares; one that sells no more has none\n\t\t\tif (entity.def.sells?.length || entity.has(shopStock)) stockShop(world, entity)\n\t\t}\n\t}),\n\tdefineHook({\n\t\thook: 'death',\n\t\tid: 'experience',\n\t\trun(world, { entity, killer }) {\n\t\t\t// an illusion gains its killer nothing\n\t\t\tif (worthless(entity)) return\n\t\t\tawardKill(world, entity, killer)\n\t\t}\n\t}),\n\tdefineHook({\n\t\thook: 'fallenHero',\n\t\tid: 'heroesStay',\n\t\trun(_world, event) {\n\t\t\t// a fallen hero waits out of the world to be brought back: at an altar, by its own time (`withRespawn`)\n\t\t\tif (event.entity.has(heroState)) event.stays = true\n\t\t}\n\t}),\n\t...campHooks\n]\n\n/**\n * A hero's stats grow with its level, as its type says (`UnitTypeDef.hero.growth`): stamped with the level past the\n * first, so that a level set however it is set is added up again\n */\nconst heroGrowth: StatPart = {\n\tid: 'heroGrowth',\n\tstamp(entity) {\n\t\tif (!entity.def.hero) return 0\n\t\tconst level = heroOf(entity)?.level ?? 1\n\t\treturn level > 1 ? level : 0\n\t},\n\tadd(_world, entity, sum) {\n\t\tconst growth = entity.def.hero?.growth\n\t\tconst hero = growth && heroOf(entity)\n\t\tif (hero && hero.level > 1) sum.add(growth, hero.level - 1)\n\t}\n}\n\n/** Camps come back as the engine's own did: in the clean-up, before the corpses go */\nconst campsComeBack: System = { ...campRespawnSystem, before: [corpseSystem.name] }\n\n/**\n * The heroes pack: what makes a game a classic hero RTS, opted into (`GameModule.packs: [withHeroes()]`). Heroes, with\n * their experience, levels, points and abilities to learn, brought back at an altar (`revive`); creeps' camps that guard\n * their ground, sleep at night and come back (`Camp.respawn`); shops that sell (`buy`, `sell`) and places that hire\n * (`hire`). `rules` change its numbers (`HeroRules`: how many heroes, the experience a level takes), the classic RTS numbers for\n * those left out. A game without it pays nothing for any of it: no hero is made of a hero's type, no command of these\n * is taken, no camp is looked at\n *\n * @beta\n */\nexport function withHeroes(rules: Partial<HeroRules> = {}): HeroesPack {\n\tfor (const key of Object.keys(rules)) if (!(key in defaultHeroRules)) throw new Error(`\"${key}\" is not a rule of the heroes pack`)\n\treturn {\n\t\tid: HEROES,\n\t\toptions: rules,\n\t\trules: () => ({ heroes: rules }),\n\t\tcommands: [...heroCommands] as unknown as CommandDef[],\n\t\tsystems: [campsComeBack],\n\t\thooks: heroHooks,\n\t\tstatParts: [heroGrowth]\n\t}\n}\n","/**\n * Whether a game comes out the same (determinism plan D1): the simulation's state as data and as a hash, and a check\n * that runs a world twice, and on from a save, and says the first tick and the first thing they differ at. What a\n * replay of commands, a save that goes on exactly and a game the same in every browser stand on\n */\nimport { type GameModule, loadWorld } from './game'\nimport { decodeSave, encodeSave, saveWorld, type WorldSave } from './save'\nimport type { Registry } from './registry'\nimport { teamMemory } from './session/memory'\nimport type { World } from './world'\nimport { fighting } from './entity'\nimport { hashText } from './math'\n\n/**\n * The simulation's state as plain data: its save, which holds all of it, but what each team's screens remember of the\n * map, which is the watchers' (`teamMemory`)\n *\n * @beta\n */\nexport function worldState(world: World): WorldSave {\n\treturn decided(saveWorld(world, { reseat: false }), world.registry)\n}\n\n/**\n * A save as what decides the game: without what each team's screens remember of the map (`teamMemory`: kept in the\n * world for who comes back, written by whoever watches it, and read by nothing that decides), and, with the rules, the\n * components nobody would have made had nobody asked for them (`unasked`)\n */\nfunction decided(save: WorldSave, registry?: Registry): WorldSave {\n\tconst { [teamMemory.id]: _memory, ...state } = save.state\n\tconst kept = (components: Record<string, unknown>) => (registry ? unasked(registry, components) : components)\n\treturn {\n\t\t...save,\n\t\tstate: kept(state),\n\t\tplayers: save.players.map((player) => ({ ...player, state: kept(player.state) })),\n\t\tentities: save.entities.map((entity) =>\n\t\t\tentity.components ? { ...entity, components: kept(entity.components as Record<string, unknown>) } : entity\n\t\t)\n\t}\n}\n\n/**\n * Where two saves of a game first differ, as `checkDeterminism` looks (what decides first: the tick, the random state,\n * the players, the entities): the path to it (`entities[id 11].pos.x`) and what each holds there, or nothing when they\n * are the same. What the screens remember of the map, and the hash of the rules they were made with, are left out;\n * with the game's `registry`, so are components that hold what they are made with (a screen asking for one makes it).\n * What a replay that came apart says at its checkpoints (`runReplay`), and `v12 save diff`\n *\n * @beta\n */\nexport function saveDifference(a: WorldSave, b: WorldSave, registry?: Registry): Difference | undefined {\n\tconst ordered = (save: WorldSave) => {\n\t\tconst { hash: _rules, ...state } = decided(save, registry)\n\t\treturn { ...Object.fromEntries(FIRST.map((key) => [key, (state as Partial<Compared>)[key]])), ...state }\n\t}\n\treturn firstDifference(ordered(a), ordered(b))\n}\n\n/**\n * Components as they would be had nobody asked for one that was not there: one that holds what its component makes\n * when asked for (its `default`) is left out. Asking makes one, and a watcher's screen asks for what it shows (a\n * player's objectives), so a world watched and the same world unwatched differ in that alone\n */\nfunction unasked(registry: Registry, components: Record<string, unknown>): Record<string, unknown> {\n\tconst kept: Record<string, unknown> = {}\n\tfor (const [id, value] of Object.entries(components)) {\n\t\tconst made = registry.component(id)?.default?.()\n\t\tif (made !== undefined && JSON.stringify(made) === JSON.stringify(value)) continue\n\t\tkept[id] = value\n\t}\n\treturn kept\n}\n\n/**\n * The simulation's state as a hash: two worlds with the same hash are, to all that is saved of them, the same. Fourteen\n * hex digits (cyrb53, of the save as JSON, but the hash of the rules, which another build of the same code writes\n * otherwise): enough to tell drift, not to stand against someone forging a state\n *\n * @beta\n */\nexport const worldHash = (world: World): string => {\n\t// the rules' own hash names the code they were built from, which another build of the same game writes otherwise\n\tconst { hash: _rules, ...state } = worldState(world)\n\treturn hashText(canonical(state))\n}\n\n/**\n * JSON with the keys of every object in order: the same state as text however it was put together (a component a\n * watcher made early comes first in its object, and later where nobody watched)\n */\nfunction canonical(value: unknown): string {\n\treturn JSON.stringify(value, (_key, each: unknown) => {\n\t\tif (!each || typeof each !== 'object' || Array.isArray(each)) return each\n\t\tconst sorted: Record<string, unknown> = {}\n\t\tfor (const key of Object.keys(each).sort()) sorted[key] = (each as Record<string, unknown>)[key]\n\t\treturn sorted\n\t})\n}\n\n/**\n * A quick hash of what a game that came apart differs in first: the tick, the random state, each player's resources,\n * upgrades and supply, and each entity's id, type, owner, place, facing, health, mana, whether it lives, its orders (how\n * many, and the first's kind and target), its buffs (which, and the time left) and its attack's cooldown and swing. Read\n * off the world as it is, with no save: 0.4 ms at 1000 units a side, where `worldHash` takes 66. What a\n * replay of commands keeps every few seconds and checks as it plays (`recordCommands`), and what `checkDeterminism`\n * compares every tick, for the tick a game came apart at; what it leaves out (components, areas, the fog) the whole\n * state, compared every so often, has\n *\n * @beta\n */\nexport function worldFingerprint(world: World): string {\n\tconst values: number[] = [world.tick, world.rng.save()]\n\tfor (const player of world.players.values()) {\n\t\tvalues.push(player.id, player.supplyUsed, player.supplyCap)\n\t\tfor (const key of Object.keys(player.resources).sort()) values.push(player.resources[key] ?? 0)\n\t\tfor (const [upgrade, level] of player.upgrades) values.push(wordOf(upgrade), level)\n\t}\n\tfor (const entity of world.entities.values()) {\n\t\tvalues.push(\n\t\t\tentity.id,\n\t\t\twordOf(entity.def.id),\n\t\t\tentity.owner,\n\t\t\tentity.pos.x,\n\t\t\tentity.pos.z,\n\t\t\tentity.facing,\n\t\t\tentity.hp,\n\t\t\tentity.mana,\n\t\t\tentity.alive ? 1 : 0\n\t\t)\n\t\tconst order = entity.orders[0]\n\t\tvalues.push(entity.orders.length, order ? wordOf(order.type) : 0, order?.init.target ?? 0)\n\t\tvalues.push(entity.buffs.length)\n\t\tfor (const buff of entity.buffs) values.push(wordOf(buff.id), buff.remaining)\n\t\tif (entity.get(fighting)) values.push(entity.get(fighting)!.cooldown, entity.get(fighting)!.swing)\n\t}\n\treturn hashWords(new Uint32Array(Float64Array.from(values).buffer))\n}\n\n/** A short text as a number, for the fingerprint: FNV-1a of its characters */\nfunction wordOf(text: string): number {\n\tlet h = 0x811c9dc5\n\tfor (let i = 0; i < text.length; i++) h = Math.imul(h ^ text.charCodeAt(i), 16777619)\n\treturn h >>> 0\n}\n\n/** cyrb53 of 32-bit words: the bits of numbers, hashed as they are */\nfunction hashWords(words: Uint32Array): string {\n\tlet h1 = 0xdeadbeef\n\tlet h2 = 0x41c6ce57\n\tfor (const word of words) {\n\t\th1 = Math.imul(h1 ^ word, 2654435761)\n\t\th2 = Math.imul(h2 ^ word, 1597334677)\n\t}\n\th1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909)\n\th2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909)\n\treturn (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(14, '0')\n}\n\n/**\n * Where two states first differ: the path to it (`entities[id 11].pos.x`) and what each holds there. Nothing when they\n * are the same. Lists of things with an `id` are named by it, the rest by their place\n *\n * @beta\n */\nexport function firstDifference(a: unknown, b: unknown, path = ''): Difference | undefined {\n\tif (Object.is(a, b)) return undefined\n\tif (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null || Array.isArray(a) !== Array.isArray(b)) return { path, a, b }\n\tif (Array.isArray(a) && Array.isArray(b)) {\n\t\tfor (let i = 0; i < Math.max(a.length, b.length); i++) {\n\t\t\tconst each = a[i] ?? b[i]\n\t\t\tconst named = each && typeof each === 'object' && 'id' in each ? `[id ${String((each as { id: unknown }).id)}]` : `[${i}]`\n\t\t\tconst found = firstDifference(a[i], b[i], `${path}${named}`)\n\t\t\tif (found) return found\n\t\t}\n\t\treturn undefined\n\t}\n\tconst keys = new Set([...Object.keys(a), ...Object.keys(b)])\n\tfor (const key of keys) {\n\t\tconst found = firstDifference((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key], path ? `${path}.${key}` : key)\n\t\tif (found) return found\n\t}\n\treturn undefined\n}\n\n/**\n * Where two states differ (`firstDifference`)\n *\n * @beta\n */\nexport interface Difference {\n\t/** The path to it in the state: `entities[id 11].pos.x` */\n\tpath: string\n\t/** What the first holds there */\n\ta: unknown\n\t/** What the second holds there */\n\tb: unknown\n}\n\n/**\n * Where two runs of a game came apart: the first tick they were looked at and differed, and what differed first\n *\n * @beta\n */\nexport interface Apart extends Difference {\n\t/** The tick they were looked at and differed */\n\ttick: number\n}\n\n/**\n * How a game is checked for coming out the same (`checkDeterminism`)\n *\n * @beta\n */\nexport interface DeterminismOptions {\n\t/** How many ticks each world runs */\n\tticks: number\n\t/**\n\t * How often their whole state is compared, in ticks: every 30 when left out. Their fingerprints\n\t * (`worldFingerprint`) are compared every tick, and the whole state at once where those differ, so that the tick\n\t * said is the one they came apart at\n\t */\n\tevery?: number\n\t/**\n\t * A tick to save a third world at, and load a fourth from that save (`loadWorld`, with `game`): the game saved and\n\t * the game loaded are run on side by side and compared. Not done when left out\n\t */\n\tfrom?: number\n\t/** The game the save is loaded with, for `from` */\n\tgame?: GameModule\n}\n\n/**\n * What the check found: for each run, where it came apart from the first, or `null` for the same to the last tick\n *\n * @beta\n */\nexport interface DeterminismReport {\n\t/** A second world made the same way and run the same */\n\ttwice: Apart | null\n\t/** A world loaded from a save taken at `from`, beside the world the save was taken of: none when `from` was not said */\n\tfromSave?: Apart | null\n}\n\n/**\n * Makes a world twice with `make` (the same seed, the same commands given in it, as a replay would) and runs them side\n * by side, comparing their fingerprints every tick and their states (and the order each player's entities are filed\n * in) every `every` ticks; with `from`, a third is saved at that tick and a fourth loaded\n * from the save, and the two run on side by side. Says, for each, the first tick and thing it differs at, or that it does not. A test of a game's\n * own systems: one that reads `Math.random`, the clock, or the order of something unordered is found here\n *\n * const report = await checkDeterminism(() => makeMyGame(1), { ticks: 1800, from: 300, game: rules })\n * expect(report).toEqual({ twice: null, fromSave: null })\n *\n * @beta\n */\nexport async function checkDeterminism(make: () => World | Promise<World>, options: DeterminismOptions): Promise<DeterminismReport> {\n\tconst { ticks, every = 30, from } = options\n\tif (from !== undefined && !options.game) throw new Error('checkDeterminism: a check from a save needs the game to load it with (game)')\n\tconst first = await make()\n\tconst second = await make()\n\t// the game that is saved at `from` and goes on, and the game loaded from that save beside it\n\tconst saved = from === undefined ? undefined : await make()\n\tlet loaded: World | undefined\n\tconst report: DeterminismReport = { twice: null, ...(from !== undefined && { fromSave: null }) }\n\ttry {\n\t\tfor (let tick = 1; tick <= ticks; tick++) {\n\t\t\tfirst.step()\n\t\t\tif (!report.twice) second.step()\n\t\t\tif (saved && !report.fromSave) {\n\t\t\t\tsaved.step()\n\t\t\t\tloaded?.step()\n\t\t\t\tif (saved.tick === from) {\n\t\t\t\t\t// as a file keeps it (`encodeSave`): what a save cannot hold is lost here as it would be there\n\t\t\t\t\tloaded = await loadWorld(decodeSave(encodeSave(saveWorld(saved))), { game: options.game! })\n\t\t\t\t}\n\t\t\t}\n\t\t\t// the fingerprint every tick, for the tick they came apart at; the whole state every `every`, and at once where\n\t\t\t// the fingerprints differ, for what it is\n\t\t\tconst whole = tick % every === 0\n\t\t\tif (!report.twice && (whole || worldFingerprint(first) !== worldFingerprint(second)))\n\t\t\t\treport.twice = apartAt(first.tick, compared(first), compared(second))\n\t\t\tconst going = loaded && !report.fromSave && saved!.tick > from!\n\t\t\tif (going && (whole || worldFingerprint(saved!) !== worldFingerprint(loaded!)))\n\t\t\t\treport.fromSave = apartAt(saved!.tick, compared(saved!), compared(loaded!))\n\t\t\tif (report.twice && (from === undefined || report.fromSave)) break\n\t\t}\n\t} finally {\n\t\tfirst.dispose()\n\t\tsecond.dispose()\n\t\tsaved?.dispose()\n\t\tloaded?.dispose()\n\t}\n\treturn report\n}\n\n/**\n * What is compared of a world: its state (`worldState`), and the order its index gives each player's entities in\n * (`world.index.ownedBy`), which a save does not hold and which decides what is picked first among equals (the closest\n * drop-off, a shopper, who shares the experience): a world loaded from a save has to give them in the same order\n */\ntype Compared = WorldSave & { owned: Record<number, number[]> }\n\nconst compared = (world: World): Compared => ({\n\t...worldState(world),\n\towned: Object.fromEntries([...world.players.keys()].map((player) => [player, [...world.index.ownedBy(player)].map((entity) => entity.id)]))\n})\n\n/**\n * What is looked at first: what is decided (the random state, the players, the entities, the order they are filed in)\n * before what follows from it (the fog, which units see), so that what is said is where it began\n */\nconst FIRST: (keyof Compared)[] = ['tick', 'rng', 'players', 'entities', 'owned', 'actors']\n\nconst apartAt = (tick: number, a: Compared, b: Compared): Apart | null => {\n\tconst ordered = (state: Compared) => ({ ...Object.fromEntries(FIRST.map((key) => [key, state[key]])), ...state })\n\tconst found = firstDifference(ordered(a), ordered(b))\n\treturn found ? { tick, ...found } : null\n}\n"],"mappings":"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"}
|