@v12-engine/engine 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abilities/amounts.d.ts +28 -0
- package/dist/abilities/amounts.js +74 -0
- package/dist/abilities/amounts.js.map +1 -0
- package/dist/abilities/buffs.d.ts +106 -6
- package/dist/abilities/buffs.js +443 -0
- package/dist/abilities/buffs.js.map +1 -0
- package/dist/abilities/castTold.d.ts +2 -0
- package/dist/abilities/castTold.js +66 -0
- package/dist/abilities/castTold.js.map +1 -0
- package/dist/abilities/chance.d.ts +38 -0
- package/dist/abilities/chance.js +77 -0
- package/dist/abilities/chance.js.map +1 -0
- package/dist/abilities/charges.d.ts +18 -0
- package/dist/abilities/charges.js +101 -0
- package/dist/abilities/charges.js.map +1 -0
- package/dist/abilities/control.d.ts +28 -0
- package/dist/abilities/control.js +113 -0
- package/dist/abilities/control.js.map +1 -0
- package/dist/abilities/dispel.js +51 -0
- package/dist/abilities/dispel.js.map +1 -0
- package/dist/abilities/effectFields.d.ts +1 -1
- package/dist/abilities/effectFields.js +676 -0
- package/dist/abilities/effectFields.js.map +1 -0
- package/dist/abilities/effectIndex.d.ts +27 -0
- package/dist/abilities/effectIndex.js +64 -0
- package/dist/abilities/effectIndex.js.map +1 -0
- package/dist/abilities/effects/buff.d.ts +9 -3
- package/dist/abilities/effects/buff.js +84 -0
- package/dist/abilities/effects/buff.js.map +1 -0
- package/dist/abilities/effects/conditions.d.ts +2 -0
- package/dist/abilities/effects/conditions.js +41 -0
- package/dist/abilities/effects/conditions.js.map +1 -0
- package/dist/abilities/effects/core.js +54 -0
- package/dist/abilities/effects/core.js.map +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -1
- package/dist/abilities/effects/damage.js +43 -0
- package/dist/abilities/effects/damage.js.map +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -2
- package/dist/abilities/effects/heal.js +51 -0
- package/dist/abilities/effects/heal.js.map +1 -0
- package/dist/abilities/effects/missile.d.ts +13 -1
- package/dist/abilities/effects/missile.js +104 -0
- package/dist/abilities/effects/missile.js.map +1 -0
- package/dist/abilities/effects/morph.d.ts +5 -0
- package/dist/abilities/effects/morph.js +43 -0
- package/dist/abilities/effects/morph.js.map +1 -0
- package/dist/abilities/effects/moves.d.ts +16 -4
- package/dist/abilities/effects/moves.js +212 -0
- package/dist/abilities/effects/moves.js.map +1 -0
- package/dist/abilities/effects/passives.d.ts +19 -9
- package/dist/abilities/effects/passives.js +131 -0
- package/dist/abilities/effects/passives.js.map +1 -0
- package/dist/abilities/effects/proxy.d.ts +5 -0
- package/dist/abilities/effects/proxy.js +60 -0
- package/dist/abilities/effects/proxy.js.map +1 -0
- package/dist/abilities/effects/sight.d.ts +2 -2
- package/dist/abilities/effects/sight.js +39 -0
- package/dist/abilities/effects/sight.js.map +1 -0
- package/dist/abilities/effects/spawn.d.ts +5 -2
- package/dist/abilities/effects/spawn.js +40 -0
- package/dist/abilities/effects/spawn.js.map +1 -0
- package/dist/abilities/effects/timed.d.ts +2 -2
- package/dist/abilities/effects/timed.js +96 -0
- package/dist/abilities/effects/timed.js.map +1 -0
- package/dist/abilities/effects/trade.d.ts +1 -1
- package/dist/abilities/effects/trade.js +25 -0
- package/dist/abilities/effects/trade.js.map +1 -0
- package/dist/abilities/effects.d.ts +97 -23
- package/dist/abilities/effects.js +860 -0
- package/dist/abilities/effects.js.map +1 -0
- package/dist/abilities/land.d.ts +38 -4
- package/dist/abilities/land.js +189 -0
- package/dist/abilities/land.js.map +1 -0
- package/dist/abilities/recast.d.ts +45 -0
- package/dist/abilities/recast.js +118 -0
- package/dist/abilities/recast.js.map +1 -0
- package/dist/abilities/scaled.js +40 -0
- package/dist/abilities/scaled.js.map +1 -0
- package/dist/abilities/screen.d.ts +6 -0
- package/dist/abilities/screen.js +83 -0
- package/dist/abilities/screen.js.map +1 -0
- package/dist/abilities/shapes.d.ts +66 -0
- package/dist/abilities/shapes.js +122 -0
- package/dist/abilities/shapes.js.map +1 -0
- package/dist/abilities/text.d.ts +14 -2
- package/dist/abilities/text.js +204 -0
- package/dist/abilities/text.js.map +1 -0
- package/dist/abilities/triggers.d.ts +98 -0
- package/dist/abilities/triggers.js +351 -0
- package/dist/abilities/triggers.js.map +1 -0
- package/dist/abilityChanges.d.ts +131 -0
- package/dist/abilityChanges.js +345 -0
- package/dist/abilityChanges.js.map +1 -0
- package/dist/ai/area.d.ts +4 -1
- package/dist/ai/brain.d.ts +4 -1
- package/dist/ai/brain.js +844 -0
- package/dist/ai/brain.js.map +1 -0
- package/dist/ai/budget.js +74 -0
- package/dist/ai/budget.js.map +1 -0
- package/dist/ai/checks.d.ts +9 -1
- package/dist/ai/checks.js +242 -0
- package/dist/ai/checks.js.map +1 -0
- package/dist/ai/computer.d.ts +11 -4
- package/dist/ai/computer.js +251 -0
- package/dist/ai/computer.js.map +1 -0
- package/dist/ai/defence.d.ts +4 -0
- package/dist/ai/defence.js +430 -0
- package/dist/ai/defence.js.map +1 -0
- package/dist/ai/define.d.ts +3 -2
- package/dist/ai/define.js +31 -0
- package/dist/ai/define.js.map +1 -0
- package/dist/ai/economy.d.ts +10 -7
- package/dist/ai/economy.js +780 -0
- package/dist/ai/economy.js.map +1 -0
- package/dist/ai/geometry.js +38 -0
- package/dist/ai/geometry.js.map +1 -0
- package/dist/ai/goals.d.ts +1 -0
- package/dist/ai/goals.js +560 -0
- package/dist/ai/goals.js.map +1 -0
- package/dist/ai/knowledge.d.ts +72 -7
- package/dist/ai/knowledge.js +804 -0
- package/dist/ai/knowledge.js.map +1 -0
- package/dist/ai/lanes.d.ts +10 -2
- package/dist/ai/lanes.js +715 -0
- package/dist/ai/lanes.js.map +1 -0
- package/dist/ai/melee/build.js +264 -0
- package/dist/ai/melee/build.js.map +1 -0
- package/dist/ai/melee/goals.d.ts +7 -0
- package/dist/ai/melee/goals.js +720 -0
- package/dist/ai/melee/goals.js.map +1 -0
- package/dist/ai/melee/heroes.js +68 -0
- package/dist/ai/melee/heroes.js.map +1 -0
- package/dist/ai/melee/index.d.ts +1 -1
- package/dist/ai/melee/index.js +51 -0
- package/dist/ai/melee/index.js.map +1 -0
- package/dist/ai/melee/production.js +29 -0
- package/dist/ai/melee/production.js.map +1 -0
- package/dist/ai/melee/surrender.js +64 -0
- package/dist/ai/melee/surrender.js.map +1 -0
- package/dist/ai/micro.d.ts +9 -0
- package/dist/ai/micro.js +1316 -0
- package/dist/ai/micro.js.map +1 -0
- package/dist/ai/mission.d.ts +9 -2
- package/dist/ai/mission.js +538 -0
- package/dist/ai/mission.js.map +1 -0
- package/dist/ai/missionRules.d.ts +1 -1
- package/dist/ai/missionRules.js +26 -0
- package/dist/ai/missionRules.js.map +1 -0
- package/dist/ai/module.d.ts +6 -2
- package/dist/ai/module.js +37 -0
- package/dist/ai/module.js.map +1 -0
- package/dist/ai/options.d.ts +3 -3
- package/dist/ai/plans/build.d.ts +20 -1
- package/dist/ai/plans/build.js +608 -0
- package/dist/ai/plans/build.js.map +1 -0
- package/dist/ai/plans/placement.d.ts +4 -1
- package/dist/ai/plans/placement.js +295 -0
- package/dist/ai/plans/placement.js.map +1 -0
- package/dist/ai/plans/plans.d.ts +9 -0
- package/dist/ai/plans/plans.js +110 -0
- package/dist/ai/plans/plans.js.map +1 -0
- package/dist/ai/plans/production.d.ts +14 -2
- package/dist/ai/plans/production.js +434 -0
- package/dist/ai/plans/production.js.map +1 -0
- package/dist/ai/plans/purse.d.ts +6 -3
- package/dist/ai/plans/purse.js +139 -0
- package/dist/ai/plans/purse.js.map +1 -0
- package/dist/ai/plans/tech.d.ts +6 -0
- package/dist/ai/plans/tech.js +122 -0
- package/dist/ai/plans/tech.js.map +1 -0
- package/dist/ai/profiles.d.ts +4 -4
- package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
- package/dist/ai/profiles.js.map +1 -0
- package/dist/ai/reach.js +54 -0
- package/dist/ai/reach.js.map +1 -0
- package/dist/ai/report.d.ts +8 -0
- package/dist/ai/report.js +87 -0
- package/dist/ai/report.js.map +1 -0
- package/dist/ai/roles.d.ts +4 -0
- package/dist/ai/roles.js +207 -0
- package/dist/ai/roles.js.map +1 -0
- package/dist/ai/rules.d.ts +8 -2
- package/dist/ai/rules.js +416 -0
- package/dist/ai/rules.js.map +1 -0
- package/dist/ai/scouting.d.ts +6 -0
- package/dist/ai/scouting.js +324 -0
- package/dist/ai/scouting.js.map +1 -0
- package/dist/ai/settings.js +99 -0
- package/dist/ai/settings.js.map +1 -0
- package/dist/ai/squads.d.ts +21 -2
- package/dist/ai/squads.js +916 -0
- package/dist/ai/squads.js.map +1 -0
- package/dist/ai/strength.js +320 -0
- package/dist/ai/strength.js.map +1 -0
- package/dist/ai/task.d.ts +3 -1
- package/dist/ai/task.js +17 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tasks/attack.js +24 -0
- package/dist/ai/tasks/attack.js.map +1 -0
- package/dist/ai/tasks/capture.d.ts +3 -3
- package/dist/ai/tasks/capture.js +37 -0
- package/dist/ai/tasks/capture.js.map +1 -0
- package/dist/ai/tasks/creep.js +29 -0
- package/dist/ai/tasks/creep.js.map +1 -0
- package/dist/ai/tasks/defend.js +61 -0
- package/dist/ai/tasks/defend.js.map +1 -0
- package/dist/ai/tasks/drop.js +81 -0
- package/dist/ai/tasks/drop.js.map +1 -0
- package/dist/ai/tasks/escort.js +59 -0
- package/dist/ai/tasks/escort.js.map +1 -0
- package/dist/ai/tasks/gather.js +48 -0
- package/dist/ai/tasks/gather.js.map +1 -0
- package/dist/ai/tasks/harass.js +39 -0
- package/dist/ai/tasks/harass.js.map +1 -0
- package/dist/ai/tasks/hold.js +32 -0
- package/dist/ai/tasks/hold.js.map +1 -0
- package/dist/ai/tasks/index.js +34 -0
- package/dist/ai/tasks/index.js.map +1 -0
- package/dist/ai/tasks/move.js +26 -0
- package/dist/ai/tasks/move.js.map +1 -0
- package/dist/ai/tasks/patrol.js +59 -0
- package/dist/ai/tasks/patrol.js.map +1 -0
- package/dist/ai/tasks/retreat.js +28 -0
- package/dist/ai/tasks/retreat.js.map +1 -0
- package/dist/ai/tasks/scout.js +73 -0
- package/dist/ai/tasks/scout.js.map +1 -0
- package/dist/ai/tasks/shared.d.ts +1 -1
- package/dist/ai/tasks/shared.js +137 -0
- package/dist/ai/tasks/shared.js.map +1 -0
- package/dist/ai/team.d.ts +18 -1
- package/dist/ai/team.js +492 -0
- package/dist/ai/team.js.map +1 -0
- package/dist/ai/threat.d.ts +6 -0
- package/dist/ai/threat.js +206 -0
- package/dist/ai/threat.js.map +1 -0
- package/dist/ai/view.d.ts +21 -7
- package/dist/ai/view.js +677 -0
- package/dist/ai/view.js.map +1 -0
- package/dist/ai/waves.d.ts +6 -0
- package/dist/ai/waves.js +410 -0
- package/dist/ai/waves.js.map +1 -0
- package/dist/ai.js +54 -6239
- package/dist/aiTesting.d.ts +6 -3
- package/dist/aiTesting.js +229 -0
- package/dist/aiTesting.js.map +1 -0
- package/dist/areas.d.ts +4 -1
- package/dist/areas.js +295 -0
- package/dist/areas.js.map +1 -0
- package/dist/attacks.d.ts +3 -3
- package/dist/attacks.js +127 -0
- package/dist/attacks.js.map +1 -0
- package/dist/burning.d.ts +267 -0
- package/dist/burning.js +795 -0
- package/dist/burning.js.map +1 -0
- package/dist/bytes.js +21 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callings.d.ts +71 -0
- package/dist/callings.js +157 -0
- package/dist/callings.js.map +1 -0
- package/dist/cameraOrders.d.ts +78 -0
- package/dist/cameraOrders.js +114 -0
- package/dist/cameraOrders.js.map +1 -0
- package/dist/camps.d.ts +70 -4
- package/dist/camps.js +501 -0
- package/dist/camps.js.map +1 -0
- package/dist/capture.d.ts +15 -3
- package/dist/capture.js +304 -0
- package/dist/capture.js.map +1 -0
- package/dist/cellLayers.d.ts +78 -13
- package/dist/cellLayers.js +275 -0
- package/dist/cellLayers.js.map +1 -0
- package/dist/cellPatches.d.ts +24 -0
- package/dist/cellPatches.js +73 -0
- package/dist/cellPatches.js.map +1 -0
- package/dist/cinematics.d.ts +10 -5
- package/dist/cinematics.js +161 -0
- package/dist/cinematics.js.map +1 -0
- package/dist/clock.d.ts +2 -2
- package/dist/clock.js +78 -0
- package/dist/clock.js.map +1 -0
- package/dist/commands.d.ts +36 -4
- package/dist/commands.js +636 -0
- package/dist/commands.js.map +1 -0
- package/dist/components.d.ts +31 -10
- package/dist/components.js +74 -0
- package/dist/components.js.map +1 -0
- package/dist/computers.d.ts +4 -4
- package/dist/computers.js +194 -0
- package/dist/computers.js.map +1 -0
- package/dist/concealment.d.ts +25 -2
- package/dist/concealment.js +409 -0
- package/dist/concealment.js.map +1 -0
- package/dist/coreComponents.js +130 -0
- package/dist/coreComponents.js.map +1 -0
- package/dist/createGame.d.ts +306 -0
- package/dist/createGame.js +405 -0
- package/dist/createGame.js.map +1 -0
- package/dist/dashing.d.ts +18 -2
- package/dist/dashing.js +41 -0
- package/dist/dashing.js.map +1 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +5 -3
- package/dist/debug2.js +76 -0
- package/dist/debug2.js.map +1 -0
- package/dist/debugCommands.d.ts +6 -6
- package/dist/debugCommands.js +537 -0
- package/dist/debugCommands.js.map +1 -0
- package/dist/debugging.d.ts +1 -0
- package/dist/defaultSets.d.ts +183 -0
- package/dist/defaultSets.js +216 -0
- package/dist/defaultSets.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.js +78 -0
- package/dist/definitions.js.map +1 -0
- package/dist/defs.d.ts +1895 -165
- package/dist/defs.js +380 -0
- package/dist/defs.js.map +1 -0
- package/dist/denying.d.ts +4 -4
- package/dist/denying.js +106 -0
- package/dist/denying.js.map +1 -0
- package/dist/destructibles.d.ts +2 -2
- package/dist/destructibles.js +36 -0
- package/dist/destructibles.js.map +1 -0
- package/dist/determinism.d.ts +4 -4
- package/dist/determinism.js +247 -0
- package/dist/determinism.js.map +1 -0
- package/dist/dialog.d.ts +17 -2
- package/dist/dialog.js +108 -0
- package/dist/dialog.js.map +1 -0
- package/dist/effectRefs.js +28 -0
- package/dist/effectRefs.js.map +1 -0
- package/dist/effects.d.ts +27 -11
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/endings.d.ts +1 -1
- package/dist/endings.js +78 -0
- package/dist/endings.js.map +1 -0
- package/dist/engagement.d.ts +40 -6
- package/dist/engagement.js +530 -0
- package/dist/engagement.js.map +1 -0
- package/dist/engineEvents.d.ts +72 -9
- package/dist/engineEvents.js +520 -0
- package/dist/engineEvents.js.map +1 -0
- package/dist/entity.d.ts +275 -26
- package/dist/entity.js +441 -0
- package/dist/entity.js.map +1 -0
- package/dist/entityIndex.d.ts +10 -3
- package/dist/entityIndex.js +149 -0
- package/dist/entityIndex.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +11 -5
- package/dist/events.js +158 -0
- package/dist/events.js.map +1 -0
- package/dist/exactMath.js +273 -0
- package/dist/exactMath.js.map +1 -0
- package/dist/features.d.ts +1 -1
- package/dist/features.js +127 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +25 -5
- package/dist/fields.js +140 -0
- package/dist/fields.js.map +1 -0
- package/dist/fixture.d.ts +3 -3
- package/dist/fixture.js +512 -0
- package/dist/fixture.js.map +1 -0
- package/dist/fog.d.ts +26 -3
- package/dist/fog.js +333 -0
- package/dist/fog.js.map +1 -0
- package/dist/foliage.d.ts +476 -0
- package/dist/foliage.js +1478 -0
- package/dist/foliage.js.map +1 -0
- package/dist/foliageDebug.d.ts +57 -0
- package/dist/foliageDebug.js +172 -0
- package/dist/foliageDebug.js.map +1 -0
- package/dist/foliageRegrowth.d.ts +20 -0
- package/dist/foliageRegrowth.js +332 -0
- package/dist/foliageRegrowth.js.map +1 -0
- package/dist/formState.d.ts +67 -0
- package/dist/formState.js +65 -0
- package/dist/formState.js.map +1 -0
- package/dist/formation.d.ts +46 -8
- package/dist/formation.js +297 -0
- package/dist/formation.js.map +1 -0
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +146 -0
- package/dist/forms.js.map +1 -0
- package/dist/friendlyFire.d.ts +2 -2
- package/dist/friendlyFire.js +37 -0
- package/dist/friendlyFire.js.map +1 -0
- package/dist/game.d.ts +141 -48
- package/dist/game.js +834 -0
- package/dist/game.js.map +1 -0
- package/dist/gameData.d.ts +96 -22
- package/dist/gameData.js +1690 -0
- package/dist/gameData.js.map +1 -0
- package/dist/gameFiles.d.ts +3 -3
- package/dist/gameFiles.js +14 -0
- package/dist/gameFiles.js.map +1 -0
- package/dist/gates.js +92 -0
- package/dist/gates.js.map +1 -0
- package/dist/generate.d.ts +28 -1
- package/dist/generate.js +1062 -0
- package/dist/generate.js.map +1 -0
- package/dist/generateWorker.d.ts +7 -3
- package/dist/generateWorker.js +86 -0
- package/dist/generateWorker.js.map +1 -0
- package/dist/grid.d.ts +9 -0
- package/dist/grid.js +102 -0
- package/dist/grid.js.map +1 -0
- package/dist/ground.d.ts +17 -1
- package/dist/ground.js +375 -0
- package/dist/ground.js.map +1 -0
- package/dist/groundObjects.d.ts +70 -0
- package/dist/groundObjects.js +371 -0
- package/dist/groundObjects.js.map +1 -0
- package/dist/groundSpeed.d.ts +20 -3
- package/dist/groundSpeed.js +117 -0
- package/dist/groundSpeed.js.map +1 -0
- package/dist/hero.d.ts +126 -10
- package/dist/hero.js +432 -0
- package/dist/hero.js.map +1 -0
- package/dist/holds.d.ts +94 -0
- package/dist/holds.js +305 -0
- package/dist/holds.js.map +1 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.js +30 -0
- package/dist/home.js.map +1 -0
- package/dist/hooks.d.ts +339 -57
- package/dist/hooks.js +105 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hotReload.d.ts +6 -5
- package/dist/hotReload.js +145 -0
- package/dist/hotReload.js.map +1 -0
- package/dist/ids.d.ts +3 -3
- package/dist/ids.js +30 -0
- package/dist/ids.js.map +1 -0
- package/dist/idsFile.d.ts +36 -0
- package/dist/idsFile.js +134 -0
- package/dist/idsFile.js.map +1 -0
- package/dist/index.d.ts +105 -68
- package/dist/index.js +194 -4701
- package/dist/inspect.d.ts +29 -2
- package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
- package/dist/inspect.js.map +1 -0
- package/dist/inventory.d.ts +14 -1
- package/dist/inventory.js +84 -0
- package/dist/inventory.js.map +1 -0
- package/dist/items.d.ts +136 -8
- package/dist/items.js +585 -0
- package/dist/items.js.map +1 -0
- package/dist/lanes.d.ts +12 -3
- package/dist/lanes.js +496 -0
- package/dist/lanes.js.map +1 -0
- package/dist/life.d.ts +6 -2
- package/dist/life.js +287 -0
- package/dist/life.js.map +1 -0
- package/dist/log.d.ts +26 -3
- package/dist/log.js +192 -0
- package/dist/log.js.map +1 -0
- package/dist/manaBurn.d.ts +2 -2
- package/dist/manaBurn.js +75 -0
- package/dist/manaBurn.js.map +1 -0
- package/dist/map/file.d.ts +56 -3
- package/dist/map/file.js +264 -0
- package/dist/map/file.js.map +1 -0
- package/dist/map/images.js +61 -0
- package/dist/map/images.js.map +1 -0
- package/dist/map/look.d.ts +1 -1
- package/dist/map/look.js +30 -0
- package/dist/map/look.js.map +1 -0
- package/dist/map/pathProfile.js +183 -0
- package/dist/map/pathProfile.js.map +1 -0
- package/dist/map/resize.d.ts +4 -0
- package/dist/map/resize.js +136 -0
- package/dist/map/resize.js.map +1 -0
- package/dist/map/schema.js +257 -0
- package/dist/map/schema.js.map +1 -0
- package/dist/map/terrain.js +214 -0
- package/dist/map/terrain.js.map +1 -0
- package/dist/map/types.d.ts +92 -13
- package/dist/map/types.js +251 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mapCheck/cells.js +94 -0
- package/dist/mapCheck/cells.js.map +1 -0
- package/dist/mapCheck/rules/foliage.d.ts +9 -0
- package/dist/mapCheck/rules/foliage.js +83 -0
- package/dist/mapCheck/rules/foliage.js.map +1 -0
- package/dist/mapCheck/rules/names.js +39 -0
- package/dist/mapCheck/rules/names.js.map +1 -0
- package/dist/mapCheck/rules/objects.d.ts +1 -1
- package/dist/mapCheck/rules/objects.js +56 -0
- package/dist/mapCheck/rules/objects.js.map +1 -0
- package/dist/mapCheck/rules/paths.js +32 -0
- package/dist/mapCheck/rules/paths.js.map +1 -0
- package/dist/mapCheck/rules/players.js +20 -0
- package/dist/mapCheck/rules/players.js.map +1 -0
- package/dist/mapCheck/rules/races.js +56 -0
- package/dist/mapCheck/rules/races.js.map +1 -0
- package/dist/mapCheck/rules/random.js +47 -0
- package/dist/mapCheck/rules/random.js.map +1 -0
- package/dist/mapCheck/rules/regions.js +30 -0
- package/dist/mapCheck/rules/regions.js.map +1 -0
- package/dist/mapCheck/rules/targets.js +31 -0
- package/dist/mapCheck/rules/targets.js.map +1 -0
- package/dist/mapCheck/rules/walking.js +45 -0
- package/dist/mapCheck/rules/walking.js.map +1 -0
- package/dist/mapCheck.d.ts +2 -2
- package/dist/mapCheck.js +63 -0
- package/dist/mapCheck.js.map +1 -0
- package/dist/mapFields.d.ts +25 -2
- package/dist/mapFields.js +134 -0
- package/dist/mapFields.js.map +1 -0
- package/dist/mapFile.js +176 -0
- package/dist/mapFile.js.map +1 -0
- package/dist/mapMeasure.d.ts +8 -0
- package/dist/mapMeasure.js +283 -0
- package/dist/mapMeasure.js.map +1 -0
- package/dist/mapMerge.d.ts +1 -0
- package/dist/mapMerge.js +172 -0
- package/dist/mapMerge.js.map +1 -0
- package/dist/mapObjectives.js +138 -0
- package/dist/mapObjectives.js.map +1 -0
- package/dist/mapObjects.js +80 -0
- package/dist/mapObjects.js.map +1 -0
- package/dist/math.d.ts +37 -7
- package/dist/math.js +155 -0
- package/dist/math.js.map +1 -0
- package/dist/messages.d.ts +71 -4
- package/dist/messages.js +29 -0
- package/dist/messages.js.map +1 -0
- package/dist/missionRules.d.ts +10 -2
- package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
- package/dist/missionRules.js.map +1 -0
- package/dist/mods.d.ts +39 -20
- package/dist/mods.js +271 -0
- package/dist/mods.js.map +1 -0
- package/dist/moves.d.ts +87 -0
- package/dist/moves.js +539 -0
- package/dist/moves.js.map +1 -0
- package/dist/names.d.ts +7 -0
- package/dist/names.js +122 -0
- package/dist/names.js.map +1 -0
- package/dist/navigation/agentParams.js +14 -0
- package/dist/navigation/agentParams.js.map +1 -0
- package/dist/navigation/air.d.ts +7 -3
- package/dist/navigation/air.js +401 -0
- package/dist/navigation/air.js.map +1 -0
- package/dist/navigation/builds.d.ts +34 -2
- package/dist/navigation/builds.js +287 -0
- package/dist/navigation/builds.js.map +1 -0
- package/dist/navigation/groundAreas.d.ts +59 -1
- package/dist/navigation/groundAreas.js +407 -0
- package/dist/navigation/groundAreas.js.map +1 -0
- package/dist/navigation/navigation.d.ts +98 -9
- package/dist/navigation/recast.d.ts +194 -18
- package/dist/navigation/recast.js +1379 -0
- package/dist/navigation/recast.js.map +1 -0
- package/dist/navigation/sidePaths.d.ts +8 -3
- package/dist/navigation/sidePaths.js +241 -0
- package/dist/navigation/sidePaths.js.map +1 -0
- package/dist/navigation/sized.js +243 -0
- package/dist/navigation/sized.js.map +1 -0
- package/dist/nearest.js +32 -0
- package/dist/nearest.js.map +1 -0
- package/dist/noise.js +59 -0
- package/dist/noise.js.map +1 -0
- package/dist/objectives.d.ts +12 -3
- package/dist/objectives.js +144 -0
- package/dist/objectives.js.map +1 -0
- package/dist/orders/basic.d.ts +5 -5
- package/dist/orders/basic.js +417 -0
- package/dist/orders/basic.js.map +1 -0
- package/dist/orders/build.js +278 -0
- package/dist/orders/build.js.map +1 -0
- package/dist/orders/cast.d.ts +13 -3
- package/dist/orders/cast.js +558 -0
- package/dist/orders/cast.js.map +1 -0
- package/dist/orders/facts.js +16 -0
- package/dist/orders/facts.js.map +1 -0
- package/dist/orders/harvest.d.ts +21 -5
- package/dist/orders/harvest.js +540 -0
- package/dist/orders/harvest.js.map +1 -0
- package/dist/orders/idle.d.ts +3 -1
- package/dist/orders/idle.js +234 -0
- package/dist/orders/idle.js.map +1 -0
- package/dist/orders/items.js +92 -0
- package/dist/orders/items.js.map +1 -0
- package/dist/orders/queue.js +108 -0
- package/dist/orders/queue.js.map +1 -0
- package/dist/orders/waiting.d.ts +39 -0
- package/dist/orders/waiting.js +149 -0
- package/dist/orders/waiting.js.map +1 -0
- package/dist/pack.schema.js +13 -0
- package/dist/pack.schema.js.map +1 -0
- package/dist/pack.schema.json +7622 -841
- package/dist/packs/director/index.d.ts +13 -5
- package/dist/packs/director/index.js +204 -0
- package/dist/packs/director/index.js.map +1 -0
- package/dist/packs/heroes/campaign.d.ts +3 -2
- package/dist/packs/heroes/campaign.js +241 -0
- package/dist/packs/heroes/campaign.js.map +1 -0
- package/dist/packs/heroes/carry.d.ts +6 -0
- package/dist/packs/heroes/carry.js +112 -0
- package/dist/packs/heroes/carry.js.map +1 -0
- package/dist/packs/heroes/commands.js +115 -0
- package/dist/packs/heroes/commands.js.map +1 -0
- package/dist/packs/heroes/fallen.d.ts +43 -0
- package/dist/packs/heroes/fallen.js +61 -0
- package/dist/packs/heroes/fallen.js.map +1 -0
- package/dist/packs/heroes/hire.js +60 -0
- package/dist/packs/heroes/hire.js.map +1 -0
- package/dist/packs/heroes/index.d.ts +7 -6
- package/dist/packs/heroes/index.js +130 -0
- package/dist/packs/heroes/index.js.map +1 -0
- package/dist/packs/heroes/loop.d.ts +95 -0
- package/dist/packs/heroes/loop.js +250 -0
- package/dist/packs/heroes/loop.js.map +1 -0
- package/dist/packs/heroes/making.d.ts +6 -3
- package/dist/packs/heroes/making.js +55 -0
- package/dist/packs/heroes/making.js.map +1 -0
- package/dist/packs/heroes/respawn.d.ts +3 -3
- package/dist/packs/heroes/respawn.js +87 -0
- package/dist/packs/heroes/respawn.js.map +1 -0
- package/dist/packs/heroes/sets.d.ts +32 -0
- package/dist/packs/heroes/sets.js +51 -0
- package/dist/packs/heroes/sets.js.map +1 -0
- package/dist/packs/heroes/spells.d.ts +16 -0
- package/dist/packs/heroes/spells.js +269 -0
- package/dist/packs/heroes/spells.js.map +1 -0
- package/dist/packs/items/defaults.d.ts +43 -0
- package/dist/packs/items/defaults.js +1504 -0
- package/dist/packs/items/defaults.js.map +1 -0
- package/dist/packs/items/index.d.ts +27 -0
- package/dist/packs/items/index.js +214 -0
- package/dist/packs/items/index.js.map +1 -0
- package/dist/packs/moba/index.d.ts +3 -3
- package/dist/packs/moba/index.js +174 -0
- package/dist/packs/moba/index.js.map +1 -0
- package/dist/packs/pack.d.ts +15 -15
- package/dist/packs/pack.js +14 -0
- package/dist/packs/pack.js.map +1 -0
- package/dist/packs.d.ts +15 -7
- package/dist/packs.js +222 -0
- package/dist/packs.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +109 -0
- package/dist/paths.js.map +1 -0
- package/dist/plain.js +57 -0
- package/dist/plain.js.map +1 -0
- package/dist/player.d.ts +33 -10
- package/dist/player.js +159 -0
- package/dist/player.js.map +1 -0
- package/dist/portals.d.ts +1 -1
- package/dist/portals.js +194 -0
- package/dist/portals.js.map +1 -0
- package/dist/prefabs.d.ts +25 -2
- package/dist/prefabs.js +239 -0
- package/dist/prefabs.js.map +1 -0
- package/dist/presetBuildings.js +58 -0
- package/dist/presetBuildings.js.map +1 -0
- package/dist/presetFoliage.d.ts +27 -0
- package/dist/presetFoliage.js +98 -0
- package/dist/presetFoliage.js.map +1 -0
- package/dist/presetGround.js +65 -0
- package/dist/presetGround.js.map +1 -0
- package/dist/proxies.d.ts +12 -0
- package/dist/proxies.js +79 -0
- package/dist/proxies.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +88 -0
- package/dist/query.js.map +1 -0
- package/dist/races.d.ts +15 -14
- package/dist/races.js +172 -0
- package/dist/races.js.map +1 -0
- package/dist/randomGroups.js +91 -0
- package/dist/randomGroups.js.map +1 -0
- package/dist/registry.d.ts +117 -53
- package/dist/registry.js +323 -0
- package/dist/registry.js.map +1 -0
- package/dist/remains.d.ts +11 -9
- package/dist/remains.js +188 -0
- package/dist/remains.js.map +1 -0
- package/dist/replication.d.ts +12 -7
- package/dist/replication.js +100 -0
- package/dist/replication.js.map +1 -0
- package/dist/rng.d.ts +2 -0
- package/dist/rng.js +40 -0
- package/dist/rng.js.map +1 -0
- package/dist/rules.d.ts +186 -99
- package/dist/rules.js +179 -0
- package/dist/rules.js.map +1 -0
- package/dist/rulesCheck.d.ts +5 -4
- package/dist/rulesCheck.js +693 -0
- package/dist/rulesCheck.js.map +1 -0
- package/dist/runes.d.ts +2 -2
- package/dist/runes.js +80 -0
- package/dist/runes.js.map +1 -0
- package/dist/save.d.ts +37 -12
- package/dist/save.js +532 -0
- package/dist/save.js.map +1 -0
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +99 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.js +156 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/score.d.ts +19 -19
- package/dist/score.js +709 -0
- package/dist/score.js.map +1 -0
- package/dist/sequences.d.ts +10 -6
- package/dist/sequences.js +206 -0
- package/dist/sequences.js.map +1 -0
- package/dist/server/doorman.js +154 -0
- package/dist/server/doorman.js.map +1 -0
- package/dist/server/gameServer.d.ts +16 -1
- package/dist/server/gameServer.js +643 -0
- package/dist/server/gameServer.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/lobby.js +199 -0
- package/dist/server/lobby.js.map +1 -0
- package/dist/server/log.js +18 -0
- package/dist/server/log.js.map +1 -0
- package/dist/server/match.js +267 -0
- package/dist/server/match.js.map +1 -0
- package/dist/server/mode.d.ts +18 -9
- package/dist/server/mode.js +220 -0
- package/dist/server/mode.js.map +1 -0
- package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
- package/dist/server/navigation-worker.js.map +1 -0
- package/dist/server/navigation.js +39 -0
- package/dist/server/navigation.js.map +1 -0
- package/dist/server/ops.d.ts +4 -0
- package/dist/server/ops.js +137 -0
- package/dist/server/ops.js.map +1 -0
- package/dist/server/packs.d.ts +3 -3
- package/dist/server/packs.js +32 -0
- package/dist/server/packs.js.map +1 -0
- package/dist/server/ratings.d.ts +5 -0
- package/dist/server/ratings.js +104 -0
- package/dist/server/ratings.js.map +1 -0
- package/dist/server/relay.d.ts +12 -2
- package/dist/server/relay.js +144 -0
- package/dist/server/relay.js.map +1 -0
- package/dist/server/rooms.d.ts +9 -2
- package/dist/server/rooms.js +442 -0
- package/dist/server/rooms.js.map +1 -0
- package/dist/server/seat.js +116 -0
- package/dist/server/seat.js.map +1 -0
- package/dist/server/seatSettings.d.ts +3 -3
- package/dist/server/seatSettings.js +63 -0
- package/dist/server/seatSettings.js.map +1 -0
- package/dist/server/secret.js +13 -0
- package/dist/server/secret.js.map +1 -0
- package/dist/server/start.d.ts +13 -6
- package/dist/server/start.js +76 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/websocket.d.ts +9 -1
- package/dist/server/websocket.js +306 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/server.js +15 -2861
- package/dist/session/can.js +26 -0
- package/dist/session/can.js.map +1 -0
- package/dist/session/commandReplay.d.ts +8 -2
- package/dist/session/commandReplay.js +293 -0
- package/dist/session/commandReplay.js.map +1 -0
- package/dist/session/debug.js +151 -0
- package/dist/session/debug.js.map +1 -0
- package/dist/session/delay.js +62 -0
- package/dist/session/delay.js.map +1 -0
- package/dist/session/delta.d.ts +14 -1
- package/dist/session/delta.js +407 -0
- package/dist/session/delta.js.map +1 -0
- package/dist/session/entityState.js +415 -0
- package/dist/session/entityState.js.map +1 -0
- package/dist/session/local.d.ts +47 -5
- package/dist/session/local.js +670 -0
- package/dist/session/local.js.map +1 -0
- package/dist/session/memory.d.ts +20 -2
- package/dist/session/memory.js +131 -0
- package/dist/session/memory.js.map +1 -0
- package/dist/session/protocol.d.ts +325 -31
- package/dist/session/protocol.js +55 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/remote.d.ts +74 -12
- package/dist/session/remote.js +1394 -0
- package/dist/session/remote.js.map +1 -0
- package/dist/session/replay.d.ts +11 -2
- package/dist/session/replay.js +160 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/seed.js +12 -0
- package/dist/session/seed.js.map +1 -0
- package/dist/session/share.d.ts +5 -1
- package/dist/session/share.js +94 -0
- package/dist/session/share.js.map +1 -0
- package/dist/session/socket.d.ts +1 -1
- package/dist/session/socket.js +29 -0
- package/dist/session/socket.js.map +1 -0
- package/dist/session/wire.d.ts +5 -0
- package/dist/session/wire.js +84 -0
- package/dist/session/wire.js.map +1 -0
- package/dist/session/worker.d.ts +77 -12
- package/dist/session/worker.js +499 -0
- package/dist/session/worker.js.map +1 -0
- package/dist/shared.d.ts +31 -5
- package/dist/shared.js +166 -0
- package/dist/shared.js.map +1 -0
- package/dist/sides.d.ts +9 -3
- package/dist/sides.js +149 -0
- package/dist/sides.js.map +1 -0
- package/dist/sight.js +85 -0
- package/dist/sight.js.map +1 -0
- package/dist/simulate-worker.js +1 -1
- package/dist/simulate.d.ts +12 -8
- package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
- package/dist/simulate.js.map +1 -0
- package/dist/smart.js +77 -0
- package/dist/smart.js.map +1 -0
- package/dist/spatial.d.ts +32 -16
- package/dist/spatial.js +234 -0
- package/dist/spatial.js.map +1 -0
- package/dist/spawning.d.ts +1 -0
- package/dist/spawning.js +224 -0
- package/dist/spawning.js.map +1 -0
- package/dist/stances.d.ts +6 -3
- package/dist/stances.js +169 -0
- package/dist/stances.js.map +1 -0
- package/dist/start.d.ts +10 -10
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/stats.d.ts +42 -16
- package/dist/stats.js +290 -0
- package/dist/stats.js.map +1 -0
- package/dist/summoned.d.ts +52 -0
- package/dist/summoned.js +38 -0
- package/dist/summoned.js.map +1 -0
- package/dist/summons.d.ts +10 -13
- package/dist/summons.js +271 -0
- package/dist/summons.js.map +1 -0
- package/dist/systems/abilities.js +224 -0
- package/dist/systems/abilities.js.map +1 -0
- package/dist/systems/combat.d.ts +35 -1
- package/dist/systems/combat.js +677 -0
- package/dist/systems/combat.js.map +1 -0
- package/dist/systems/combatTold.d.ts +3 -1
- package/dist/systems/combatTold.js +85 -0
- package/dist/systems/combatTold.js.map +1 -0
- package/dist/systems/construction.js +80 -0
- package/dist/systems/construction.js.map +1 -0
- package/dist/systems/economy.d.ts +0 -6
- package/dist/systems/economy.js +128 -0
- package/dist/systems/economy.js.map +1 -0
- package/dist/systems/fog.d.ts +1 -1
- package/dist/systems/fog.js +120 -0
- package/dist/systems/fog.js.map +1 -0
- package/dist/systems/life.js +32 -0
- package/dist/systems/life.js.map +1 -0
- package/dist/systems/movement.d.ts +24 -12
- package/dist/systems/movement.js +1247 -0
- package/dist/systems/movement.js.map +1 -0
- package/dist/systems/orders.js +64 -0
- package/dist/systems/orders.js.map +1 -0
- package/dist/systems/production.js +322 -0
- package/dist/systems/production.js.map +1 -0
- package/dist/systems/productionQueue.js +120 -0
- package/dist/systems/productionQueue.js.map +1 -0
- package/dist/systems/victory.d.ts +1 -1
- package/dist/systems/victory.js +56 -0
- package/dist/systems/victory.js.map +1 -0
- package/dist/talk.d.ts +6 -6
- package/dist/talk.js +153 -0
- package/dist/talk.js.map +1 -0
- package/dist/targeting.d.ts +142 -0
- package/dist/targeting.js +49 -0
- package/dist/targeting.js.map +1 -0
- package/dist/tech.d.ts +20 -3
- package/dist/tech.js +239 -0
- package/dist/tech.js.map +1 -0
- package/dist/techTree.d.ts +7 -0
- package/dist/techTree.js +90 -0
- package/dist/techTree.js.map +1 -0
- package/dist/terrain.d.ts +59 -7
- package/dist/terrain.js +389 -0
- package/dist/terrain.js.map +1 -0
- package/dist/terrainSave.d.ts +6 -0
- package/dist/terrainSave.js +74 -0
- package/dist/terrainSave.js.map +1 -0
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +13 -739
- package/dist/testing.js.map +1 -1
- package/dist/tiles.d.ts +1 -1
- package/dist/tiles.js +43 -0
- package/dist/tiles.js.map +1 -0
- package/dist/timers.d.ts +29 -4
- package/dist/timers.js +242 -0
- package/dist/timers.js.map +1 -0
- package/dist/tomes.d.ts +4 -4
- package/dist/tomes.js +94 -0
- package/dist/tomes.js.map +1 -0
- package/dist/trade.js +103 -0
- package/dist/trade.js.map +1 -0
- package/dist/transport.d.ts +6 -1
- package/dist/transport.js +281 -0
- package/dist/transport.js.map +1 -0
- package/dist/tunables.d.ts +10 -3
- package/dist/tunables.js +56 -0
- package/dist/tunables.js.map +1 -0
- package/dist/unitResources.d.ts +67 -0
- package/dist/unitResources.js +266 -0
- package/dist/unitResources.js.map +1 -0
- package/dist/upkeep.d.ts +6 -1
- package/dist/upkeep.js +26 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/veterancy.d.ts +8 -3
- package/dist/veterancy.js +131 -0
- package/dist/veterancy.js.map +1 -0
- package/dist/vision.d.ts +36 -0
- package/dist/vision.js +133 -0
- package/dist/vision.js.map +1 -0
- package/dist/walls.d.ts +1 -1
- package/dist/walls.js +278 -0
- package/dist/walls.js.map +1 -0
- package/dist/world.d.ts +606 -88
- package/dist/world.js +1263 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
- package/dist/ai.js.map +0 -1
- package/dist/attributes.d.ts +0 -66
- package/dist/brain-BvVdUhX8.js +0 -7659
- package/dist/brain-BvVdUhX8.js.map +0 -1
- package/dist/builds-C6LfgvEU.js +0 -460
- package/dist/builds-C6LfgvEU.js.map +0 -1
- package/dist/coreComponents-syuh2fPG.js +0 -5149
- package/dist/coreComponents-syuh2fPG.js.map +0 -1
- package/dist/debugCommands-CzjrSm66.js +0 -14739
- package/dist/debugCommands-CzjrSm66.js.map +0 -1
- package/dist/determinism-BCymQwiE.js +0 -518
- package/dist/determinism-BCymQwiE.js.map +0 -1
- package/dist/game-DiJEN-Ks.js +0 -5800
- package/dist/game-DiJEN-Ks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect-D9dWHmZ0.js.map +0 -1
- package/dist/local-Dkovq42k.js +0 -1379
- package/dist/local-Dkovq42k.js.map +0 -1
- package/dist/missionRules-C-bGxm0Q.js.map +0 -1
- package/dist/navigation-worker.js.map +0 -1
- package/dist/packs-g5thvmGn.js +0 -3199
- package/dist/packs-g5thvmGn.js.map +0 -1
- package/dist/profiles-B3NS9jwk.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/simulate-oXBiw1Ff.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","names":[],"sources":["../src/generate.ts"],"sourcesContent":["/**\n * Maps made by a generator (world plan G1): a map from a seed and a few sliders, made of passes a game adds to,\n * replaces or leaves out, each a function of a context that holds the map, the seed's numbers, noise that repeats\n * across the map, the symmetry and what the passes before put down. Deterministic: the engine's `Rng`, nothing of\n * the clock. The engine's own passes shape the ground (`terrainPass`), paint it (`tilesPass`), seat the players\n * (`startsPass`), scatter things over it (`scatterPass`: trees now, rocks and houses the same way later), put\n * resources near the starts (`resourcesPass`) and lay roads (`roadsPass`); `generateMap` runs them and checks the map\n * (`checkMap`), trying the next seed where a start is cut off or blocked. A game declares its generator\n * (`Rules.generator`), for the editor and the page to find; `presetGenerator` is the engine's to take whole\n */\nimport { checkMap } from './mapCheck'\nimport { Rng } from './rng'\nimport { layeredNoise, type Noise2 } from './noise'\nimport {\n\tcreateMap,\n\ttype GameMap,\n\tMAP_CREEPS,\n\tMAP_NEUTRAL,\n\ttype MapCamp,\n\ttype MapDoodad,\n\ttype MapObject,\n\ttype MapPlayer,\n\ttype MapRegion,\n\tmapTerrain\n} from './map'\nimport type { MapProblem } from './mapFields'\nimport type { Vec2 } from './math'\nimport type { AreaShape } from './areas'\nimport type { PlayerId } from './entity'\nimport type { Registry } from './registry'\nimport { WATER_DEEP, WATER_NONE, WATER_SHALLOW } from './terrain'\nimport { atan, atan2, cos, hypot, sin } from './exactMath'\n\n/**\n * How a map is mirrored, so that it is fair: not at all, across x, across z, both ways, a half turn about the middle,\n * or quarter turns (a square map, its sides even). As the editor's symmetry says it\n *\n * @beta\n */\nexport type MapSymmetry = 'none' | 'x' | 'z' | 'both' | 'half' | 'quarter'\n\n/**\n * What a map is made with (`generateMap`): the seed, the size, the players, the symmetry, and the game's own\n * parameters (`MapGenerator.params`), each at its default where not said\n *\n * @beta\n */\nexport interface GeneratorOptions {\n\t/** The seed that makes the map: the same seed and options make the same map */\n\tseed: number\n\t/** The map's width in cells */\n\twidth: number\n\t/** The map's depth in cells */\n\tdepth: number\n\t/** How many players the map has starts for */\n\tplayers: number\n\t/** How the map is mirrored or turned so each player's side is alike: `none` when left out */\n\tsymmetry?: MapSymmetry\n\t/** The map's name: \"Generated <seed>\" when left out */\n\tname?: string\n\t/** The game's own parameters, by id, as the dialog's sliders and switches set them */\n\tparams?: Record<string, number | string | boolean>\n}\n\n/**\n * A parameter of a generator (`MapGenerator.params`): a slider, a switch or a choice in the editor's dialog and the\n * page's form, and a value in code (`GeneratorOptions.params`)\n *\n * @beta\n */\nexport interface GeneratorParamDef {\n\t/** The id the pass or parameter is kept by, in `GeneratorOptions.params` for a parameter */\n\tid: string\n\t/** The name shown in the editor's dialog and the page's form */\n\tname: string\n\t/** A line about it shown beside it in the form */\n\tdescription?: string\n\t/** A number on a slider (the default), a switch, or one of `choices` */\n\tkind?: 'number' | 'boolean' | 'choice'\n\t/** The value used when the options do not say: a number, a string for a `choice` or a boolean for a switch */\n\tdefault: number | string | boolean\n\t/** Of a `number`: the least the slider goes to */\n\tmin?: number\n\t/** Of a `number`: the most the slider goes to */\n\tmax?: number\n\t/** Of a `number`: the size of one step of the slider */\n\tstep?: number\n\t/** Of a `choice`: the values it can be, each with the label shown for it */\n\tchoices?: { value: string; label: string }[]\n}\n\n/**\n * What was put down by a pass, for the passes after to avoid or use (`GeneratorContext.placed`)\n *\n * @beta\n */\nexport interface GeneratorMark {\n\t/** The kind of thing marked, a name the passes agree on (`start`, `camp`), read by `GeneratorContext.free` */\n\tkind: string\n\t/** The mark's centre on the map's x axis, in cells */\n\tx: number\n\t/** The mark's centre on the map's z axis, in cells */\n\tz: number\n\t/** The radius the mark keeps clear, in cells */\n\tradius: number\n}\n\n/**\n * What a pass works with (`GeneratorPass.run`): the map as the passes before left it, the seed's numbers, noise that\n * repeats across the map, the symmetry, and what to put down with\n *\n * @beta\n */\nexport interface GeneratorContext {\n\t/** The map as the passes before left it; a pass changes it in place */\n\tmap: GameMap\n\t/** The seed's numbers: every draw of a pass is one of these, so the same seed makes the same map */\n\trng: Rng\n\t/** The options the map is made with: seed, size, players, symmetry and parameters */\n\toptions: GeneratorOptions\n\t/** The game's registry, which tells what unit types and doodads exist */\n\tregistry: Registry\n\t/** A parameter as it is: what the options say, or its default (`MapGenerator.params`), or `fallback` where neither says */\n\tparam<T extends number | string | boolean>(id: string, fallback: T): T\n\t/**\n\t * A place, and the places the symmetry mirrors or turns it to (the first is the place itself): what is put down at\n\t * one is put down at the others, so the map is fair\n\t */\n\tsymmetric(x: number, z: number): Vec2[]\n\t/** Whether a cell is the first of its mirrored set: what is done once a set is done at this one, and mirrored from it */\n\tcanonical(cx: number, cz: number): boolean\n\t/**\n\t * What `draw` makes, made once for a place and the places the symmetry mirrors it to: the first call of a set draws\n\t * (and spends the seed's numbers), the calls for its mirrors get the same. For a choice put down at every mirror\n\t * (a camp's creeps), so the map stays fair\n\t */\n\tonce<T>(x: number, z: number, draw: () => T): T\n\t/**\n\t * Noise that repeats across the map, by a name (the same name is the same noise), 0..1 at a point of the map in\n\t * cells; `cells` are the sizes of its features, coarsest first (`[32, 16, 8]` for hills). Mirrored as the map is\n\t */\n\tnoise(name: string, cells?: readonly number[]): (x: number, z: number) => number\n\t/** What the passes before put down, by kind */\n\tplaced: GeneratorMark[]\n\t/** Puts a mark down for the passes after: nothing on the map, only in `placed` */\n\tmark(kind: string, x: number, z: number, radius: number): void\n\t/** Whether nothing marked is within `radius` of a place (of `kinds` alone, when said) */\n\tfree(x: number, z: number, radius: number, kinds?: readonly string[]): boolean\n\t/** The level of the ground at a point: its cell's cliff level */\n\tlevelAt(x: number, z: number): number\n\t/** Whether a point is on the map and on ground something walks: no deep water, not off the map */\n\twalkable(x: number, z: number): boolean\n\t/** Scenery put down, with an id of its own: the model by its path in `models/`, as big as it says, turned as it says */\n\taddDoodad(doodad: Omit<MapDoodad, 'id' | 'scale' | 'yaw'> & { scale?: number | [number, number, number]; yaw?: number }): MapDoodad\n\t/** A unit or a building of a type put down, with an id of its own, for a player (`MAP_NEUTRAL`, `MAP_CREEPS`, or one of the map's) */\n\taddObject(type: string, owner: PlayerId, x: number, z: number, more?: Partial<Omit<MapObject, 'id' | 'type' | 'owner' | 'x' | 'z'>>): MapObject\n\t/** Creeps that guard a spot, with an id of their own */\n\taddCamp(x: number, z: number, units: string[], more?: Partial<Omit<MapCamp, 'id' | 'x' | 'z' | 'units'>>): MapCamp\n\t/** A region the rules watch by name, with an id of its own */\n\taddRegion(name: string, shape: AreaShape, more?: Partial<Omit<MapRegion, 'id' | 'name' | 'shape'>>): MapRegion\n}\n\n/**\n * A pass of a generator: one thing done to the map, in its turn (`MapGenerator.passes`)\n *\n * @beta\n */\nexport interface GeneratorPass {\n\t/** The id the pass is told apart by */\n\tid: string\n\t/** The name shown for the pass */\n\tname: string\n\t/** Does the pass's work on `ctx.map`, returning nothing */\n\trun(ctx: GeneratorContext): void\n}\n\n/**\n * A game's generator (`Rules.generator`): its parameters, as the dialog and the page show them, and its passes\n * in order. `generateMap` runs it\n *\n * @beta\n */\nexport interface MapGenerator {\n\t/** The parameters the generator takes, as the dialog and the page show them */\n\tparams: GeneratorParamDef[]\n\t/** The passes run in order, each working on the map the passes before made */\n\tpasses: GeneratorPass[]\n\t/**\n\t * How many seeds are tried where the map comes out with a problem that keeps it from being played (an error, a start\n\t * cut off from the others or blocked): 4 when left out\n\t */\n\ttries?: number\n}\n\n/**\n * How a map was made, kept with it (`GameMap.generated`): the same again from the same\n *\n * @beta\n */\nexport interface GeneratedWith {\n\t/** The seed the map came out of */\n\tseed: number\n\t/** The options the map was made with, kept so the same map can be made again */\n\toptions: GeneratorOptions\n}\n\n/**\n * The map a generator makes of options: its passes run in order on a map of the size and players asked, with the\n * game's tiles; then checked (`checkMap`). A map with a problem that keeps it from being played (a start cut off from\n * the others, or where nothing walks) is thrown away and the next seed tried, `tries` times; the last is given with\n * its problems. The map says how it was made (`GameMap.generated`)\n *\n * @beta\n */\nexport function generateMap(\n\tgenerator: MapGenerator,\n\toptions: GeneratorOptions,\n\tregistry: Registry\n): { map: GameMap; problems: MapProblem[]; seed: number } {\n\tconst tries = Math.max(1, generator.tries ?? 4)\n\tlet last: { map: GameMap; problems: MapProblem[]; seed: number } | undefined\n\tfor (let attempt = 0; attempt < tries; attempt++) {\n\t\tconst seed = options.seed + attempt\n\t\tconst map = createMap({\n\t\t\tname: options.name ?? `Generated ${seed}`,\n\t\t\twidth: options.width,\n\t\t\tdepth: options.depth,\n\t\t\tplayers: options.players,\n\t\t\tgame: registry.module?.id,\n\t\t\ttileset: registry.tileIds\n\t\t})\n\t\tconst ctx: GeneratorContext = createContext(map, { ...options, seed }, registry, generator)\n\t\tfor (const pass of generator.passes) pass.run(ctx)\n\t\tmap.generated = { seed, options: { ...options, seed } }\n\t\tconst problems = checkMap(map, registry)\n\t\tlast = { map, problems, seed }\n\t\tif (!problems.some(unplayable)) return last\n\t}\n\treturn last!\n}\n\n/** What keeps a map from being played, so that the next seed is tried: an error, or a start cut off from the others or blocked */\nconst unplayable = (problem: MapProblem) => problem.error || problem.rule === 'starts-apart' || problem.rule === 'start-blocked'\n\n// ---- the context\n\nconst SYMMETRIES: MapSymmetry[] = ['none', 'x', 'z', 'both', 'half', 'quarter']\n\n/**\n * The places a point is mirrored or turned to, the point first (as the editor's `mirrors`)\n *\n * @beta\n */\nexport function symmetricPlaces(symmetry: MapSymmetry, width: number, depth: number, x: number, z: number): Vec2[] {\n\tconst out: Vec2[] = [{ x, z }]\n\tconst add = (px: number, pz: number) => {\n\t\tif (!out.some((other) => Math.abs(other.x - px) < 1e-6 && Math.abs(other.z - pz) < 1e-6)) out.push({ x: px, z: pz })\n\t}\n\tswitch (symmetry) {\n\t\tcase 'x':\n\t\t\tadd(width - x, z)\n\t\t\tbreak\n\t\tcase 'z':\n\t\t\tadd(x, depth - z)\n\t\t\tbreak\n\t\tcase 'both':\n\t\t\tadd(width - x, z)\n\t\t\tadd(x, depth - z)\n\t\t\tadd(width - x, depth - z)\n\t\t\tbreak\n\t\tcase 'half':\n\t\t\tadd(width - x, depth - z)\n\t\t\tbreak\n\t\tcase 'quarter': {\n\t\t\tconst cx = width / 2\n\t\t\tconst cz = depth / 2\n\t\t\tfor (let k = 1; k < 4; k++) {\n\t\t\t\tlet px = x - cx\n\t\t\t\tlet pz = z - cz\n\t\t\t\tfor (let i = 0; i < k; i++) [px, pz] = [-pz, px]\n\t\t\t\tadd(cx + px, cz + pz)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\treturn out\n}\n\n/** How many places a mirrored set has at most: four, for quarter turns and both ways */\nconst MIRRORS = 4\n\n/** The first of a point's mirrored set, by row then column: where a noise is read, so the noise is mirrored as the map is */\nfunction firstPlace(symmetry: MapSymmetry, width: number, depth: number, x: number, z: number, out: { x: number; z: number }): void {\n\tout.x = x\n\tout.z = z\n\tconst take = (px: number, pz: number) => takeFirst(out, px, pz)\n\tswitch (symmetry) {\n\t\tcase 'x':\n\t\t\ttake(width - x, z)\n\t\t\tbreak\n\t\tcase 'z':\n\t\t\ttake(x, depth - z)\n\t\t\tbreak\n\t\tcase 'both':\n\t\t\ttake(width - x, z)\n\t\t\ttake(x, depth - z)\n\t\t\ttake(width - x, depth - z)\n\t\t\tbreak\n\t\tcase 'half':\n\t\t\ttake(width - x, depth - z)\n\t\t\tbreak\n\t\tcase 'quarter': {\n\t\t\tconst cx = width / 2\n\t\t\tconst cz = depth / 2\n\t\t\tlet px = x - cx\n\t\t\tlet pz = z - cz\n\t\t\tfor (let k = 1; k < 4; k++) {\n\t\t\t\t;[px, pz] = [-pz, px]\n\t\t\t\ttake(cx + px, cz + pz)\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n/** The earlier of a place and another, by row then column, kept in `out` */\nfunction takeFirst(out: { x: number; z: number }, px: number, pz: number): void {\n\tif (pz < out.z - 1e-6 || (Math.abs(pz - out.z) < 1e-6 && px < out.x)) {\n\t\tout.x = px\n\t\tout.z = pz\n\t}\n}\n\n/** What the engine's passes use of a context beyond what a game's see: the mirror table */\ninterface GeneratorInternals {\n\t/** A cell's mirrored set, as cells, itself among them */\n\tmirrorsOf(c: number): number[]\n\t/** Sets a value in a cell and its mirrors */\n\tsetCell(array: Uint8Array, c: number, value: number): void\n}\n\nfunction createContext(map: GameMap, options: GeneratorOptions, registry: Registry, generator: MapGenerator): GeneratorContext & GeneratorInternals {\n\tconst { width, depth } = map\n\tconst symmetry = options.symmetry ?? 'none'\n\tif (!SYMMETRIES.includes(symmetry)) throw new Error(`generateMap: there is no symmetry \"${symmetry}\": ${SYMMETRIES.join(', ')}`)\n\tif (symmetry === 'quarter' && (width !== depth || width % 2)) throw new Error('generateMap: quarter turns need a square map with even sides')\n\tconst rng = new Rng(options.seed)\n\tconst defaults = Object.fromEntries(generator.params.map((param) => [param.id, param.default]))\n\tconst given = options.params ?? {}\n\tconst noises = new Map<string, Noise2>()\n\tconst placed: GeneratorMark[] = []\n\tlet nextId = 1\n\t// each cell's mirrored set, as cells (-1 past the end), and the first of it: where things are done once, and mirrored from\n\tconst mirrors = new Int32Array(width * depth * MIRRORS).fill(-1)\n\tconst canon = new Int32Array(width * depth)\n\tfor (let c = 0; c < canon.length; c++) {\n\t\tconst cx = c % width\n\t\tconst cz = (c - cx) / width\n\t\tlet first = c\n\t\tlet n = 0\n\t\tfor (const place of symmetricPlaces(symmetry, width, depth, cx + 0.5, cz + 0.5)) {\n\t\t\tconst mx = Math.floor(place.x)\n\t\t\tconst mz = Math.floor(place.z)\n\t\t\tif (mx < 0 || mz < 0 || mx >= width || mz >= depth) continue\n\t\t\tconst m = mz * width + mx\n\t\t\tmirrors[c * MIRRORS + n++] = m\n\t\t\tfirst = Math.min(first, m)\n\t\t}\n\t\tcanon[c] = first\n\t}\n\t// the marks in a grid of 8 cells, for what keeps off them to find the near ones alone\n\tconst GRID = 8\n\tconst cols = Math.ceil(width / GRID)\n\tconst rows = Math.ceil(depth / GRID)\n\tconst grid: number[][] = Array.from({ length: cols * rows }, () => [])\n\tlet widest = 0\n\tconst point = { x: 0, z: 0 }\n\tconst drawn = new Map<number, unknown>()\n\treturn {\n\t\tmap,\n\t\trng,\n\t\toptions,\n\t\tregistry,\n\t\tparam: <T extends number | string | boolean>(id: string, fallback: T): T => (given[id] ?? defaults[id] ?? fallback) as T,\n\t\tsymmetric: (x, z) => symmetricPlaces(symmetry, width, depth, x, z),\n\t\tcanonical: (cx, cz) => canon[cz * width + cx] === cz * width + cx,\n\t\tonce: <T>(x: number, z: number, draw: () => T): T => {\n\t\t\tconst cx = Math.min(Math.max(Math.floor(x), 0), width - 1)\n\t\t\tconst cz = Math.min(Math.max(Math.floor(z), 0), depth - 1)\n\t\t\tconst key = canon[cz * width + cx]\n\t\t\tif (drawn.has(key)) return drawn.get(key) as T\n\t\t\tconst value = draw()\n\t\t\tdrawn.set(key, value)\n\t\t\treturn value\n\t\t},\n\t\tmirrorsOf: (c) => {\n\t\t\tconst out: number[] = []\n\t\t\tfor (let i = 0; i < MIRRORS; i++) {\n\t\t\t\tconst m = mirrors[c * MIRRORS + i]\n\t\t\t\tif (m >= 0) out.push(m)\n\t\t\t}\n\t\t\treturn out\n\t\t},\n\t\tsetCell: (array, c, value) => {\n\t\t\tfor (let i = 0; i < MIRRORS; i++) {\n\t\t\t\tconst m = mirrors[c * MIRRORS + i]\n\t\t\t\tif (m >= 0) array[m] = value\n\t\t\t}\n\t\t},\n\t\tnoise(name, cells = [32, 16, 8]) {\n\t\t\tlet known = noises.get(name)\n\t\t\tif (!known) {\n\t\t\t\t// a seed of the name's own, so another name is another noise, and the same name the same\n\t\t\t\tlet salt = 0\n\t\t\t\tfor (const letter of name) salt = (salt * 31 + letter.charCodeAt(0)) >>> 0\n\t\t\t\tconst size = Math.max(width, depth)\n\t\t\t\tconst noise = layeredNoise(\n\t\t\t\t\toptions.seed + salt,\n\t\t\t\t\tcells.map((each) => Math.max(1, Math.round(size / each)))\n\t\t\t\t)\n\t\t\t\t// mirrored as the map is: read at the first of a point's mirrored set\n\t\t\t\tknown =\n\t\t\t\t\tsymmetry === 'none'\n\t\t\t\t\t\t? (x, z) => noise(x / size, z / size)\n\t\t\t\t\t\t: (x, z) => {\n\t\t\t\t\t\t\t\tfirstPlace(symmetry, width, depth, x, z, point)\n\t\t\t\t\t\t\t\treturn noise(point.x / size, point.z / size)\n\t\t\t\t\t\t\t}\n\t\t\t\tnoises.set(name, known)\n\t\t\t}\n\t\t\treturn known\n\t\t},\n\t\tplaced,\n\t\tmark: (kind, x, z, radius) => {\n\t\t\tplaced.push({ kind, x, z, radius })\n\t\t\twidest = Math.max(widest, radius)\n\t\t\tconst gx = Math.min(Math.max(Math.floor(x / GRID), 0), cols - 1)\n\t\t\tconst gz = Math.min(Math.max(Math.floor(z / GRID), 0), rows - 1)\n\t\t\tgrid[gz * cols + gx].push(placed.length - 1)\n\t\t},\n\t\tfree: (x, z, radius, kinds) => {\n\t\t\tconst reach = Math.ceil((radius + widest) / GRID)\n\t\t\tconst gx = Math.floor(x / GRID)\n\t\t\tconst gz = Math.floor(z / GRID)\n\t\t\tfor (let dz = -reach; dz <= reach; dz++)\n\t\t\t\tfor (let dx = -reach; dx <= reach; dx++) {\n\t\t\t\t\tconst gxx = gx + dx\n\t\t\t\t\tconst gzz = gz + dz\n\t\t\t\t\tif (gxx < 0 || gzz < 0 || gxx >= cols || gzz >= rows) continue\n\t\t\t\t\tfor (const i of grid[gzz * cols + gxx]) {\n\t\t\t\t\t\tconst each = placed[i]\n\t\t\t\t\t\tif (kinds && !kinds.includes(each.kind)) continue\n\t\t\t\t\t\tif (hypot(each.x - x, each.z - z) < radius + each.radius) return false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\treturn true\n\t\t},\n\t\tlevelAt: (x, z) => {\n\t\t\tconst cx = Math.min(Math.max(Math.floor(x), 0), width - 1)\n\t\t\tconst cz = Math.min(Math.max(Math.floor(z), 0), depth - 1)\n\t\t\treturn map.levels[cz * width + cx]\n\t\t},\n\t\twalkable: (x, z) => {\n\t\t\tif (x < 0 || z < 0 || x >= width || z >= depth) return false\n\t\t\treturn map.water[Math.floor(z) * width + Math.floor(x)] !== WATER_DEEP\n\t\t},\n\t\taddDoodad(doodad) {\n\t\t\tconst { scale = 1, yaw = 0, ...rest } = doodad\n\t\t\tconst made: MapDoodad = { id: nextId++, yaw, scale: typeof scale === 'number' ? [scale, scale, scale] : scale, ...rest }\n\t\t\tmap.doodads.push(made)\n\t\t\treturn made\n\t\t},\n\t\taddObject(type, owner, x, z, more = {}) {\n\t\t\tconst made: MapObject = { id: nextId++, type, owner, x, z, facing: 0, scale: 1, ...more }\n\t\t\tmap.objects.push(made)\n\t\t\treturn made\n\t\t},\n\t\taddCamp(x, z, units, more = {}) {\n\t\t\tconst made: MapCamp = { id: nextId++, x, z, units, ...more }\n\t\t\tmap.camps.push(made)\n\t\t\treturn made\n\t\t},\n\t\taddRegion(name, shape, more = {}) {\n\t\t\tconst made: MapRegion = { id: nextId++, name, shape, ...more }\n\t\t\tmap.regions.push(made)\n\t\t\treturn made\n\t\t}\n\t}\n}\n\n// ---- the ground\n\n/**\n * What `terrainPass` takes: the parameters of the generator it reads where they are not given here\n *\n * @beta\n */\nexport interface TerrainPassOptions {\n\t/** How many cliff levels the ground rises through, 1 (flat) to 4: the parameter `levels`, or 2 */\n\tlevels?: number\n\t/** How much of the map is under water, 0..1: the parameter `water`, or 0.15 */\n\twater?: number\n\t/** How much the ground rolls within a level, 0..1: the parameter `roughness`, or 0.4 */\n\troughness?: number\n\t/** How many cells a hill is across, about: the parameter `hills`, or 24 */\n\thills?: number\n\t/** Whether ramps are cut so that every part of the ground can be walked to: yes when left out */\n\tramps?: boolean\n\t/** How wide a ramp is, in cells: 3 when left out */\n\trampWidth?: number\n\t/**\n\t * The lie of the land, where it is not the noise's alone: the ground's value at a point (high is high), made from the\n\t * point, the plateau noise there (0..1) and the map; the levels and the water are cut from the values as ever (the\n\t * lowest share water). A bay (`basinShape`: the corners high, a sea in the middle, an island in it), a valley, a\n\t * ridge: a shape of the game's own\n\t */\n\tshape?: (x: number, z: number, noise: number, map: GameMap) => number\n}\n\n/**\n * What `basinShape` takes\n *\n * @beta\n */\nexport interface BasinShapeOptions {\n\t/** How big the island in the middle is, 0..1 of the way to the corners: 0.14 when left out, 0 for no island */\n\tisland?: number\n\t/** How much the noise moves the shore and the island about, 0..1: 0.25 when left out */\n\troughness?: number\n\t/**\n\t * How high the island rises, in the shape's values (the corners are at 1, the middle of the sea at 0): 0.4 when\n\t * left out, which with `water` at 0.2 and three levels lands it on the lowest dry level, the beach's, so that fords\n\t * of shallow water reach it with no cliff between\n\t */\n\theight?: number\n}\n\n/**\n * The lie of a bay, for `terrainPass`'s `shape`: the corners high, the ground falling to a sea in the middle, an\n * island in it. With `water` at 0.25–0.35 the sea takes the middle and the shore runs round it; the starts in the\n * corners (`startsPass` with a spread of 0.4), the way between them along the shore\n *\n * @beta\n */\nexport function basinShape(options: BasinShapeOptions = {}): NonNullable<TerrainPassOptions['shape']> {\n\tconst island = Math.min(Math.max(options.island ?? 0.14, 0), 0.5)\n\tconst roughness = Math.min(Math.max(options.roughness ?? 0.25, 0), 1)\n\tconst height = Math.min(Math.max(options.height ?? 0.4, 0), 1)\n\treturn (x, z, noise, map) => {\n\t\t// how far from the middle, 0 there and 1 at a corner\n\t\tconst d = hypot((x / map.width - 0.5) * 2, (z / map.depth - 0.5) * 2) / Math.SQRT2\n\t\t// the island a plateau to its rim, not a peak: high until near its edge, then down into the sea\n\t\tconst r = island > 0 ? d / island : 1\n\t\tconst rise = r < 1 ? (1 - r * r * r * r) * height : 0\n\t\treturn d + rise + (noise - 0.5) * roughness\n\t}\n}\n\n/** Whether a cell is on the map */\nconst on = (map: GameMap, cx: number, cz: number) => cx >= 0 && cz >= 0 && cx < map.width && cz < map.depth\n\n/** The four cells next to one */\nconst NEIGHBOURS: readonly (readonly [number, number])[] = [\n\t[-1, 0],\n\t[1, 0],\n\t[0, -1],\n\t[0, 1]\n]\n\n/** How steep a cell is, in radians, from the heights at its corners: as `Terrain.slopeAt` has it, read straight off the terrain */\nfunction cellSlope(terrain: { heights: Float32Array; vertsX: number }, cx: number, cz: number): number {\n\tconst { heights, vertsX } = terrain\n\tconst v = cz * vertsX + cx\n\tconst dx = (heights[v + 1] + heights[v + vertsX + 1] - heights[v] - heights[v + vertsX]) / 2\n\tconst dz = (heights[v + vertsX] + heights[v + vertsX + 1] - heights[v] - heights[v + 1]) / 2\n\treturn atan(hypot(dx, dz))\n}\n\n/** The engine's passes reach the mirror table of the context they are given; a context of a game's own has none, and mirrors by `symmetric` */\nfunction internals(ctx: GeneratorContext): GeneratorInternals {\n\tconst own = ctx as Partial<GeneratorInternals>\n\tif (own.mirrorsOf && own.setCell) return own as GeneratorInternals\n\tconst { width } = ctx.map\n\tconst mirrorsOf = (c: number) => {\n\t\tconst cx = c % width\n\t\tconst cz = (c - cx) / width\n\t\treturn ctx.symmetric(cx + 0.5, cz + 0.5).flatMap((place) => {\n\t\t\tconst mx = Math.floor(place.x)\n\t\t\tconst mz = Math.floor(place.z)\n\t\t\treturn on(ctx.map, mx, mz) ? [mz * width + mx] : []\n\t\t})\n\t}\n\treturn { mirrorsOf, setCell: (array, c, value) => mirrorsOf(c).forEach((m) => (array[m] = value)) }\n}\n\n/**\n * The ground: a height field of noise, mirrored as the map is, quantised into cliff levels with the ground rolling\n * within each, water in the low ground, and ramps cut between the levels so that every part can be walked to\n *\n * @beta\n */\nexport function terrainPass(options: TerrainPassOptions = {}): GeneratorPass {\n\treturn {\n\t\tid: 'terrain',\n\t\tname: 'The ground',\n\t\trun(ctx) {\n\t\t\tconst { map } = ctx\n\t\t\tconst { width, depth } = map\n\t\t\tconst levels = Math.min(Math.max(Math.round(options.levels ?? ctx.param('levels', 2)), 1), 4)\n\t\t\tconst waterShare = Math.min(Math.max(options.water ?? ctx.param('water', 0.15), 0), 0.6)\n\t\t\tconst roughness = Math.min(Math.max(options.roughness ?? ctx.param('roughness', 0.4), 0), 1)\n\t\t\tconst hills = Math.max(4, options.hills ?? ctx.param('hills', 24))\n\t\t\tconst plateau = ctx.noise('plateau', [hills * 2, hills])\n\t\t\tconst roll = ctx.noise('roll', [hills / 2, hills / 4, hills / 8])\n\t\t\t// the levels: the plateau noise spread evenly, so each level has about its share of the map; the lowest share is water\n\t\t\tconst values = new Float32Array(width * depth)\n\t\t\tfor (let c = 0; c < values.length; c++) {\n\t\t\t\tconst x = (c % width) + 0.5\n\t\t\t\tconst z = Math.floor(c / width) + 0.5\n\t\t\t\tvalues[c] = options.shape ? options.shape(x, z, plateau(x, z), map) : plateau(x, z)\n\t\t\t}\n\t\t\t// where the levels and the water begin, from how the noise is spread: read off a sample of it, enough to be exact to a cell or so\n\t\t\tconst stride = Math.max(1, Math.floor(values.length / 16384))\n\t\t\tconst sorted = Float32Array.from({ length: Math.floor(values.length / stride) }, (_, i) => values[i * stride]).sort()\n\t\t\tconst quantile = (q: number) => sorted[Math.min(Math.max(Math.round(q * (sorted.length - 1)), 0), sorted.length - 1)]\n\t\t\tconst waterAt = quantile(waterShare)\n\t\t\tconst steps = Array.from({ length: levels - 1 }, (_, i) => quantile(waterShare + ((1 - waterShare) * (i + 1)) / levels))\n\t\t\tfor (let c = 0; c < values.length; c++) {\n\t\t\t\tlet level = 0\n\t\t\t\tfor (const step of steps) if (values[c] >= step) level++\n\t\t\t\tmap.levels[c] = level\n\t\t\t\tmap.water[c] = values[c] < waterAt ? WATER_DEEP : WATER_NONE\n\t\t\t}\n\t\t\t// no cells alone of their level: a cliff of one cell is a spike. Each cell takes the level most of its neighbours have, twice over\n\t\t\tconst { setCell } = internals(ctx)\n\t\t\tconst counts = new Int32Array(5)\n\t\t\tfor (let round = 0; round < 2; round++) {\n\t\t\t\tconst before = map.levels.slice()\n\t\t\t\tfor (let c = 0; c < before.length; c++) {\n\t\t\t\t\tconst cx = c % width\n\t\t\t\t\tconst cz = (c - cx) / width\n\t\t\t\t\tif (!ctx.canonical(cx, cz)) continue\n\t\t\t\t\tcounts.fill(0)\n\t\t\t\t\tfor (let dz = -1; dz <= 1; dz++)\n\t\t\t\t\t\tfor (let dx = -1; dx <= 1; dx++) if (on(map, cx + dx, cz + dz)) counts[before[(cz + dz) * width + cx + dx]]++\n\t\t\t\t\tlet best = before[c]\n\t\t\t\t\tlet most = counts[best]\n\t\t\t\t\tfor (let level = 0; level < counts.length; level++) if (counts[level] > most) [best, most] = [level, counts[level]]\n\t\t\t\t\tif (best !== before[c]) setCell(map.levels, c, best)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// water lies in the low ground alone, shallow at its rim\n\t\t\tfor (let c = 0; c < values.length; c++) if (map.levels[c] > 0) map.water[c] = WATER_NONE\n\t\t\tconst deep = map.water.slice()\n\t\t\tfor (let c = 0; c < deep.length; c++) {\n\t\t\t\tif (deep[c] !== WATER_DEEP) continue\n\t\t\t\tconst cx = c % width\n\t\t\t\tconst cz = (c - cx) / width\n\t\t\t\tlet rim = false\n\t\t\t\tfor (const [dx, dz] of NEIGHBOURS) if (on(map, cx + dx, cz + dz) && deep[(cz + dz) * width + cx + dx] !== WATER_DEEP) rim = true\n\t\t\t\tif (rim) map.water[c] = WATER_SHALLOW\n\t\t\t}\n\t\t\t// the ground rolls within a level, lower under the water\n\t\t\tconst vx = width + 1\n\t\t\tfor (let iz = 0; iz <= depth; iz++)\n\t\t\t\tfor (let ix = 0; ix <= width; ix++) {\n\t\t\t\t\tconst v = iz * vx + ix\n\t\t\t\t\tmap.ground[v] = 1 + (roll(ix, iz) - 0.5) * roughness * 1.5\n\t\t\t\t}\n\t\t\tif (options.ramps !== false) cutRamps(ctx, Math.max(2, Math.round(options.rampWidth ?? 3)))\n\t\t}\n\t}\n}\n\n/**\n * Ramps between the levels, so that every part of the ground joins the rest: the parts of a level (a flood fill on the\n * level map, water left out) joined by a ramp each across the straightest stretch of cliff between two of them, the\n * nearest the middle of both first, until all are one; mirrored as the map is\n */\nfunction cutRamps(ctx: GeneratorContext, rampWidth: number): void {\n\tconst { map } = ctx\n\tconst { width, depth, levels, water, ramps } = map\n\tconst { setCell } = internals(ctx)\n\t// the parts: cells of one level, joined, with no water\n\tconst part = new Int32Array(width * depth).fill(-1)\n\tconst parts: { cells: number; x: number; z: number }[] = []\n\tconst queue = new Int32Array(width * depth)\n\tfor (let start = 0; start < part.length; start++) {\n\t\tif (part[start] >= 0 || water[start] === WATER_DEEP) continue\n\t\tconst id = parts.length\n\t\tconst sum = { cells: 0, x: 0, z: 0 }\n\t\tparts.push(sum)\n\t\tlet head = 0\n\t\tlet tail = 0\n\t\tqueue[tail++] = start\n\t\tpart[start] = id\n\t\twhile (head < tail) {\n\t\t\tconst c = queue[head++]\n\t\t\tconst cx = c % width\n\t\t\tconst cz = (c - cx) / width\n\t\t\tsum.cells++\n\t\t\tsum.x += cx + 0.5\n\t\t\tsum.z += cz + 0.5\n\t\t\tfor (const [dx, dz] of NEIGHBOURS) {\n\t\t\t\tconst nx = cx + dx\n\t\t\t\tconst nz = cz + dz\n\t\t\t\tif (!on(map, nx, nz)) continue\n\t\t\t\tconst n = nz * width + nx\n\t\t\t\tif (part[n] >= 0 || water[n] === WATER_DEEP || levels[n] !== levels[c]) continue\n\t\t\t\tpart[n] = id\n\t\t\t\tqueue[tail++] = n\n\t\t\t}\n\t\t}\n\t}\n\tfor (const each of parts) {\n\t\teach.x /= each.cells\n\t\teach.z /= each.cells\n\t}\n\tif (parts.length < 2) return\n\t// a ramp can go where a stretch of cliff is straight: `rampWidth` cells along the edge, two deep either side, all of\n\t// one level a side, none of it water. Each a candidate between the two parts, with how far from their middles it is\n\tconst half = Math.floor(rampWidth / 2)\n\tconst candidates: { a: number; b: number; cells: number[]; cost: number }[] = []\n\tconst straight = (cx: number, cz: number, dx: number, dz: number): number[] | undefined => {\n\t\t// the edge between (cx, cz) and (cx + dx, cz + dz): along it is (dz, dx)\n\t\tconst low = cz * width + cx\n\t\tconst high = (cz + dz) * width + cx + dx\n\t\tif (Math.abs(levels[low] - levels[high]) !== 1) return undefined\n\t\tconst cells: number[] = []\n\t\tfor (let along = -half; along < rampWidth - half; along++) {\n\t\t\tfor (let deep = -1; deep <= 2; deep++) {\n\t\t\t\tconst x = cx + dz * along + dx * deep\n\t\t\t\tconst z = cz + dx * along + dz * deep\n\t\t\t\tif (!on(map, x, z)) return undefined\n\t\t\t\tconst c = z * width + x\n\t\t\t\tif (water[c] !== WATER_NONE) return undefined\n\t\t\t\tif (levels[c] !== (deep <= 0 ? levels[low] : levels[high])) return undefined\n\t\t\t\tif (deep >= 0 && deep <= 1) cells.push(c)\n\t\t\t}\n\t\t}\n\t\treturn cells\n\t}\n\tfor (let cz = 0; cz < depth; cz++)\n\t\tfor (let cx = 0; cx < width; cx++) {\n\t\t\tif (!ctx.canonical(cx, cz)) continue\n\t\t\tfor (const [dx, dz] of [\n\t\t\t\t[1, 0],\n\t\t\t\t[0, 1]\n\t\t\t]) {\n\t\t\t\tif (!on(map, cx + dx, cz + dz)) continue\n\t\t\t\tconst cells = straight(cx, cz, dx, dz)\n\t\t\t\tif (!cells) continue\n\t\t\t\tconst a = part[cz * width + cx]\n\t\t\t\tconst b = part[(cz + dz) * width + cx + dx]\n\t\t\t\tif (a < 0 || b < 0 || a === b) continue\n\t\t\t\tconst mx = (parts[a].x + parts[b].x) / 2\n\t\t\t\tconst mz = (parts[a].z + parts[b].z) / 2\n\t\t\t\tcandidates.push({ a, b, cells, cost: hypot(cx + 0.5 - mx, cz + 0.5 - mz) })\n\t\t\t}\n\t\t}\n\tcandidates.sort((p, q) => p.cost - q.cost)\n\t// joined as a spanning tree: the nearest the middle first, never two between the same two parts\n\tconst root = parts.map((_, i) => i)\n\tconst find = (i: number): number => (root[i] === i ? i : (root[i] = find(root[i])))\n\tfor (const candidate of candidates) {\n\t\tconst a = find(candidate.a)\n\t\tconst b = find(candidate.b)\n\t\tif (a === b) continue\n\t\troot[a] = b\n\t\tfor (const c of candidate.cells) setCell(ramps, c, 1)\n\t}\n}\n\n// ---- the paint\n\n/**\n * What `tilesPass` takes: how a cell is painted, from what the ground is there\n *\n * @beta\n */\nexport interface TilesPassOptions {\n\t/**\n\t * The tile a cell is painted with, by id, or nothing for none (the ground's own colours): from its level, the slope\n\t * there (radians), how wet it is (a noise, 0..1) and whether it is by the water. The engine's own rule when left\n\t * out: `sand` by the water, `rock` on steep ground (the cliffs), `snow` on the top of four levels or more, `dirt`\n\t * where it is dry, each where the game has such a tile\n\t */\n\tby?: (\n\t\tcell: { x: number; z: number; level: number; slope: number; moisture: number; shore: boolean },\n\t\ttiles: readonly string[]\n\t) => string | undefined\n}\n\n/**\n * The paint: each cell a tile by what the ground is there, through the game's tiles by name\n *\n * @beta\n */\nexport function tilesPass(options: TilesPassOptions = {}): GeneratorPass {\n\treturn {\n\t\tid: 'tiles',\n\t\tname: 'The paint',\n\t\trun(ctx) {\n\t\t\tconst { map, registry } = ctx\n\t\t\tconst { width, depth } = map\n\t\t\tconst tiles = registry.tileIds\n\t\t\tif (!tiles.length) return\n\t\t\tconst terrain = mapTerrain(map)\n\t\t\tconst moisture = ctx.noise('moisture', [20, 10])\n\t\t\tlet top = 0\n\t\t\tfor (const level of map.levels) top = Math.max(top, level)\n\t\t\tconst by =\n\t\t\t\toptions.by ??\n\t\t\t\t((cell, ids) => {\n\t\t\t\t\tconst has = (id: string) => (ids.includes(id) ? id : undefined)\n\t\t\t\t\tif (cell.shore) return has('sand')\n\t\t\t\t\tif (cell.slope > 0.5) return has('rock')\n\t\t\t\t\tif (cell.level === top && top >= 3) return has('snow') ?? has('rock')\n\t\t\t\t\tif (cell.moisture < 0.35) return has('dirt')\n\t\t\t\t\treturn undefined\n\t\t\t\t})\n\t\t\tfor (let cz = 0; cz < depth; cz++)\n\t\t\t\tfor (let cx = 0; cx < width; cx++) {\n\t\t\t\t\tconst c = cz * width + cx\n\t\t\t\t\tif (map.water[c] === WATER_DEEP) continue\n\t\t\t\t\tlet shore = map.water[c] === WATER_SHALLOW\n\t\t\t\t\tif (!shore)\n\t\t\t\t\t\tfor (const [dx, dz] of NEIGHBOURS) if (on(map, cx + dx, cz + dz) && map.water[(cz + dz) * width + cx + dx] !== WATER_NONE) shore = true\n\t\t\t\t\tconst id = by(\n\t\t\t\t\t\t{ x: cx, z: cz, level: map.levels[c], slope: cellSlope(terrain, cx, cz), moisture: moisture(cx + 0.5, cz + 0.5), shore },\n\t\t\t\t\t\ttiles\n\t\t\t\t\t)\n\t\t\t\t\tmap.tiles[c] = id ? registry.tile(id) : 0\n\t\t\t\t}\n\t\t}\n\t}\n}\n\n// ---- the starts\n\n/**\n * What `startsPass` takes\n *\n * @beta\n */\nexport interface StartsPassOptions {\n\t/** How many cells around a start are flattened and dried: 6 when left out */\n\tclearing?: number\n\t/** How far from the map's middle the starts stand, 0..0.5 of its size: 0.36 when left out */\n\tspread?: number\n\t/** What a game puts at a start: its town hall and workers. Nothing when left out */\n\tfrom?: (player: MapPlayer, at: Vec2, ctx: GeneratorContext) => void\n}\n\n/**\n * The starts: as far apart as the symmetry allows (mirrored from one, or around the middle), each on flat, dry ground\n * (a clearing made for it), the player's `start` set, and what the game puts there\n *\n * @beta\n */\nexport function startsPass(options: StartsPassOptions = {}): GeneratorPass {\n\treturn {\n\t\tid: 'starts',\n\t\tname: 'The starts',\n\t\trun(ctx) {\n\t\t\tconst { map, rng } = ctx\n\t\t\tconst { width, depth } = map\n\t\t\tconst players = map.players.filter((player) => player.id !== MAP_NEUTRAL && player.id !== MAP_CREEPS)\n\t\t\tif (!players.length) return\n\t\t\tconst clearing = Math.max(2, options.clearing ?? 6)\n\t\t\tconst spread = Math.min(Math.max(options.spread ?? 0.36, 0.1), 0.48)\n\t\t\tconst symmetry = ctx.options.symmetry ?? 'none'\n\t\t\t// how many a mirrored set gives: that many starts from one place\n\t\t\tconst setSize = ctx.symmetric(width * 0.3, depth * 0.2).length\n\t\t\tconst seeds = Math.ceil(players.length / setSize)\n\t\t\tconst places: Vec2[] = []\n\t\t\tconst angle0 = symmetry === 'none' ? rng.next() * Math.PI * 2 : symmetry === 'x' ? Math.PI : symmetry === 'z' ? Math.PI / 2 : Math.PI * 1.25\n\t\t\t// a set can give fewer places than `setSize` (a start on a mirror axis is its own mirror): go on round the ring until each player has one\n\t\t\tfor (let i = 0; i < seeds + players.length && places.length < players.length; i++) {\n\t\t\t\tconst angle = angle0 + (i * Math.PI * 2) / Math.max(seeds * setSize, 1)\n\t\t\t\tconst x = width / 2 + cos(angle) * width * spread\n\t\t\t\tconst z = depth / 2 + sin(angle) * depth * spread\n\t\t\t\tfor (const place of ctx.symmetric(x, z)) if (places.length < players.length) places.push(place)\n\t\t\t}\n\t\t\tplayers.forEach((player, i) => {\n\t\t\t\tconst at = dryGround(ctx, places[i], clearing)\n\t\t\t\tclear(ctx, at, clearing)\n\t\t\t\tplayer.start = { x: at.x, z: at.z }\n\t\t\t\tctx.mark('start', at.x, at.z, clearing)\n\t\t\t\toptions.from?.(player, at, ctx)\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * The nearest place to one that is not in the water, at a cell's middle: for a pass of a game's own that puts something\n * down where the ground may be wet\n *\n * @beta\n */\nexport const nearestDryGround = (ctx: GeneratorContext, at: Vec2, reach: number): Vec2 => dryGround(ctx, at, reach)\n\n/**\n * The ground around a place made flat and dry: one level (the one there, or `level`), no water, no ramps, the ground at\n * one height eased into what is around; mirrored as the map is, unless `alone`. What a start's clearing and a mine's\n * are made with, for a pass of a game's own\n *\n * @beta\n */\nexport const clearGround = (ctx: GeneratorContext, at: Vec2, radius: number, alone = false, level?: number): void =>\n\tclear(ctx, at, radius, alone, level ?? ctx.levelAt(at.x, at.z))\n\n/** The nearest place to one that is not in the water, at a cell's middle */\nfunction dryGround(ctx: GeneratorContext, at: Vec2, reach: number): Vec2 {\n\tconst { map } = ctx\n\tconst { width, depth } = map\n\tconst cx = Math.min(Math.max(Math.floor(at.x), 1), width - 2)\n\tconst cz = Math.min(Math.max(Math.floor(at.z), 1), depth - 2)\n\tfor (let r = 0; r <= reach * 3; r++)\n\t\tfor (let dz = -r; dz <= r; dz++)\n\t\t\tfor (let dx = -r; dx <= r; dx++) {\n\t\t\t\tif (Math.max(Math.abs(dx), Math.abs(dz)) !== r) continue\n\t\t\t\tconst x = cx + dx\n\t\t\t\tconst z = cz + dz\n\t\t\t\tif (x < 1 || z < 1 || x >= width - 1 || z >= depth - 1) continue\n\t\t\t\tif (map.water[z * width + x] === WATER_NONE) return { x: x + 0.5, z: z + 0.5 }\n\t\t\t}\n\treturn { x: cx + 0.5, z: cz + 0.5 }\n}\n\n/** The ground around a place made flat and dry: one level, no water, no ramps, the ground at one height. Mirrored, unless `alone` */\nfunction clear(ctx: GeneratorContext, at: Vec2, radius: number, alone = false, level = ctx.levelAt(at.x, at.z)): void {\n\tconst { map } = ctx\n\tconst { width, depth } = map\n\tconst vx = width + 1\n\tlet height = 0\n\tlet count = 0\n\tfor (let iz = Math.max(Math.floor(at.z - radius), 0); iz <= Math.min(Math.ceil(at.z + radius), depth); iz++)\n\t\tfor (let ix = Math.max(Math.floor(at.x - radius), 0); ix <= Math.min(Math.ceil(at.x + radius), width); ix++) {\n\t\t\theight += map.ground[iz * vx + ix]\n\t\t\tcount++\n\t\t}\n\theight /= Math.max(count, 1)\n\tfor (const place of alone ? [at] : ctx.symmetric(at.x, at.z)) {\n\t\tfor (let cz = Math.max(Math.floor(place.z - radius), 0); cz < Math.min(Math.ceil(place.z + radius), depth); cz++)\n\t\t\tfor (let cx = Math.max(Math.floor(place.x - radius), 0); cx < Math.min(Math.ceil(place.x + radius), width); cx++) {\n\t\t\t\tif (hypot(cx + 0.5 - place.x, cz + 0.5 - place.z) > radius) continue\n\t\t\t\tconst c = cz * width + cx\n\t\t\t\tmap.levels[c] = level\n\t\t\t\tmap.water[c] = WATER_NONE\n\t\t\t\tmap.ramps[c] = 0\n\t\t\t}\n\t\tfor (let iz = Math.max(Math.floor(place.z - radius), 0); iz <= Math.min(Math.ceil(place.z + radius), depth); iz++)\n\t\t\tfor (let ix = Math.max(Math.floor(place.x - radius), 0); ix <= Math.min(Math.ceil(place.x + radius), width); ix++) {\n\t\t\t\tconst d = hypot(ix - place.x, iz - place.z)\n\t\t\t\tif (d > radius) continue\n\t\t\t\t// flat in the middle, eased into the ground around at the rim\n\t\t\t\tconst t = Math.min(Math.max((d - radius * 0.6) / (radius * 0.4), 0), 1)\n\t\t\t\tconst v = iz * vx + ix\n\t\t\t\tmap.ground[v] = height + (map.ground[v] - height) * t * t * (3 - 2 * t)\n\t\t\t}\n\t}\n}\n\n// ---- things scattered\n\n/**\n * What `scatterPass` takes: how much of what, where\n *\n * @beta\n */\nexport interface ScatterPassOptions {\n\t/** What the things are, for the passes after (`placed`): `trees`, `rocks` */\n\tkind: string\n\t/** Puts one down at a place: a doodad, a unit, a camp, a region */\n\twhat: (ctx: GeneratorContext, at: Vec2) => void\n\t/** How much of the map they cover, 0..1: the parameter `<kind>` where the generator has one, or 0.12 */\n\tdensity?: number\n\t/** How far apart they are at least, in cells: 1.5 when left out */\n\tspacing?: number\n\t/** How big each is, for what comes after to keep off: half the spacing when left out */\n\tradius?: number\n\t/** How far from a start they keep, in cells: 10 when left out */\n\tavoid?: number\n\t/** What else they keep off, by kind (`placed`), with how far: the starts always */\n\tavoidKinds?: Record<string, number>\n\t/** Where they may go: a cell's level, slope, water and the noise of the kind (0..1, patches). On any dry ground when left out */\n\twhere?: (cell: { x: number; z: number; level: number; slope: number; noise: number; shore: boolean }) => boolean\n\t/** In patches of a noise (how much the noise decides, 0 even, 1 all in patches): 0.6 when left out */\n\tpatches?: number\n}\n\n/**\n * Things scattered over the map: as many as the density says, in patches of a noise, at least `spacing` apart, off\n * the starts and what else they avoid, where they may go; each put down by `what`, mirrored as the map is. Trees now;\n * rocks, houses, ruins and the rest the same way, with another `what`\n *\n * @beta\n */\nexport function scatterPass(options: ScatterPassOptions): GeneratorPass {\n\treturn {\n\t\tid: `scatter:${options.kind}`,\n\t\tname: `Scattered: ${options.kind}`,\n\t\trun(ctx) {\n\t\t\tconst { map, rng } = ctx\n\t\t\tconst { width, depth } = map\n\t\t\tconst density = Math.min(Math.max(options.density ?? ctx.param(options.kind, 0.12), 0), 1)\n\t\t\tif (density <= 0) return\n\t\t\tconst spacing = Math.max(0.5, options.spacing ?? 1.5)\n\t\t\tconst radius = options.radius ?? spacing / 2\n\t\t\tconst avoid = options.avoid ?? 10\n\t\t\tconst patches = Math.min(Math.max(options.patches ?? 0.6, 0), 1)\n\t\t\tconst noise = ctx.noise(`scatter:${options.kind}`, [24, 12, 6])\n\t\t\t// the slopes, for a `where` that asks: the terrain made once, only then\n\t\t\tlet made: ReturnType<typeof mapTerrain> | undefined\n\t\t\tconst terrain = () => (made ??= mapTerrain(map))\n\t\t\t// what is put down, in a grid of the spacing, so that nothing comes too close\n\t\t\tconst cell = spacing\n\t\t\tconst cols = Math.ceil(width / cell)\n\t\t\tconst rows = Math.ceil(depth / cell)\n\t\t\tconst grid: Vec2[][] = Array.from({ length: cols * rows }, () => [])\n\t\t\tconst tooClose = (x: number, z: number) => {\n\t\t\t\tconst gx = Math.floor(x / cell)\n\t\t\t\tconst gz = Math.floor(z / cell)\n\t\t\t\tfor (let dz = -1; dz <= 1; dz++)\n\t\t\t\t\tfor (let dx = -1; dx <= 1; dx++) {\n\t\t\t\t\t\tconst gxx = gx + dx\n\t\t\t\t\t\tconst gzz = gz + dz\n\t\t\t\t\t\tif (gxx < 0 || gzz < 0 || gxx >= cols || gzz >= rows) continue\n\t\t\t\t\t\tfor (const other of grid[gzz * cols + gxx]) if (hypot(other.x - x, other.z - z) < spacing) return true\n\t\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst put = (x: number, z: number) => {\n\t\t\t\tgrid[Math.floor(z / cell) * cols + Math.floor(x / cell)].push({ x, z })\n\t\t\t\tctx.mark(options.kind, x, z, radius)\n\t\t\t\toptions.what(ctx, { x, z })\n\t\t\t}\n\t\t\t// each cell tries once, the first of its mirrored set for all of them: a draw against the density, in patches\n\t\t\tfor (let cz = 0; cz < depth; cz++)\n\t\t\t\tfor (let cx = 0; cx < width; cx++) {\n\t\t\t\t\tif (!ctx.canonical(cx, cz)) continue\n\t\t\t\t\tconst c = cz * width + cx\n\t\t\t\t\tconst x = cx + rng.next()\n\t\t\t\t\tconst z = cz + rng.next()\n\t\t\t\t\tconst n = noise(x, z)\n\t\t\t\t\tconst chance = density * (1 - patches + patches * Math.min(Math.max((n - 0.35) / 0.3, 0), 1) * 2)\n\t\t\t\t\tif (rng.next() >= chance) continue\n\t\t\t\t\tif (map.water[c] !== WATER_NONE) continue\n\t\t\t\t\tif (options.where) {\n\t\t\t\t\t\tconst shore = NEIGHBOURS.some(([dx, dz]) => on(map, cx + dx, cz + dz) && map.water[(cz + dz) * width + cx + dx] !== WATER_NONE)\n\t\t\t\t\t\tif (!options.where({ x, z, level: map.levels[c], slope: cellSlope(terrain(), cx, cz), noise: n, shore })) continue\n\t\t\t\t\t}\n\t\t\t\t\tif (map.ramps[c]) continue\n\t\t\t\t\tif (!ctx.free(x, z, avoid, ['start'])) continue\n\t\t\t\t\tif (options.avoidKinds && Object.entries(options.avoidKinds).some(([kind, far]) => !ctx.free(x, z, far, [kind]))) continue\n\t\t\t\t\tconst places = ctx.symmetric(x, z).filter((place) => place.x >= 0 && place.z >= 0 && place.x < width && place.z < depth)\n\t\t\t\t\tif (places.some((place) => tooClose(place.x, place.z))) continue\n\t\t\t\t\tfor (const place of places) put(place.x, place.z)\n\t\t\t\t}\n\t\t}\n\t}\n}\n\n// ---- resources\n\n/**\n * What `resourcesPass` takes: where the game's mines go, and what the game puts there\n *\n * @beta\n */\nexport interface ResourcesPassOptions {\n\t/** How far from each start its own stands, in cells: 8 when left out; `false` for none at the starts (a game puts those down itself) */\n\tmain?: number | false\n\t/** How many more there are besides the starts', spread over the map and mirrored: 2 when left out */\n\textra?: number\n\t/** How far apart the extra ones keep from each other and from the starts, in cells: 20 when left out */\n\tspacing?: number\n\t/**\n\t * How many cells around each are made flat and dry for it, as a start's clearing is: 3 when left out, enough for a\n\t * mine of 4 by 4; 0 for none\n\t */\n\tclearing?: number\n\t/** Puts the resource down: the game's mine, a camp guarding it. Told the start it is for, where it is one's */\n\tfrom: (ctx: GeneratorContext, at: Vec2, start?: MapPlayer) => void\n}\n\n/**\n * Resources: one near each start (towards the map's middle, as far as `main` says), and more spread over the map,\n * mirrored as the map is, each put down by the game\n *\n * @beta\n */\nexport function resourcesPass(options: ResourcesPassOptions): GeneratorPass {\n\treturn {\n\t\tid: 'resources',\n\t\tname: 'The resources',\n\t\trun(ctx) {\n\t\t\tconst { map, rng } = ctx\n\t\t\tconst { width, depth } = map\n\t\t\tconst main = options.main ?? 8\n\t\t\tconst spacing = options.spacing ?? 20\n\t\t\tconst clearing = options.clearing ?? 3\n\t\t\tfor (const player of map.players) {\n\t\t\t\tif (!player.start || main === false) continue\n\t\t\t\tconst toward = atan2(depth / 2 - player.start.z, width / 2 - player.start.x) + (rng.next() - 0.5) * 0.8\n\t\t\t\tconst at = dryGround(ctx, { x: player.start.x + cos(toward) * main, z: player.start.z + sin(toward) * main }, 4)\n\t\t\t\t// on the start's level, its clearing reaching the start's: its workers walk to it\n\t\t\t\tif (clearing > 0) clear(ctx, at, clearing, true, ctx.levelAt(player.start.x, player.start.z))\n\t\t\t\tctx.mark('resource', at.x, at.z, 3)\n\t\t\t\toptions.from(ctx, at, player)\n\t\t\t}\n\t\t\tconst extra = Math.max(0, Math.round(options.extra ?? 2))\n\t\t\tlet placed = 0\n\t\t\tfor (let attempt = 0; attempt < extra * 40 && placed < extra; attempt++) {\n\t\t\t\tconst x = 4 + rng.next() * (width - 8)\n\t\t\t\tconst z = 4 + rng.next() * (depth - 8)\n\t\t\t\tif (!ctx.canonical(Math.floor(x), Math.floor(z))) continue\n\t\t\t\tconst places = ctx.symmetric(x, z)\n\t\t\t\tif (!places.every((place) => ctx.walkable(place.x, place.z) && ctx.free(place.x, place.z, spacing, ['start', 'resource']))) continue\n\t\t\t\tfor (const place of places) {\n\t\t\t\t\tconst at = dryGround(ctx, place, 4)\n\t\t\t\t\tif (clearing > 0) clear(ctx, at, clearing, true)\n\t\t\t\t\tctx.mark('resource', at.x, at.z, 3)\n\t\t\t\t\toptions.from(ctx, at)\n\t\t\t\t}\n\t\t\t\tplaced++\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ---- roads\n\n/**\n * What `roadsPass` takes\n *\n * @beta\n */\nexport interface RoadsPassOptions {\n\t/** The tile the road is painted with, by id */\n\ttile: string\n\t/** How wide, in cells: 2 when left out */\n\twidth?: number\n\t/** Between what: every two starts when left out, or places of the map's own */\n\tbetween?: Vec2[]\n}\n\n/**\n * Roads between the starts (or places given), the way something on foot would go (over the level map, by ramps, around\n * water; the gentlest ground preferred), painted with a tile\n *\n * @beta\n */\nexport function roadsPass(options: RoadsPassOptions): GeneratorPass {\n\treturn {\n\t\tid: 'roads',\n\t\tname: 'The roads',\n\t\trun(ctx) {\n\t\t\tconst { map, registry } = ctx\n\t\t\tif (!registry.tileIds.includes(options.tile)) return\n\t\t\tconst tile = registry.tile(options.tile)\n\t\t\tconst wide = Math.max(1, Math.round(options.width ?? 2))\n\t\t\tconst places = options.between ?? map.players.flatMap((player) => (player.start ? [player.start] : []))\n\t\t\tconst terrain = mapTerrain(map)\n\t\t\tfor (let i = 0; i < places.length; i++)\n\t\t\t\tfor (let j = i + 1; j < places.length; j++) {\n\t\t\t\t\tconst path = findPath(map, terrain, places[i], places[j])\n\t\t\t\t\tfor (const c of path) {\n\t\t\t\t\t\tconst cx = c % map.width\n\t\t\t\t\t\tconst cz = (c - cx) / map.width\n\t\t\t\t\t\tfor (let dz = 0; dz < wide; dz++)\n\t\t\t\t\t\t\tfor (let dx = 0; dx < wide; dx++) {\n\t\t\t\t\t\t\t\tconst x = cx + dx - Math.floor(wide / 2)\n\t\t\t\t\t\t\t\tconst z = cz + dz - Math.floor(wide / 2)\n\t\t\t\t\t\t\t\tif (on(map, x, z) && map.water[z * map.width + x] === WATER_NONE) map.tiles[z * map.width + x] = tile\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\t}\n}\n\n/** The cells of the way from one place to another over the level map: A* with the gentlest ground preferred; nothing where there is none */\nfunction findPath(map: GameMap, terrain: ReturnType<typeof mapTerrain>, from: Vec2, to: Vec2): number[] {\n\tconst { width, depth, levels, ramps, water } = map\n\tconst start = Math.floor(from.z) * width + Math.floor(from.x)\n\tconst goal = Math.floor(to.z) * width + Math.floor(to.x)\n\tconst passable = (a: number, b: number) => levels[a] === levels[b] || ramps[a] > 0 || ramps[b] > 0\n\tconst cost = new Float32Array(width * depth).fill(Infinity)\n\tconst came = new Int32Array(width * depth).fill(-1)\n\tconst closed = new Uint8Array(width * depth)\n\t// a heap of what is to be looked at, the nearest estimate first\n\tconst heapCells: number[] = []\n\tconst heapCosts: number[] = []\n\tconst push = (estimate: number, c: number) => {\n\t\theapCells.push(c)\n\t\theapCosts.push(estimate)\n\t\tlet i = heapCells.length - 1\n\t\twhile (i > 0) {\n\t\t\tconst parent = (i - 1) >> 1\n\t\t\tif (heapCosts[parent] <= heapCosts[i]) break\n\t\t\t;[heapCosts[parent], heapCosts[i]] = [heapCosts[i], heapCosts[parent]]\n\t\t\t;[heapCells[parent], heapCells[i]] = [heapCells[i], heapCells[parent]]\n\t\t\ti = parent\n\t\t}\n\t}\n\tconst pop = (): number => {\n\t\tconst top = heapCells[0]\n\t\tconst lastCell = heapCells.pop()!\n\t\tconst lastCost = heapCosts.pop()!\n\t\tif (heapCells.length) {\n\t\t\theapCells[0] = lastCell\n\t\t\theapCosts[0] = lastCost\n\t\t\tlet i = 0\n\t\t\tfor (;;) {\n\t\t\t\tconst l = i * 2 + 1\n\t\t\t\tconst r = l + 1\n\t\t\t\tlet best = i\n\t\t\t\tif (l < heapCells.length && heapCosts[l] < heapCosts[best]) best = l\n\t\t\t\tif (r < heapCells.length && heapCosts[r] < heapCosts[best]) best = r\n\t\t\t\tif (best === i) break\n\t\t\t\t;[heapCosts[best], heapCosts[i]] = [heapCosts[i], heapCosts[best]]\n\t\t\t\t;[heapCells[best], heapCells[i]] = [heapCells[i], heapCells[best]]\n\t\t\t\ti = best\n\t\t\t}\n\t\t}\n\t\treturn top\n\t}\n\tconst h = (c: number) => hypot((c % width) - (goal % width), Math.floor(c / width) - Math.floor(goal / width))\n\tcost[start] = 0\n\tpush(h(start), start)\n\twhile (heapCells.length) {\n\t\tconst c = pop()\n\t\tif (closed[c]) continue\n\t\tclosed[c] = 1\n\t\tif (c === goal) break\n\t\tconst cx = c % width\n\t\tconst cz = (c - cx) / width\n\t\tfor (const [dx, dz] of NEIGHBOURS) {\n\t\t\tconst nx = cx + dx\n\t\t\tconst nz = cz + dz\n\t\t\tif (!on(map, nx, nz)) continue\n\t\t\tconst n = nz * width + nx\n\t\t\tif (closed[n] || water[n] === WATER_DEEP || !passable(c, n)) continue\n\t\t\tconst step = 1 + terrain.slopeAt(nx + 0.5, nz + 0.5) * 4 + (water[n] ? 2 : 0)\n\t\t\tconst next = cost[c] + step\n\t\t\tif (next >= cost[n]) continue\n\t\t\tcost[n] = next\n\t\t\tcame[n] = c\n\t\t\tpush(next + h(n), n)\n\t\t}\n\t}\n\tif (came[goal] < 0 && goal !== start) return []\n\tconst path: number[] = []\n\tfor (let c = goal; c >= 0; c = came[c]) {\n\t\tpath.push(c)\n\t\tif (c === start) break\n\t}\n\treturn path.reverse()\n}\n\n// ---- a preset\n\n/**\n * What the engine's preset takes from a game: what its scenery is\n *\n * @beta\n */\nexport interface PresetGeneratorOptions {\n\t/** The models of trees, by their paths in `models/`: one picked for each. No trees when left out */\n\ttrees?: string[]\n\t/** How big a tree is drawn, and how much that varies: 1, by a fifth, when left out */\n\ttreeScale?: { scale?: number; vary?: number }\n\t/** The models of rocks, the same way. None when left out */\n\trocks?: string[]\n\t/** What a game puts at a start (`startsPass`): its hall and workers */\n\tstart?: StartsPassOptions['from']\n}\n\n/**\n * A generator to take whole: hills and water, the paint, the starts, trees in patches and rocks about, with the\n * parameters `levels`, `water`, `roughness`, `hills`, `trees` and `rocks`; what the trees and rocks are is the game's\n * to say\n *\n * @beta\n */\nexport function presetGenerator(options: PresetGeneratorOptions = {}): MapGenerator {\n\tconst { trees = [], rocks = [], treeScale = {} } = options\n\tconst scale = treeScale.scale ?? 1\n\tconst vary = treeScale.vary ?? 0.2\n\treturn {\n\t\tparams: [\n\t\t\t{ id: 'levels', name: 'Cliff levels', description: 'How many levels the ground rises through', default: 2, min: 1, max: 4, step: 1 },\n\t\t\t{ id: 'water', name: 'Water', description: 'How much of the map is under water', default: 0.15, min: 0, max: 0.5, step: 0.05 },\n\t\t\t{ id: 'roughness', name: 'Roughness', description: 'How much the ground rolls', default: 0.4, min: 0, max: 1, step: 0.05 },\n\t\t\t{ id: 'hills', name: 'Hills', description: 'How many cells a hill is across', default: 24, min: 8, max: 64, step: 4 },\n\t\t\t{ id: 'trees', name: 'Trees', description: 'How much of the map is woods', default: trees.length ? 0.12 : 0, min: 0, max: 0.5, step: 0.02 },\n\t\t\t{ id: 'rocks', name: 'Rocks', description: 'How many rocks lie about', default: rocks.length ? 0.02 : 0, min: 0, max: 0.2, step: 0.01 }\n\t\t],\n\t\tpasses: [\n\t\t\tterrainPass(),\n\t\t\ttilesPass(),\n\t\t\tstartsPass({ from: options.start }),\n\t\t\t...(trees.length\n\t\t\t\t? [\n\t\t\t\t\t\tscatterPass({\n\t\t\t\t\t\t\tkind: 'trees',\n\t\t\t\t\t\t\tspacing: 1.6,\n\t\t\t\t\t\t\twhat: (ctx, at) => {\n\t\t\t\t\t\t\t\tconst size = scale * (1 + (ctx.rng.next() - 0.5) * 2 * vary)\n\t\t\t\t\t\t\t\tctx.addDoodad({\n\t\t\t\t\t\t\t\t\tmodel: trees[ctx.rng.int(0, trees.length - 1)],\n\t\t\t\t\t\t\t\t\tx: at.x,\n\t\t\t\t\t\t\t\t\tz: at.z,\n\t\t\t\t\t\t\t\t\tyaw: ctx.rng.next() * Math.PI * 2,\n\t\t\t\t\t\t\t\t\tscale: size,\n\t\t\t\t\t\t\t\t\tblocks: 'walk',\n\t\t\t\t\t\t\t\t\tradius: 0.5\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t]\n\t\t\t\t: []),\n\t\t\t...(rocks.length\n\t\t\t\t? [\n\t\t\t\t\t\tscatterPass({\n\t\t\t\t\t\t\tkind: 'rocks',\n\t\t\t\t\t\t\tspacing: 3,\n\t\t\t\t\t\t\tpatches: 0.3,\n\t\t\t\t\t\t\tavoidKinds: { trees: 1 },\n\t\t\t\t\t\t\twhat: (ctx, at) => {\n\t\t\t\t\t\t\t\tconst size = scale * (0.8 + ctx.rng.next() * 0.6)\n\t\t\t\t\t\t\t\tctx.addDoodad({\n\t\t\t\t\t\t\t\t\tmodel: rocks[ctx.rng.int(0, rocks.length - 1)],\n\t\t\t\t\t\t\t\t\tx: at.x,\n\t\t\t\t\t\t\t\t\tz: at.z,\n\t\t\t\t\t\t\t\t\tyaw: ctx.rng.next() * Math.PI * 2,\n\t\t\t\t\t\t\t\t\tscale: size,\n\t\t\t\t\t\t\t\t\tblocks: 'walk',\n\t\t\t\t\t\t\t\t\tradius: 0.6\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t]\n\t\t\t\t: [])\n\t\t]\n\t}\n}\n"],"mappings":"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"}
|
package/dist/generateWorker.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type GeneratorOptions } from './generate';
|
|
2
|
-
import { type
|
|
2
|
+
import { type Rules } from './game';
|
|
3
|
+
import { type Game } from './createGame';
|
|
3
4
|
import type { GameMap } from './map';
|
|
4
5
|
import type { MapProblem } from './mapFields';
|
|
5
6
|
import type { NavigationPort, NavigationWorkerLike } from './navigation/builds';
|
|
@@ -9,8 +10,11 @@ import type { NavigationPort, NavigationWorkerLike } from './navigation/builds';
|
|
|
9
10
|
* @beta
|
|
10
11
|
*/
|
|
11
12
|
export interface GeneratedMap {
|
|
13
|
+
/** The map the generator made */
|
|
12
14
|
map: GameMap;
|
|
15
|
+
/** What is wrong with the map, as `MapProblem`s found when it was checked */
|
|
13
16
|
problems: MapProblem[];
|
|
17
|
+
/** The seed the map came out of */
|
|
14
18
|
seed: number;
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
@@ -21,14 +25,14 @@ export interface GeneratedMap {
|
|
|
21
25
|
*/
|
|
22
26
|
export type MapGenerating = (options: GeneratorOptions) => Promise<GeneratedMap>;
|
|
23
27
|
/**
|
|
24
|
-
* What a worker's file of a game's maps does: it makes, with the game's generator (`
|
|
28
|
+
* What a worker's file of a game's maps does: it makes, with the game's generator (`Rules.generator`) and its
|
|
25
29
|
* registry, the map of each set of options it is sent, and sends it back. A worker's file of two lines, the game's rules
|
|
26
30
|
* imported and this called with them; `port` is where it hears, as for `serveNavigationBuilds`: the worker's own scope
|
|
27
31
|
* when left out
|
|
28
32
|
*
|
|
29
33
|
* @beta
|
|
30
34
|
*/
|
|
31
|
-
export declare function serveMapGenerator(
|
|
35
|
+
export declare function serveMapGenerator(game: Game<unknown> | Rules, port?: NavigationPort): void;
|
|
32
36
|
/**
|
|
33
37
|
* Maps made in a worker whose file serves them (`serveMapGenerator`): the page makes the worker as its bundler wants it,
|
|
34
38
|
* `mapGeneratorWorker(() => new Worker(new URL('./generate.worker.ts', import.meta.url), { type: 'module' }))`. Given
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createRegistry } from "./game.js";
|
|
2
|
+
import { generateMap } from "./generate.js";
|
|
3
|
+
import { rulesOf } from "./createGame.js";
|
|
4
|
+
//#region src/generateWorker.ts
|
|
5
|
+
/**
|
|
6
|
+
* What a worker's file of a game's maps does: it makes, with the game's generator (`Rules.generator`) and its
|
|
7
|
+
* registry, the map of each set of options it is sent, and sends it back. A worker's file of two lines, the game's rules
|
|
8
|
+
* imported and this called with them; `port` is where it hears, as for `serveNavigationBuilds`: the worker's own scope
|
|
9
|
+
* when left out
|
|
10
|
+
*
|
|
11
|
+
* @beta
|
|
12
|
+
*/
|
|
13
|
+
function serveMapGenerator(game, port = globalThis) {
|
|
14
|
+
const rules = rulesOf(game);
|
|
15
|
+
let registry;
|
|
16
|
+
const asked = (message) => {
|
|
17
|
+
const { id, options } = message;
|
|
18
|
+
try {
|
|
19
|
+
if (!rules.generator) throw new Error(`${rules.name} has no generator of maps (Rules.generator)`);
|
|
20
|
+
registry ??= createRegistry(rules);
|
|
21
|
+
port.postMessage({
|
|
22
|
+
id,
|
|
23
|
+
made: generateMap(rules.generator, options, registry)
|
|
24
|
+
});
|
|
25
|
+
} catch (error) {
|
|
26
|
+
port.postMessage({
|
|
27
|
+
id,
|
|
28
|
+
error: error instanceof Error ? error.message : String(error)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
if (port.on) port.on("message", asked);
|
|
33
|
+
else port.addEventListener?.("message", (event) => asked(event.data));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Maps made in a worker whose file serves them (`serveMapGenerator`): the page makes the worker as its bundler wants it,
|
|
37
|
+
* `mapGeneratorWorker(() => new Worker(new URL('./generate.worker.ts', import.meta.url), { type: 'module' }))`. Given
|
|
38
|
+
* as a function, the worker is made at the first map asked for: a menu that is never opened fetches none of it
|
|
39
|
+
*
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
function mapGeneratorWorker(given) {
|
|
43
|
+
let next = 0;
|
|
44
|
+
const waiting = /* @__PURE__ */ new Map();
|
|
45
|
+
const answered = (answer) => {
|
|
46
|
+
const wait = waiting.get(answer.id);
|
|
47
|
+
if (!wait) return;
|
|
48
|
+
waiting.delete(answer.id);
|
|
49
|
+
if (answer.made) wait.done(answer.made);
|
|
50
|
+
else wait.failed(new Error(answer.error ?? "The map could not be made"));
|
|
51
|
+
};
|
|
52
|
+
const broke = (error) => {
|
|
53
|
+
const reason = /* @__PURE__ */ new Error(`The maps' worker stopped: ${error instanceof Error ? error.message : String(error?.message ?? error)}`);
|
|
54
|
+
for (const wait of waiting.values()) wait.failed(reason);
|
|
55
|
+
waiting.clear();
|
|
56
|
+
};
|
|
57
|
+
let made;
|
|
58
|
+
const worker = () => {
|
|
59
|
+
if (made) return made;
|
|
60
|
+
made = typeof given === "function" ? given() : given;
|
|
61
|
+
if (made.on) {
|
|
62
|
+
made.on("message", (value) => answered(value));
|
|
63
|
+
made.on("error", broke);
|
|
64
|
+
} else {
|
|
65
|
+
made.addEventListener?.("message", (event) => answered(event.data));
|
|
66
|
+
made.addEventListener?.("error", broke);
|
|
67
|
+
}
|
|
68
|
+
return made;
|
|
69
|
+
};
|
|
70
|
+
if (typeof given !== "function") worker();
|
|
71
|
+
return (options) => new Promise((done, failed) => {
|
|
72
|
+
const id = ++next;
|
|
73
|
+
waiting.set(id, {
|
|
74
|
+
done,
|
|
75
|
+
failed
|
|
76
|
+
});
|
|
77
|
+
worker().postMessage({
|
|
78
|
+
id,
|
|
79
|
+
options
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
export { mapGeneratorWorker, serveMapGenerator };
|
|
85
|
+
|
|
86
|
+
//# sourceMappingURL=generateWorker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateWorker.js","names":[],"sources":["../src/generateWorker.ts"],"sourcesContent":["import { generateMap, type GeneratorOptions } from './generate'\nimport { createRegistry, type Rules } from './game'\nimport { type Game, rulesOf } from './createGame'\nimport type { GameMap } from './map'\nimport type { MapProblem } from './mapFields'\nimport type { NavigationPort, NavigationWorkerLike } from './navigation/builds'\nimport type { Registry } from './registry'\n\n/**\n * A map a generator made (`generateMap`): the map, what is wrong with it, and the seed it came out of\n *\n * @beta\n */\nexport interface GeneratedMap {\n\t/** The map the generator made */\n\tmap: GameMap\n\t/** What is wrong with the map, as `MapProblem`s found when it was checked */\n\tproblems: MapProblem[]\n\t/** The seed the map came out of */\n\tseed: number\n}\n\n/**\n * Makes a map of options somewhere else than this thread (`mapGeneratorWorker`): a menu's preview of a random map that\n * does not stop the page while it is made\n *\n * @beta\n */\nexport type MapGenerating = (options: GeneratorOptions) => Promise<GeneratedMap>\n\ninterface GenerateAnswer {\n\tid: number\n\tmade?: GeneratedMap\n\terror?: string\n}\n\n/**\n * What a worker's file of a game's maps does: it makes, with the game's generator (`Rules.generator`) and its\n * registry, the map of each set of options it is sent, and sends it back. A worker's file of two lines, the game's rules\n * imported and this called with them; `port` is where it hears, as for `serveNavigationBuilds`: the worker's own scope\n * when left out\n *\n * @beta\n */\nexport function serveMapGenerator(game: Game<unknown> | Rules, port: NavigationPort = globalThis as unknown as NavigationPort): void {\n\tconst rules = rulesOf(game)\n\tlet registry: Registry | undefined\n\tconst asked = (message: unknown) => {\n\t\tconst { id, options } = message as { id: number; options: GeneratorOptions }\n\t\ttry {\n\t\t\tif (!rules.generator) throw new Error(`${rules.name} has no generator of maps (Rules.generator)`)\n\t\t\tregistry ??= createRegistry(rules)\n\t\t\tport.postMessage({ id, made: generateMap(rules.generator, options, registry) } satisfies GenerateAnswer)\n\t\t} catch (error) {\n\t\t\tport.postMessage({ id, error: error instanceof Error ? error.message : String(error) } satisfies GenerateAnswer)\n\t\t}\n\t}\n\tif (port.on) port.on('message', asked)\n\telse port.addEventListener?.('message', (event) => asked(event.data))\n}\n\n/**\n * Maps made in a worker whose file serves them (`serveMapGenerator`): the page makes the worker as its bundler wants it,\n * `mapGeneratorWorker(() => new Worker(new URL('./generate.worker.ts', import.meta.url), { type: 'module' }))`. Given\n * as a function, the worker is made at the first map asked for: a menu that is never opened fetches none of it\n *\n * @beta\n */\nexport function mapGeneratorWorker(given: NavigationWorkerLike | (() => NavigationWorkerLike)): MapGenerating {\n\tlet next = 0\n\tconst waiting = new Map<number, { done: (made: GeneratedMap) => void; failed: (error: Error) => void }>()\n\tconst answered = (answer: GenerateAnswer) => {\n\t\tconst wait = waiting.get(answer.id)\n\t\tif (!wait) return\n\t\twaiting.delete(answer.id)\n\t\tif (answer.made) wait.done(answer.made)\n\t\telse wait.failed(new Error(answer.error ?? 'The map could not be made'))\n\t}\n\tconst broke = (error: unknown) => {\n\t\tconst reason = new Error(\n\t\t\t`The maps' worker stopped: ${error instanceof Error ? error.message : String((error as { message?: string })?.message ?? error)}`\n\t\t)\n\t\tfor (const wait of waiting.values()) wait.failed(reason)\n\t\twaiting.clear()\n\t}\n\tlet made: NavigationWorkerLike | undefined\n\tconst worker = () => {\n\t\tif (made) return made\n\t\tmade = typeof given === 'function' ? given() : given\n\t\tif (made.on) {\n\t\t\tmade.on('message', (value) => answered(value as GenerateAnswer))\n\t\t\tmade.on('error', broke)\n\t\t} else {\n\t\t\tmade.addEventListener?.('message', (event) => answered(event.data as GenerateAnswer))\n\t\t\tmade.addEventListener?.('error', broke)\n\t\t}\n\t\treturn made\n\t}\n\tif (typeof given !== 'function') worker()\n\treturn (options) =>\n\t\tnew Promise<GeneratedMap>((done, failed) => {\n\t\t\tconst id = ++next\n\t\t\twaiting.set(id, { done, failed })\n\t\t\tworker().postMessage({ id, options })\n\t\t})\n}\n"],"mappings":";;;;;;;;;;;;AA4CA,SAAgB,kBAAkB,MAA6B,OAAuB,YAA+C;CACpI,MAAM,QAAQ,QAAQ,IAAI;CAC1B,IAAI;CACJ,MAAM,SAAS,YAAqB;EACnC,MAAM,EAAE,IAAI,YAAY;EACxB,IAAI;GACH,IAAI,CAAC,MAAM,WAAW,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,4CAA4C;GAChG,aAAa,eAAe,KAAK;GACjC,KAAK,YAAY;IAAE;IAAI,MAAM,YAAY,MAAM,WAAW,SAAS,QAAQ;GAAE,CAA0B;EACxG,SAAS,OAAO;GACf,KAAK,YAAY;IAAE;IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAAE,CAA0B;EAChH;CACD;CACA,IAAI,KAAK,IAAI,KAAK,GAAG,WAAW,KAAK;MAChC,KAAK,mBAAmB,YAAY,UAAU,MAAM,MAAM,IAAI,CAAC;AACrE;;;;;;;;AASA,SAAgB,mBAAmB,OAA2E;CAC7G,IAAI,OAAO;CACX,MAAM,0BAAU,IAAI,IAAoF;CACxG,MAAM,YAAY,WAA2B;EAC5C,MAAM,OAAO,QAAQ,IAAI,OAAO,EAAE;EAClC,IAAI,CAAC,MAAM;EACX,QAAQ,OAAO,OAAO,EAAE;EACxB,IAAI,OAAO,MAAM,KAAK,KAAK,OAAO,IAAI;OACjC,KAAK,OAAO,IAAI,MAAM,OAAO,SAAS,2BAA2B,CAAC;CACxE;CACA,MAAM,SAAS,UAAmB;EACjC,MAAM,yBAAS,IAAI,MAClB,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAQ,OAAgC,WAAW,KAAK,GAC/H;EACA,KAAK,MAAM,QAAQ,QAAQ,OAAO,GAAG,KAAK,OAAO,MAAM;EACvD,QAAQ,MAAM;CACf;CACA,IAAI;CACJ,MAAM,eAAe;EACpB,IAAI,MAAM,OAAO;EACjB,OAAO,OAAO,UAAU,aAAa,MAAM,IAAI;EAC/C,IAAI,KAAK,IAAI;GACZ,KAAK,GAAG,YAAY,UAAU,SAAS,KAAuB,CAAC;GAC/D,KAAK,GAAG,SAAS,KAAK;EACvB,OAAO;GACN,KAAK,mBAAmB,YAAY,UAAU,SAAS,MAAM,IAAsB,CAAC;GACpF,KAAK,mBAAmB,SAAS,KAAK;EACvC;EACA,OAAO;CACR;CACA,IAAI,OAAO,UAAU,YAAY,OAAO;CACxC,QAAQ,YACP,IAAI,SAAuB,MAAM,WAAW;EAC3C,MAAM,KAAK,EAAE;EACb,QAAQ,IAAI,IAAI;GAAE;GAAM;EAAO,CAAC;EAChC,OAAO,CAAC,CAAC,YAAY;GAAE;GAAI;EAAQ,CAAC;CACrC,CAAC;AACH"}
|
package/dist/grid.d.ts
CHANGED
|
@@ -20,7 +20,9 @@ export interface GridOptions {
|
|
|
20
20
|
*/
|
|
21
21
|
export declare class BuildGrid {
|
|
22
22
|
private readonly terrain;
|
|
23
|
+
/** The grid's width in cells, the map's width */
|
|
23
24
|
readonly width: number;
|
|
25
|
+
/** The grid's depth in cells, the map's depth */
|
|
24
26
|
readonly depth: number;
|
|
25
27
|
/** Id of the structure occupying each cell, 0 when free */
|
|
26
28
|
private readonly occupant;
|
|
@@ -38,16 +40,23 @@ export declare class BuildGrid {
|
|
|
38
40
|
width: number;
|
|
39
41
|
depth: number;
|
|
40
42
|
}): void;
|
|
43
|
+
/** Whether the cell `(x, z)` is on the grid */
|
|
41
44
|
inBounds(x: number, z: number): boolean;
|
|
45
|
+
/** The id of the structure standing on the cell, 0 when none does and -1 when the cell is off the grid */
|
|
42
46
|
occupantAt(x: number, z: number): number;
|
|
47
|
+
/** Whether a structure may be put on the cell by the ground alone: on the grid, flat enough, dry, not at the edge or blocked */
|
|
43
48
|
isBuildable(x: number, z: number): boolean;
|
|
49
|
+
/** Whether the cell is buildable and has no structure on it */
|
|
44
50
|
isFree(x: number, z: number): boolean;
|
|
45
51
|
/** Min cell of a footprint centered as close as possible to the given point */
|
|
46
52
|
cellFor(x: number, z: number, w: number, d: number): {
|
|
47
53
|
x: number;
|
|
48
54
|
z: number;
|
|
49
55
|
};
|
|
56
|
+
/** Whether a footprint of `w` by `d` cells with its first cell at `(cellX, cellZ)` is free and on ground level enough to build on */
|
|
50
57
|
canPlace(cellX: number, cellZ: number, w: number, d: number): boolean;
|
|
58
|
+
/** Marks the footprint's cells as taken by the structure `id`; cells off the grid are skipped */
|
|
51
59
|
occupy(cellX: number, cellZ: number, w: number, d: number, id: number): void;
|
|
60
|
+
/** Frees the footprint's cells that the structure `id` holds; cells held by another id are left */
|
|
52
61
|
release(cellX: number, cellZ: number, w: number, d: number, id: number): void;
|
|
53
62
|
}
|
package/dist/grid.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
//#region src/grid.ts
|
|
2
|
+
/**
|
|
3
|
+
* Min cell of a footprint centered as close as possible to the given point
|
|
4
|
+
*
|
|
5
|
+
* @beta
|
|
6
|
+
*/
|
|
7
|
+
var footprintCell = (x, z, w, d) => ({
|
|
8
|
+
x: Math.round(x - w / 2),
|
|
9
|
+
z: Math.round(z - d / 2)
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Placement grid. One cell per world unit, tracking where structures stand and
|
|
13
|
+
* where the ground is flat enough to build.
|
|
14
|
+
*
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
var BuildGrid = class {
|
|
18
|
+
terrain;
|
|
19
|
+
/** The grid's width in cells, the map's width */
|
|
20
|
+
width;
|
|
21
|
+
/** The grid's depth in cells, the map's depth */
|
|
22
|
+
depth;
|
|
23
|
+
/** Id of the structure occupying each cell, 0 when free */
|
|
24
|
+
occupant;
|
|
25
|
+
buildable;
|
|
26
|
+
/** The steepest a cell is built on */
|
|
27
|
+
maxBuildSlope;
|
|
28
|
+
constructor(terrain, options = {}) {
|
|
29
|
+
this.terrain = terrain;
|
|
30
|
+
this.maxBuildSlope = options.maxBuildSlope ?? .3;
|
|
31
|
+
this.width = terrain.width;
|
|
32
|
+
this.depth = terrain.depth;
|
|
33
|
+
this.occupant = new Int32Array(this.width * this.depth);
|
|
34
|
+
this.buildable = new Uint8Array(this.width * this.depth);
|
|
35
|
+
this.groundChanged({
|
|
36
|
+
x: 0,
|
|
37
|
+
z: 0,
|
|
38
|
+
width: this.width,
|
|
39
|
+
depth: this.depth
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Works out again where can be built, in a rectangle of cells and the ring about it (a slope is of the vertices about a
|
|
44
|
+
* cell): after the ground was reshaped there (`World.reshapeGround`). What stands there stays where it is
|
|
45
|
+
*/
|
|
46
|
+
groundChanged(rect) {
|
|
47
|
+
const { terrain } = this;
|
|
48
|
+
const x0 = Math.max(rect.x - 1, 0);
|
|
49
|
+
const z0 = Math.max(rect.z - 1, 0);
|
|
50
|
+
const x1 = Math.min(rect.x + rect.width + 1, this.width);
|
|
51
|
+
const z1 = Math.min(rect.z + rect.depth + 1, this.depth);
|
|
52
|
+
for (let z = z0; z < z1; z++) for (let x = x0; x < x1; x++) {
|
|
53
|
+
const edge = x < 1 || z < 1 || x >= this.width - 1 || z >= this.depth - 1 || !terrain.inPlay(x, z) || terrain.blocked[z * this.width + x] > 0;
|
|
54
|
+
const wet = terrain.water[z * this.width + x] !== 0;
|
|
55
|
+
this.buildable[z * this.width + x] = !edge && !wet && terrain.slopeAt(x + .5, z + .5) <= this.maxBuildSlope ? 1 : 0;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Whether the cell `(x, z)` is on the grid */
|
|
59
|
+
inBounds(x, z) {
|
|
60
|
+
return x >= 0 && z >= 0 && x < this.width && z < this.depth;
|
|
61
|
+
}
|
|
62
|
+
/** The id of the structure standing on the cell, 0 when none does and -1 when the cell is off the grid */
|
|
63
|
+
occupantAt(x, z) {
|
|
64
|
+
return this.inBounds(x, z) ? this.occupant[z * this.width + x] : -1;
|
|
65
|
+
}
|
|
66
|
+
/** Whether a structure may be put on the cell by the ground alone: on the grid, flat enough, dry, not at the edge or blocked */
|
|
67
|
+
isBuildable(x, z) {
|
|
68
|
+
return this.inBounds(x, z) && this.buildable[z * this.width + x] === 1;
|
|
69
|
+
}
|
|
70
|
+
/** Whether the cell is buildable and has no structure on it */
|
|
71
|
+
isFree(x, z) {
|
|
72
|
+
return this.isBuildable(x, z) && this.occupant[z * this.width + x] === 0;
|
|
73
|
+
}
|
|
74
|
+
/** Min cell of a footprint centered as close as possible to the given point */
|
|
75
|
+
cellFor(x, z, w, d) {
|
|
76
|
+
return footprintCell(x, z, w, d);
|
|
77
|
+
}
|
|
78
|
+
/** Whether a footprint of `w` by `d` cells with its first cell at `(cellX, cellZ)` is free and on ground level enough to build on */
|
|
79
|
+
canPlace(cellX, cellZ, w, d) {
|
|
80
|
+
let min = Infinity;
|
|
81
|
+
let max = -Infinity;
|
|
82
|
+
for (let z = cellZ; z < cellZ + d; z++) for (let x = cellX; x < cellX + w; x++) if (!this.isFree(x, z)) return false;
|
|
83
|
+
for (let z = cellZ; z <= cellZ + d; z++) for (let x = cellX; x <= cellX + w; x++) {
|
|
84
|
+
const h = this.terrain.vertexHeight(x, z);
|
|
85
|
+
if (h < min) min = h;
|
|
86
|
+
if (h > max) max = h;
|
|
87
|
+
}
|
|
88
|
+
return max - min <= .2 * Math.max(w, d) + .4;
|
|
89
|
+
}
|
|
90
|
+
/** Marks the footprint's cells as taken by the structure `id`; cells off the grid are skipped */
|
|
91
|
+
occupy(cellX, cellZ, w, d, id) {
|
|
92
|
+
for (let z = cellZ; z < cellZ + d; z++) for (let x = cellX; x < cellX + w; x++) if (this.inBounds(x, z)) this.occupant[z * this.width + x] = id;
|
|
93
|
+
}
|
|
94
|
+
/** Frees the footprint's cells that the structure `id` holds; cells held by another id are left */
|
|
95
|
+
release(cellX, cellZ, w, d, id) {
|
|
96
|
+
for (let z = cellZ; z < cellZ + d; z++) for (let x = cellX; x < cellX + w; x++) if (this.inBounds(x, z) && this.occupant[z * this.width + x] === id) this.occupant[z * this.width + x] = 0;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
100
|
+
export { BuildGrid, footprintCell };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=grid.js.map
|
package/dist/grid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","names":[],"sources":["../src/grid.ts"],"sourcesContent":["import type { Terrain } from './terrain'\n\n/**\n * Min cell of a footprint centered as close as possible to the given point\n *\n * @beta\n */\nexport const footprintCell = (x: number, z: number, w: number, d: number) => ({ x: Math.round(x - w / 2), z: Math.round(z - d / 2) })\n\nexport interface GridOptions {\n\t/** Steepest slope (radians) that can be built on */\n\tmaxBuildSlope?: number\n}\n\n/**\n * Placement grid. One cell per world unit, tracking where structures stand and\n * where the ground is flat enough to build.\n *\n * @beta\n */\nexport class BuildGrid {\n\t/** The grid's width in cells, the map's width */\n\treadonly width: number\n\t/** The grid's depth in cells, the map's depth */\n\treadonly depth: number\n\t/** Id of the structure occupying each cell, 0 when free */\n\tprivate readonly occupant: Int32Array\n\tprivate readonly buildable: Uint8Array\n\n\t/** The steepest a cell is built on */\n\tprivate readonly maxBuildSlope: number\n\n\tconstructor(\n\t\tprivate readonly terrain: Terrain,\n\t\toptions: GridOptions = {}\n\t) {\n\t\tthis.maxBuildSlope = options.maxBuildSlope ?? 0.3\n\t\tthis.width = terrain.width\n\t\tthis.depth = terrain.depth\n\t\tthis.occupant = new Int32Array(this.width * this.depth)\n\t\tthis.buildable = new Uint8Array(this.width * this.depth)\n\t\tthis.groundChanged({ x: 0, z: 0, width: this.width, depth: this.depth })\n\t}\n\n\t/**\n\t * Works out again where can be built, in a rectangle of cells and the ring about it (a slope is of the vertices about a\n\t * cell): after the ground was reshaped there (`World.reshapeGround`). What stands there stays where it is\n\t */\n\tgroundChanged(rect: { x: number; z: number; width: number; depth: number }): void {\n\t\tconst { terrain } = this\n\t\tconst x0 = Math.max(rect.x - 1, 0)\n\t\tconst z0 = Math.max(rect.z - 1, 0)\n\t\tconst x1 = Math.min(rect.x + rect.width + 1, this.width)\n\t\tconst z1 = Math.min(rect.z + rect.depth + 1, this.depth)\n\t\tfor (let z = z0; z < z1; z++) {\n\t\t\tfor (let x = x0; x < x1; x++) {\n\t\t\t\tconst edge = x < 1 || z < 1 || x >= this.width - 1 || z >= this.depth - 1 || !terrain.inPlay(x, z) || terrain.blocked[z * this.width + x] > 0\n\t\t\t\tconst wet = terrain.water[z * this.width + x] !== 0\n\t\t\t\tthis.buildable[z * this.width + x] = !edge && !wet && terrain.slopeAt(x + 0.5, z + 0.5) <= this.maxBuildSlope ? 1 : 0\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Whether the cell `(x, z)` is on the grid */\n\tinBounds(x: number, z: number): boolean {\n\t\treturn x >= 0 && z >= 0 && x < this.width && z < this.depth\n\t}\n\n\t/** The id of the structure standing on the cell, 0 when none does and -1 when the cell is off the grid */\n\toccupantAt(x: number, z: number): number {\n\t\treturn this.inBounds(x, z) ? this.occupant[z * this.width + x] : -1\n\t}\n\n\t/** Whether a structure may be put on the cell by the ground alone: on the grid, flat enough, dry, not at the edge or blocked */\n\tisBuildable(x: number, z: number): boolean {\n\t\treturn this.inBounds(x, z) && this.buildable[z * this.width + x] === 1\n\t}\n\n\t/** Whether the cell is buildable and has no structure on it */\n\tisFree(x: number, z: number): boolean {\n\t\treturn this.isBuildable(x, z) && this.occupant[z * this.width + x] === 0\n\t}\n\n\t/** Min cell of a footprint centered as close as possible to the given point */\n\tcellFor(x: number, z: number, w: number, d: number): { x: number; z: number } {\n\t\treturn footprintCell(x, z, w, d)\n\t}\n\n\t/** Whether a footprint of `w` by `d` cells with its first cell at `(cellX, cellZ)` is free and on ground level enough to build on */\n\tcanPlace(cellX: number, cellZ: number, w: number, d: number): boolean {\n\t\tlet min = Infinity\n\t\tlet max = -Infinity\n\t\tfor (let z = cellZ; z < cellZ + d; z++) {\n\t\t\tfor (let x = cellX; x < cellX + w; x++) {\n\t\t\t\tif (!this.isFree(x, z)) return false\n\t\t\t}\n\t\t}\n\t\tfor (let z = cellZ; z <= cellZ + d; z++) {\n\t\t\tfor (let x = cellX; x <= cellX + w; x++) {\n\t\t\t\tconst h = this.terrain.vertexHeight(x, z)\n\t\t\t\tif (h < min) min = h\n\t\t\t\tif (h > max) max = h\n\t\t\t}\n\t\t}\n\t\treturn max - min <= 0.2 * Math.max(w, d) + 0.4\n\t}\n\n\t/** Marks the footprint's cells as taken by the structure `id`; cells off the grid are skipped */\n\toccupy(cellX: number, cellZ: number, w: number, d: number, id: number): void {\n\t\tfor (let z = cellZ; z < cellZ + d; z++) {\n\t\t\tfor (let x = cellX; x < cellX + w; x++) {\n\t\t\t\tif (this.inBounds(x, z)) this.occupant[z * this.width + x] = id\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Frees the footprint's cells that the structure `id` holds; cells held by another id are left */\n\trelease(cellX: number, cellZ: number, w: number, d: number, id: number): void {\n\t\tfor (let z = cellZ; z < cellZ + d; z++) {\n\t\t\tfor (let x = cellX; x < cellX + w; x++) {\n\t\t\t\tif (this.inBounds(x, z) && this.occupant[z * this.width + x] === id) this.occupant[z * this.width + x] = 0\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
package/dist/ground.d.ts
CHANGED
|
@@ -14,8 +14,11 @@ export type SavedGround = TerrainSave | GroundChanges;
|
|
|
14
14
|
export interface GroundChanges {
|
|
15
15
|
/** The map it started as, by its name (`GameMap.name`) and a hash of the ground it makes (`groundHash`) */
|
|
16
16
|
map: string;
|
|
17
|
+
/** A hash of the ground the map makes, which tells the ground of a save or a welcome is the one it was taken from */
|
|
17
18
|
hash: string;
|
|
19
|
+
/** The ground's width in cells */
|
|
18
20
|
width: number;
|
|
21
|
+
/** The ground's depth in cells */
|
|
19
22
|
depth: number;
|
|
20
23
|
/** For each layer that changed: which cells (packed as 32-bit numbers), and what each holds now */
|
|
21
24
|
changes: Partial<Record<GroundLayer, {
|
|
@@ -38,7 +41,11 @@ export interface GroundChanges {
|
|
|
38
41
|
};
|
|
39
42
|
}
|
|
40
43
|
declare const LAYERS: readonly ['heights', 'levels', 'water', 'waterHeights', 'tiles', 'blocked'];
|
|
41
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* A layer of the ground that can change: `heights`, `levels`, `water`, `waterHeights`, `tiles` or `blocked`
|
|
46
|
+
*
|
|
47
|
+
* @beta
|
|
48
|
+
*/
|
|
42
49
|
export type GroundLayer = (typeof LAYERS)[number];
|
|
43
50
|
/**
|
|
44
51
|
* Whether a save's ground is the changes of a map, not the whole of it
|
|
@@ -58,9 +65,11 @@ export declare function groundHash(terrain: Terrain): string;
|
|
|
58
65
|
* @beta
|
|
59
66
|
*/
|
|
60
67
|
export interface GroundBase {
|
|
68
|
+
/** The name of the map the ground started as (`GameMap.name`) */
|
|
61
69
|
map: string;
|
|
62
70
|
/** A hash of the ground (`groundHash`): worked out the first time it is asked for */
|
|
63
71
|
readonly hash: string;
|
|
72
|
+
/** The ground itself, with the changes of play not yet laid on it */
|
|
64
73
|
terrain: Terrain;
|
|
65
74
|
}
|
|
66
75
|
/**
|
|
@@ -73,16 +82,23 @@ export interface GroundBase {
|
|
|
73
82
|
export interface TerrainPatch {
|
|
74
83
|
/** The first cell, and how many across and down */
|
|
75
84
|
x: number;
|
|
85
|
+
/** The patch's first cell on the z axis, in cells */
|
|
76
86
|
z: number;
|
|
87
|
+
/** How many cells across the patch is */
|
|
77
88
|
width: number;
|
|
89
|
+
/** How many cells down the patch is */
|
|
78
90
|
depth: number;
|
|
79
91
|
/** Per vertex, row by row: `(width + 1) * (depth + 1)` of them */
|
|
80
92
|
heights: number[];
|
|
93
|
+
/** Heights of the water at the patch's vertices, in the order of `heights` */
|
|
81
94
|
waterHeights: number[];
|
|
82
95
|
/** Per cell, row by row: `width * depth` of them */
|
|
83
96
|
levels: number[];
|
|
97
|
+
/** Per cell, the water there (0 for none) */
|
|
84
98
|
water: number[];
|
|
99
|
+
/** Per cell, the tile there (an index into the game's tiles) */
|
|
85
100
|
tiles: number[];
|
|
101
|
+
/** Per cell, whether the cell is blocked for walking (0 for no) */
|
|
86
102
|
blocked: number[];
|
|
87
103
|
/** The game's layers of cells (`Terrain.cells`), by id, per cell: those in either ground */
|
|
88
104
|
cells?: Record<string, number[]>;
|