@datamoc/mw_games 0.43.0 → 0.45.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/3d/models.d.ts +1 -0
- package/3d/models.js +1 -0
- package/3d.d.ts +1 -0
- package/3d.js +1 -0
- package/README.md +5 -710
- package/actors.d.ts +1 -0
- package/actors.js +1 -0
- package/ai/lua.d.ts +1 -0
- package/ai/lua.js +1 -0
- package/ai.d.ts +1 -0
- package/ai.js +1 -0
- package/assets/binary.d.ts +1 -0
- package/assets/binary.js +1 -0
- package/assets/paths.d.ts +1 -0
- package/assets/paths.js +1 -0
- package/assets.d.ts +1 -0
- package/assets.js +1 -0
- package/audio.d.ts +1 -0
- package/audio.js +1 -0
- package/battle.d.ts +1 -0
- package/battle.js +1 -0
- package/board.d.ts +1 -0
- package/board.js +1 -0
- package/core.d.ts +1 -0
- package/core.js +1 -0
- package/headless.d.ts +1 -0
- package/headless.js +1 -0
- package/i18n.d.ts +1 -0
- package/i18n.js +1 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/mwl/presentation.d.ts +1 -0
- package/mwl/presentation.js +1 -0
- package/mwl/pyroeis.d.ts +1 -0
- package/mwl/pyroeis.js +1 -0
- package/mwl.d.ts +1 -0
- package/mwl.js +1 -0
- package/package.json +212 -387
- package/physics/xpbd.d.ts +1 -0
- package/physics/xpbd.js +1 -0
- package/physics.d.ts +1 -0
- package/physics.js +1 -0
- package/roguelike.d.ts +1 -0
- package/roguelike.js +1 -0
- package/rpg.d.ts +1 -0
- package/rpg.js +1 -0
- package/simulation.d.ts +1 -0
- package/simulation.js +1 -0
- package/skeleton.d.ts +1 -0
- package/skeleton.js +1 -0
- package/testing.d.ts +1 -0
- package/testing.js +1 -0
- package/threads.d.ts +1 -0
- package/threads.js +1 -0
- package/tools/asset-report.d.mts +1 -37
- package/tools/asset-report.mjs +1 -157
- package/tools/audio.d.mts +1 -0
- package/tools/audio.mjs +1 -0
- package/tools/audit-adoptions.d.mts +1 -65
- package/tools/audit-adoptions.mjs +1 -252
- package/tools/benchmark-browser.d.mts +1 -33
- package/tools/benchmark-browser.mjs +1 -169
- package/tools/benchmark-history.d.mts +1 -8
- package/tools/benchmark-history.mjs +1 -31
- package/tools/browser-driver.d.mts +1 -122
- package/tools/browser-driver.mjs +1 -861
- package/tools/browser-smoke.d.mts +1 -30
- package/tools/browser-smoke.mjs +1 -184
- package/tools/build-tablebases.d.mts +1 -22
- package/tools/build-tablebases.mjs +1 -557
- package/tools/bundle-size.d.mts +1 -11
- package/tools/bundle-size.mjs +1 -142
- package/tools/classic-html.d.mts +1 -6
- package/tools/classic-html.mjs +1 -69
- package/tools/compile-openings.d.mts +1 -20
- package/tools/compile-openings.mjs +1 -138
- package/tools/compile-resources.d.mts +1 -66
- package/tools/compile-resources.mjs +1 -406
- package/tools/compress-dist.d.mts +1 -42
- package/tools/compress-dist.mjs +1 -193
- package/tools/csp.d.mts +1 -7
- package/tools/csp.mjs +1 -65
- package/tools/emit-page.d.mts +1 -61
- package/tools/emit-page.mjs +1 -273
- package/tools/extract-html.d.mts +1 -18
- package/tools/extract-html.mjs +1 -235
- package/tools/extract-rgssad.d.mts +1 -5
- package/tools/extract-rgssad.mjs +1 -64
- package/tools/find-chrome.d.mts +1 -7
- package/tools/find-chrome.mjs +1 -106
- package/tools/i18n-edit.d.mts +1 -29
- package/tools/i18n-edit.mjs +1 -748
- package/tools/init.d.mts +1 -5
- package/tools/init.mjs +1 -155
- package/tools/make-example-assets.d.mts +1 -2
- package/tools/make-example-assets.mjs +1 -731
- package/tools/multiplayer-server.d.mts +1 -27
- package/tools/multiplayer-server.mjs +1 -199
- package/tools/play-uci.d.mts +1 -26
- package/tools/play-uci.mjs +1 -205
- package/tools/sbom.d.mts +1 -83
- package/tools/sbom.mjs +1 -340
- package/tools/single-file.d.mts +1 -33
- package/tools/single-file.mjs +1 -239
- package/tools/soundfonts.d.mts +1 -79
- package/tools/soundfonts.mjs +1 -301
- package/tools/svg-optimise.d.mts +1 -8
- package/tools/svg-optimise.mjs +1 -45
- package/tools/verify-scenarios.d.mts +1 -15
- package/tools/verify-scenarios.mjs +1 -133
- package/tools/vite.d.mts +1 -17
- package/tools/vite.mjs +1 -102
- package/tools/webp-convert.d.mts +1 -8
- package/tools/webp-convert.mjs +1 -98
- package/two-d/pixi-interop.d.ts +1 -0
- package/two-d/pixi-interop.js +1 -0
- package/two-d/presentation.d.ts +1 -0
- package/two-d/presentation.js +1 -0
- package/two-d/render.d.ts +1 -0
- package/two-d/render.js +1 -0
- package/two-d/stage.d.ts +1 -0
- package/two-d/stage.js +1 -0
- package/two-d/ui.d.ts +1 -0
- package/two-d/ui.js +1 -0
- package/two-d.d.ts +1 -0
- package/two-d.js +1 -0
- package/world.d.ts +1 -0
- package/world.js +1 -0
- package/CHANGELOG.md +0 -3129
- package/LICENSE +0 -373
- package/MWG - Best Practices.md +0 -97
- package/MWG - Deep Code and Architecture Review.md +0 -238
- package/REFERENCE.md +0 -2180
- package/api-surface.json +0 -17102
- package/data/microgm-essential.PROVENANCE.md +0 -13
- package/data/microgm-essential.sf2 +0 -0
- package/data/microgm-opt.PROVENANCE.md +0 -23
- package/data/microgm-opt.sf2 +0 -0
- package/data/soundfont-catalog.json +0 -191
- package/dist/actors/Advancement.d.ts +0 -90
- package/dist/actors/Advancement.d.ts.map +0 -1
- package/dist/actors/Advancement.js +0 -115
- package/dist/actors/Advancement.js.map +0 -1
- package/dist/actors/Affix.d.ts +0 -96
- package/dist/actors/Affix.d.ts.map +0 -1
- package/dist/actors/Affix.js +0 -68
- package/dist/actors/Affix.js.map +0 -1
- package/dist/actors/Appearances.d.ts +0 -48
- package/dist/actors/Appearances.d.ts.map +0 -1
- package/dist/actors/Appearances.js +0 -62
- package/dist/actors/Appearances.js.map +0 -1
- package/dist/actors/Aura.d.ts +0 -45
- package/dist/actors/Aura.d.ts.map +0 -1
- package/dist/actors/Aura.js +0 -85
- package/dist/actors/Aura.js.map +0 -1
- package/dist/actors/Barrier.d.ts +0 -60
- package/dist/actors/Barrier.d.ts.map +0 -1
- package/dist/actors/Barrier.js +0 -70
- package/dist/actors/Barrier.js.map +0 -1
- package/dist/actors/Charges.d.ts +0 -66
- package/dist/actors/Charges.d.ts.map +0 -1
- package/dist/actors/Charges.js +0 -61
- package/dist/actors/Charges.js.map +0 -1
- package/dist/actors/EntityTemplate.d.ts +0 -127
- package/dist/actors/EntityTemplate.d.ts.map +0 -1
- package/dist/actors/EntityTemplate.js +0 -117
- package/dist/actors/EntityTemplate.js.map +0 -1
- package/dist/actors/Equipment.d.ts +0 -88
- package/dist/actors/Equipment.d.ts.map +0 -1
- package/dist/actors/Equipment.js +0 -107
- package/dist/actors/Equipment.js.map +0 -1
- package/dist/actors/Inventory.d.ts +0 -123
- package/dist/actors/Inventory.d.ts.map +0 -1
- package/dist/actors/Inventory.js +0 -165
- package/dist/actors/Inventory.js.map +0 -1
- package/dist/actors/ItemState.d.ts +0 -43
- package/dist/actors/ItemState.d.ts.map +0 -1
- package/dist/actors/ItemState.js +0 -63
- package/dist/actors/ItemState.js.map +0 -1
- package/dist/actors/ItemStatusEffect.d.ts +0 -40
- package/dist/actors/ItemStatusEffect.d.ts.map +0 -1
- package/dist/actors/ItemStatusEffect.js +0 -39
- package/dist/actors/ItemStatusEffect.js.map +0 -1
- package/dist/actors/Loot.d.ts +0 -38
- package/dist/actors/Loot.d.ts.map +0 -1
- package/dist/actors/Loot.js +0 -28
- package/dist/actors/Loot.js.map +0 -1
- package/dist/actors/Progression.d.ts +0 -52
- package/dist/actors/Progression.d.ts.map +0 -1
- package/dist/actors/Progression.js +0 -59
- package/dist/actors/Progression.js.map +0 -1
- package/dist/actors/Resource.d.ts +0 -53
- package/dist/actors/Resource.d.ts.map +0 -1
- package/dist/actors/Resource.js +0 -58
- package/dist/actors/Resource.js.map +0 -1
- package/dist/actors/Scaling.d.ts +0 -30
- package/dist/actors/Scaling.d.ts.map +0 -1
- package/dist/actors/Scaling.js +0 -9
- package/dist/actors/Scaling.js.map +0 -1
- package/dist/actors/Shop.d.ts +0 -40
- package/dist/actors/Shop.d.ts.map +0 -1
- package/dist/actors/Shop.js +0 -36
- package/dist/actors/Shop.js.map +0 -1
- package/dist/actors/SkillPoints.d.ts +0 -72
- package/dist/actors/SkillPoints.d.ts.map +0 -1
- package/dist/actors/SkillPoints.js +0 -87
- package/dist/actors/SkillPoints.js.map +0 -1
- package/dist/actors/StatBlock.d.ts +0 -86
- package/dist/actors/StatBlock.d.ts.map +0 -1
- package/dist/actors/StatBlock.js +0 -110
- package/dist/actors/StatBlock.js.map +0 -1
- package/dist/actors/StatusEffect.d.ts +0 -67
- package/dist/actors/StatusEffect.d.ts.map +0 -1
- package/dist/actors/StatusEffect.js +0 -59
- package/dist/actors/StatusEffect.js.map +0 -1
- package/dist/actors/Support.d.ts +0 -43
- package/dist/actors/Support.d.ts.map +0 -1
- package/dist/actors/Support.js +0 -71
- package/dist/actors/Support.js.map +0 -1
- package/dist/actors/Traits.d.ts +0 -43
- package/dist/actors/Traits.d.ts.map +0 -1
- package/dist/actors/Traits.js +0 -35
- package/dist/actors/Traits.js.map +0 -1
- package/dist/actors/craft.d.ts +0 -63
- package/dist/actors/craft.d.ts.map +0 -1
- package/dist/actors/craft.js +0 -86
- package/dist/actors/craft.js.map +0 -1
- package/dist/actors/index.d.ts +0 -46
- package/dist/actors/index.d.ts.map +0 -1
- package/dist/actors/index.js +0 -24
- package/dist/actors/index.js.map +0 -1
- package/dist/actors/skillCheck.d.ts +0 -21
- package/dist/actors/skillCheck.d.ts.map +0 -1
- package/dist/actors/skillCheck.js +0 -24
- package/dist/actors/skillCheck.js.map +0 -1
- package/dist/ai/Heuristics.d.ts +0 -240
- package/dist/ai/Heuristics.d.ts.map +0 -1
- package/dist/ai/Heuristics.js +0 -298
- package/dist/ai/Heuristics.js.map +0 -1
- package/dist/ai/Neural.d.ts +0 -65
- package/dist/ai/Neural.d.ts.map +0 -1
- package/dist/ai/Neural.js +0 -169
- package/dist/ai/Neural.js.map +0 -1
- package/dist/ai/Suggest.d.ts +0 -54
- package/dist/ai/Suggest.d.ts.map +0 -1
- package/dist/ai/Suggest.js +0 -48
- package/dist/ai/Suggest.js.map +0 -1
- package/dist/ai/index.d.ts +0 -136
- package/dist/ai/index.d.ts.map +0 -1
- package/dist/ai/index.js +0 -207
- package/dist/ai/index.js.map +0 -1
- package/dist/ai/lua.d.ts +0 -74
- package/dist/ai/lua.d.ts.map +0 -1
- package/dist/ai/lua.js +0 -217
- package/dist/ai/lua.js.map +0 -1
- package/dist/ai/score.d.ts +0 -162
- package/dist/ai/score.d.ts.map +0 -1
- package/dist/ai/score.js +0 -147
- package/dist/ai/score.js.map +0 -1
- package/dist/ai/search.d.ts +0 -108
- package/dist/ai/search.d.ts.map +0 -1
- package/dist/ai/search.js +0 -148
- package/dist/ai/search.js.map +0 -1
- package/dist/assets/ByteProgress.d.ts +0 -37
- package/dist/assets/ByteProgress.d.ts.map +0 -1
- package/dist/assets/ByteProgress.js +0 -54
- package/dist/assets/ByteProgress.js.map +0 -1
- package/dist/assets/Streaming.d.ts +0 -56
- package/dist/assets/Streaming.d.ts.map +0 -1
- package/dist/assets/Streaming.js +0 -100
- package/dist/assets/Streaming.js.map +0 -1
- package/dist/assets/SvgParts.d.ts +0 -31
- package/dist/assets/SvgParts.d.ts.map +0 -1
- package/dist/assets/SvgParts.js +0 -54
- package/dist/assets/SvgParts.js.map +0 -1
- package/dist/assets/SvgSource.d.ts +0 -3
- package/dist/assets/SvgSource.d.ts.map +0 -1
- package/dist/assets/SvgSource.js +0 -22
- package/dist/assets/SvgSource.js.map +0 -1
- package/dist/assets/binary.d.ts +0 -52
- package/dist/assets/binary.d.ts.map +0 -1
- package/dist/assets/binary.js +0 -57
- package/dist/assets/binary.js.map +0 -1
- package/dist/assets/index.d.ts +0 -27
- package/dist/assets/index.d.ts.map +0 -1
- package/dist/assets/index.js +0 -20
- package/dist/assets/index.js.map +0 -1
- package/dist/assets/loader.d.ts +0 -70
- package/dist/assets/loader.d.ts.map +0 -1
- package/dist/assets/loader.js +0 -115
- package/dist/assets/loader.js.map +0 -1
- package/dist/assets/paths.d.ts +0 -73
- package/dist/assets/paths.d.ts.map +0 -1
- package/dist/assets/paths.js +0 -91
- package/dist/assets/paths.js.map +0 -1
- package/dist/assets/svg.d.ts +0 -87
- package/dist/assets/svg.d.ts.map +0 -1
- package/dist/assets/svg.js +0 -166
- package/dist/assets/svg.js.map +0 -1
- package/dist/audio/AudioLoader.d.ts +0 -28
- package/dist/audio/AudioLoader.d.ts.map +0 -1
- package/dist/audio/AudioLoader.js +0 -53
- package/dist/audio/AudioLoader.js.map +0 -1
- package/dist/audio/Captions.d.ts +0 -27
- package/dist/audio/Captions.d.ts.map +0 -1
- package/dist/audio/Captions.js +0 -16
- package/dist/audio/Captions.js.map +0 -1
- package/dist/audio/Channels.d.ts +0 -218
- package/dist/audio/Channels.d.ts.map +0 -1
- package/dist/audio/Channels.js +0 -486
- package/dist/audio/Channels.js.map +0 -1
- package/dist/audio/LoopTags.d.ts +0 -37
- package/dist/audio/LoopTags.d.ts.map +0 -1
- package/dist/audio/LoopTags.js +0 -116
- package/dist/audio/LoopTags.js.map +0 -1
- package/dist/audio/Midi.d.ts +0 -184
- package/dist/audio/Midi.d.ts.map +0 -1
- package/dist/audio/Midi.js +0 -339
- package/dist/audio/Midi.js.map +0 -1
- package/dist/audio/MidiRender.d.ts +0 -113
- package/dist/audio/MidiRender.d.ts.map +0 -1
- package/dist/audio/MidiRender.js +0 -371
- package/dist/audio/MidiRender.js.map +0 -1
- package/dist/audio/Music.d.ts +0 -70
- package/dist/audio/Music.d.ts.map +0 -1
- package/dist/audio/Music.js +0 -191
- package/dist/audio/Music.js.map +0 -1
- package/dist/audio/MusicPlayer.d.ts +0 -80
- package/dist/audio/MusicPlayer.d.ts.map +0 -1
- package/dist/audio/MusicPlayer.js +0 -147
- package/dist/audio/MusicPlayer.js.map +0 -1
- package/dist/audio/Orchestrator.d.ts +0 -58
- package/dist/audio/Orchestrator.d.ts.map +0 -1
- package/dist/audio/Orchestrator.js +0 -74
- package/dist/audio/Orchestrator.js.map +0 -1
- package/dist/audio/Playable.d.ts +0 -31
- package/dist/audio/Playable.d.ts.map +0 -1
- package/dist/audio/Playable.js +0 -29
- package/dist/audio/Playable.js.map +0 -1
- package/dist/audio/Positional.d.ts +0 -125
- package/dist/audio/Positional.d.ts.map +0 -1
- package/dist/audio/Positional.js +0 -135
- package/dist/audio/Positional.js.map +0 -1
- package/dist/audio/SampleDecoder.d.ts +0 -55
- package/dist/audio/SampleDecoder.d.ts.map +0 -1
- package/dist/audio/SampleDecoder.js +0 -74
- package/dist/audio/SampleDecoder.js.map +0 -1
- package/dist/audio/Sound.d.ts +0 -57
- package/dist/audio/Sound.d.ts.map +0 -1
- package/dist/audio/Sound.js +0 -79
- package/dist/audio/Sound.js.map +0 -1
- package/dist/audio/SoundFont.d.ts +0 -192
- package/dist/audio/SoundFont.d.ts.map +0 -1
- package/dist/audio/SoundFont.js +0 -862
- package/dist/audio/SoundFont.js.map +0 -1
- package/dist/audio/Synth.d.ts +0 -64
- package/dist/audio/Synth.d.ts.map +0 -1
- package/dist/audio/Synth.js +0 -133
- package/dist/audio/Synth.js.map +0 -1
- package/dist/audio/humanize/Groove.d.ts +0 -80
- package/dist/audio/humanize/Groove.d.ts.map +0 -1
- package/dist/audio/humanize/Groove.js +0 -102
- package/dist/audio/humanize/Groove.js.map +0 -1
- package/dist/audio/humanize/GrooveConverter.d.ts +0 -49
- package/dist/audio/humanize/GrooveConverter.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveConverter.js +0 -344
- package/dist/audio/humanize/GrooveConverter.js.map +0 -1
- package/dist/audio/humanize/GrooveExtractor.d.ts +0 -49
- package/dist/audio/humanize/GrooveExtractor.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveExtractor.js +0 -179
- package/dist/audio/humanize/GrooveExtractor.js.map +0 -1
- package/dist/audio/humanize/GrooveHumanizer.d.ts +0 -34
- package/dist/audio/humanize/GrooveHumanizer.d.ts.map +0 -1
- package/dist/audio/humanize/GrooveHumanizer.js +0 -37
- package/dist/audio/humanize/GrooveHumanizer.js.map +0 -1
- package/dist/audio/humanize/Humanize.d.ts +0 -54
- package/dist/audio/humanize/Humanize.d.ts.map +0 -1
- package/dist/audio/humanize/Humanize.js +0 -239
- package/dist/audio/humanize/Humanize.js.map +0 -1
- package/dist/audio/humanize/HumanizerFactory.d.ts +0 -68
- package/dist/audio/humanize/HumanizerFactory.d.ts.map +0 -1
- package/dist/audio/humanize/HumanizerFactory.js +0 -84
- package/dist/audio/humanize/HumanizerFactory.js.map +0 -1
- package/dist/audio/humanize/LiteHumanizer.d.ts +0 -30
- package/dist/audio/humanize/LiteHumanizer.d.ts.map +0 -1
- package/dist/audio/humanize/LiteHumanizer.js +0 -35
- package/dist/audio/humanize/LiteHumanizer.js.map +0 -1
- package/dist/audio/humanize/Onsets.d.ts +0 -26
- package/dist/audio/humanize/Onsets.d.ts.map +0 -1
- package/dist/audio/humanize/Onsets.js +0 -164
- package/dist/audio/humanize/Onsets.js.map +0 -1
- package/dist/audio/index.d.ts +0 -43
- package/dist/audio/index.d.ts.map +0 -1
- package/dist/audio/index.js +0 -22
- package/dist/audio/index.js.map +0 -1
- package/dist/battle/AttackDialog.d.ts +0 -75
- package/dist/battle/AttackDialog.d.ts.map +0 -1
- package/dist/battle/AttackDialog.js +0 -115
- package/dist/battle/AttackDialog.js.map +0 -1
- package/dist/battle/AttackPreview.d.ts +0 -70
- package/dist/battle/AttackPreview.d.ts.map +0 -1
- package/dist/battle/AttackPreview.js +0 -78
- package/dist/battle/AttackPreview.js.map +0 -1
- package/dist/battle/BattleAI.d.ts +0 -40
- package/dist/battle/BattleAI.d.ts.map +0 -1
- package/dist/battle/BattleAI.js +0 -63
- package/dist/battle/BattleAI.js.map +0 -1
- package/dist/battle/BattleStats.d.ts +0 -45
- package/dist/battle/BattleStats.d.ts.map +0 -1
- package/dist/battle/BattleStats.js +0 -63
- package/dist/battle/BattleStats.js.map +0 -1
- package/dist/battle/Evolution.d.ts +0 -34
- package/dist/battle/Evolution.d.ts.map +0 -1
- package/dist/battle/Evolution.js +0 -37
- package/dist/battle/Evolution.js.map +0 -1
- package/dist/battle/Field.d.ts +0 -36
- package/dist/battle/Field.d.ts.map +0 -1
- package/dist/battle/Field.js +0 -31
- package/dist/battle/Field.js.map +0 -1
- package/dist/battle/Hooks.d.ts +0 -39
- package/dist/battle/Hooks.d.ts.map +0 -1
- package/dist/battle/Hooks.js +0 -38
- package/dist/battle/Hooks.js.map +0 -1
- package/dist/battle/Move.d.ts +0 -45
- package/dist/battle/Move.d.ts.map +0 -1
- package/dist/battle/Move.js +0 -23
- package/dist/battle/Move.js.map +0 -1
- package/dist/battle/Party.d.ts +0 -32
- package/dist/battle/Party.d.ts.map +0 -1
- package/dist/battle/Party.js +0 -62
- package/dist/battle/Party.js.map +0 -1
- package/dist/battle/Species.d.ts +0 -50
- package/dist/battle/Species.d.ts.map +0 -1
- package/dist/battle/Species.js +0 -41
- package/dist/battle/Species.js.map +0 -1
- package/dist/battle/StatStages.d.ts +0 -52
- package/dist/battle/StatStages.d.ts.map +0 -1
- package/dist/battle/StatStages.js +0 -50
- package/dist/battle/StatStages.js.map +0 -1
- package/dist/battle/TypeMatrix.d.ts +0 -25
- package/dist/battle/TypeMatrix.d.ts.map +0 -1
- package/dist/battle/TypeMatrix.js +0 -35
- package/dist/battle/TypeMatrix.js.map +0 -1
- package/dist/battle/UnitSelector.d.ts +0 -72
- package/dist/battle/UnitSelector.d.ts.map +0 -1
- package/dist/battle/UnitSelector.js +0 -117
- package/dist/battle/UnitSelector.js.map +0 -1
- package/dist/battle/Whiteboard.d.ts +0 -50
- package/dist/battle/Whiteboard.d.ts.map +0 -1
- package/dist/battle/Whiteboard.js +0 -94
- package/dist/battle/Whiteboard.js.map +0 -1
- package/dist/battle/index.d.ts +0 -26
- package/dist/battle/index.d.ts.map +0 -1
- package/dist/battle/index.js +0 -15
- package/dist/battle/index.js.map +0 -1
- package/dist/board/Army.d.ts +0 -92
- package/dist/board/Army.d.ts.map +0 -1
- package/dist/board/Army.js +0 -123
- package/dist/board/Army.js.map +0 -1
- package/dist/board/Classics.d.ts +0 -419
- package/dist/board/Classics.d.ts.map +0 -1
- package/dist/board/Classics.js +0 -754
- package/dist/board/Classics.js.map +0 -1
- package/dist/board/Engine.d.ts +0 -93
- package/dist/board/Engine.d.ts.map +0 -1
- package/dist/board/Engine.js +0 -545
- package/dist/board/Engine.js.map +0 -1
- package/dist/board/FogOfWar.d.ts +0 -79
- package/dist/board/FogOfWar.d.ts.map +0 -1
- package/dist/board/FogOfWar.js +0 -150
- package/dist/board/FogOfWar.js.map +0 -1
- package/dist/board/HexSkirmish.d.ts +0 -213
- package/dist/board/HexSkirmish.d.ts.map +0 -1
- package/dist/board/HexSkirmish.js +0 -329
- package/dist/board/HexSkirmish.js.map +0 -1
- package/dist/board/Tactics.d.ts +0 -212
- package/dist/board/Tactics.d.ts.map +0 -1
- package/dist/board/Tactics.js +0 -305
- package/dist/board/Tactics.js.map +0 -1
- package/dist/board/bitboard.d.ts +0 -132
- package/dist/board/bitboard.d.ts.map +0 -1
- package/dist/board/bitboard.js +0 -495
- package/dist/board/bitboard.js.map +0 -1
- package/dist/board/chess.d.ts +0 -167
- package/dist/board/chess.d.ts.map +0 -1
- package/dist/board/chess.js +0 -578
- package/dist/board/chess.js.map +0 -1
- package/dist/board/index.d.ts +0 -23
- package/dist/board/index.d.ts.map +0 -1
- package/dist/board/index.js +0 -12
- package/dist/board/index.js.map +0 -1
- package/dist/board/openings.d.ts +0 -58
- package/dist/board/openings.d.ts.map +0 -1
- package/dist/board/openings.js +0 -45
- package/dist/board/openings.js.map +0 -1
- package/dist/board/tablebase.d.ts +0 -118
- package/dist/board/tablebase.d.ts.map +0 -1
- package/dist/board/tablebase.js +0 -414
- package/dist/board/tablebase.js.map +0 -1
- package/dist/board/tourney.d.ts +0 -97
- package/dist/board/tourney.d.ts.map +0 -1
- package/dist/board/tourney.js +0 -1019
- package/dist/board/tourney.js.map +0 -1
- package/dist/core/Achievements.d.ts +0 -101
- package/dist/core/Achievements.d.ts.map +0 -1
- package/dist/core/Achievements.js +0 -141
- package/dist/core/Achievements.js.map +0 -1
- package/dist/core/ActionJournal.d.ts +0 -43
- package/dist/core/ActionJournal.d.ts.map +0 -1
- package/dist/core/ActionJournal.js +0 -77
- package/dist/core/ActionJournal.js.map +0 -1
- package/dist/core/Blob.d.ts +0 -79
- package/dist/core/Blob.d.ts.map +0 -1
- package/dist/core/Blob.js +0 -140
- package/dist/core/Blob.js.map +0 -1
- package/dist/core/Clone.d.ts +0 -31
- package/dist/core/Clone.d.ts.map +0 -1
- package/dist/core/Clone.js +0 -84
- package/dist/core/Clone.js.map +0 -1
- package/dist/core/Collection.d.ts +0 -59
- package/dist/core/Collection.d.ts.map +0 -1
- package/dist/core/Collection.js +0 -77
- package/dist/core/Collection.js.map +0 -1
- package/dist/core/Csv.d.ts +0 -74
- package/dist/core/Csv.d.ts.map +0 -1
- package/dist/core/Csv.js +0 -201
- package/dist/core/Csv.js.map +0 -1
- package/dist/core/DialogueText.d.ts +0 -72
- package/dist/core/DialogueText.d.ts.map +0 -1
- package/dist/core/DialogueText.js +0 -68
- package/dist/core/DialogueText.js.map +0 -1
- package/dist/core/Entity.d.ts +0 -42
- package/dist/core/Entity.d.ts.map +0 -1
- package/dist/core/Entity.js +0 -61
- package/dist/core/Entity.js.map +0 -1
- package/dist/core/Feedback.d.ts +0 -27
- package/dist/core/Feedback.d.ts.map +0 -1
- package/dist/core/Feedback.js +0 -33
- package/dist/core/Feedback.js.map +0 -1
- package/dist/core/FixedStepper.d.ts +0 -38
- package/dist/core/FixedStepper.d.ts.map +0 -1
- package/dist/core/FixedStepper.js +0 -56
- package/dist/core/FixedStepper.js.map +0 -1
- package/dist/core/Grid.d.ts +0 -179
- package/dist/core/Grid.d.ts.map +0 -1
- package/dist/core/Grid.js +0 -201
- package/dist/core/Grid.js.map +0 -1
- package/dist/core/Handles.d.ts +0 -42
- package/dist/core/Handles.d.ts.map +0 -1
- package/dist/core/Handles.js +0 -38
- package/dist/core/Handles.js.map +0 -1
- package/dist/core/Hex.d.ts +0 -79
- package/dist/core/Hex.d.ts.map +0 -1
- package/dist/core/Hex.js +0 -161
- package/dist/core/Hex.js.map +0 -1
- package/dist/core/Hooks.d.ts +0 -48
- package/dist/core/Hooks.d.ts.map +0 -1
- package/dist/core/Hooks.js +0 -33
- package/dist/core/Hooks.js.map +0 -1
- package/dist/core/HttpTransport.d.ts +0 -53
- package/dist/core/HttpTransport.d.ts.map +0 -1
- package/dist/core/HttpTransport.js +0 -108
- package/dist/core/HttpTransport.js.map +0 -1
- package/dist/core/Input.d.ts +0 -256
- package/dist/core/Input.d.ts.map +0 -1
- package/dist/core/Input.js +0 -557
- package/dist/core/Input.js.map +0 -1
- package/dist/core/JavaRandom.d.ts +0 -55
- package/dist/core/JavaRandom.d.ts.map +0 -1
- package/dist/core/JavaRandom.js +0 -81
- package/dist/core/JavaRandom.js.map +0 -1
- package/dist/core/Loading.d.ts +0 -65
- package/dist/core/Loading.d.ts.map +0 -1
- package/dist/core/Loading.js +0 -119
- package/dist/core/Loading.js.map +0 -1
- package/dist/core/Log.d.ts +0 -48
- package/dist/core/Log.d.ts.map +0 -1
- package/dist/core/Log.js +0 -59
- package/dist/core/Log.js.map +0 -1
- package/dist/core/Math.d.ts +0 -14
- package/dist/core/Math.d.ts.map +0 -1
- package/dist/core/Math.js +0 -16
- package/dist/core/Math.js.map +0 -1
- package/dist/core/Motion.d.ts +0 -47
- package/dist/core/Motion.d.ts.map +0 -1
- package/dist/core/Motion.js +0 -122
- package/dist/core/Motion.js.map +0 -1
- package/dist/core/Multiplayer.d.ts +0 -101
- package/dist/core/Multiplayer.d.ts.map +0 -1
- package/dist/core/Multiplayer.js +0 -156
- package/dist/core/Multiplayer.js.map +0 -1
- package/dist/core/News.d.ts +0 -51
- package/dist/core/News.d.ts.map +0 -1
- package/dist/core/News.js +0 -65
- package/dist/core/News.js.map +0 -1
- package/dist/core/Pathfinding.d.ts +0 -41
- package/dist/core/Pathfinding.d.ts.map +0 -1
- package/dist/core/Pathfinding.js +0 -86
- package/dist/core/Pathfinding.js.map +0 -1
- package/dist/core/PlayerInput.d.ts +0 -57
- package/dist/core/PlayerInput.d.ts.map +0 -1
- package/dist/core/PlayerInput.js +0 -82
- package/dist/core/PlayerInput.js.map +0 -1
- package/dist/core/Presentation.d.ts +0 -56
- package/dist/core/Presentation.d.ts.map +0 -1
- package/dist/core/Presentation.js +0 -78
- package/dist/core/Presentation.js.map +0 -1
- package/dist/core/Random.d.ts +0 -259
- package/dist/core/Random.d.ts.map +0 -1
- package/dist/core/Random.js +0 -408
- package/dist/core/Random.js.map +0 -1
- package/dist/core/Reactions.d.ts +0 -67
- package/dist/core/Reactions.d.ts.map +0 -1
- package/dist/core/Reactions.js +0 -92
- package/dist/core/Reactions.js.map +0 -1
- package/dist/core/Registry.d.ts +0 -31
- package/dist/core/Registry.d.ts.map +0 -1
- package/dist/core/Registry.js +0 -46
- package/dist/core/Registry.js.map +0 -1
- package/dist/core/Replay.d.ts +0 -126
- package/dist/core/Replay.d.ts.map +0 -1
- package/dist/core/Replay.js +0 -162
- package/dist/core/Replay.js.map +0 -1
- package/dist/core/ReplayFile.d.ts +0 -197
- package/dist/core/ReplayFile.d.ts.map +0 -1
- package/dist/core/ReplayFile.js +0 -257
- package/dist/core/ReplayFile.js.map +0 -1
- package/dist/core/RunHistory.d.ts +0 -54
- package/dist/core/RunHistory.d.ts.map +0 -1
- package/dist/core/RunHistory.js +0 -40
- package/dist/core/RunHistory.js.map +0 -1
- package/dist/core/Sanitize.d.ts +0 -101
- package/dist/core/Sanitize.d.ts.map +0 -1
- package/dist/core/Sanitize.js +0 -162
- package/dist/core/Sanitize.js.map +0 -1
- package/dist/core/Save.d.ts +0 -123
- package/dist/core/Save.d.ts.map +0 -1
- package/dist/core/Save.js +0 -216
- package/dist/core/Save.js.map +0 -1
- package/dist/core/SaveSync.d.ts +0 -43
- package/dist/core/SaveSync.d.ts.map +0 -1
- package/dist/core/SaveSync.js +0 -56
- package/dist/core/SaveSync.js.map +0 -1
- package/dist/core/Scene.d.ts +0 -63
- package/dist/core/Scene.d.ts.map +0 -1
- package/dist/core/Scene.js +0 -81
- package/dist/core/Scene.js.map +0 -1
- package/dist/core/SceneComponents.d.ts +0 -67
- package/dist/core/SceneComponents.d.ts.map +0 -1
- package/dist/core/SceneComponents.js +0 -76
- package/dist/core/SceneComponents.js.map +0 -1
- package/dist/core/SceneStack.d.ts +0 -61
- package/dist/core/SceneStack.d.ts.map +0 -1
- package/dist/core/SceneStack.js +0 -91
- package/dist/core/SceneStack.js.map +0 -1
- package/dist/core/Scramble.d.ts +0 -21
- package/dist/core/Scramble.d.ts.map +0 -1
- package/dist/core/Scramble.js +0 -52
- package/dist/core/Scramble.js.map +0 -1
- package/dist/core/Session.d.ts +0 -31
- package/dist/core/Session.d.ts.map +0 -1
- package/dist/core/Session.js +0 -11
- package/dist/core/Session.js.map +0 -1
- package/dist/core/Settings.d.ts +0 -96
- package/dist/core/Settings.d.ts.map +0 -1
- package/dist/core/Settings.js +0 -190
- package/dist/core/Settings.js.map +0 -1
- package/dist/core/Signal.d.ts +0 -35
- package/dist/core/Signal.d.ts.map +0 -1
- package/dist/core/Signal.js +0 -41
- package/dist/core/Signal.js.map +0 -1
- package/dist/core/Spawner.d.ts +0 -65
- package/dist/core/Spawner.d.ts.map +0 -1
- package/dist/core/Spawner.js +0 -82
- package/dist/core/Spawner.js.map +0 -1
- package/dist/core/State.d.ts +0 -97
- package/dist/core/State.d.ts.map +0 -1
- package/dist/core/State.js +0 -177
- package/dist/core/State.js.map +0 -1
- package/dist/core/Stats.d.ts +0 -46
- package/dist/core/Stats.d.ts.map +0 -1
- package/dist/core/Stats.js +0 -47
- package/dist/core/Stats.js.map +0 -1
- package/dist/core/StoredValue.d.ts +0 -30
- package/dist/core/StoredValue.d.ts.map +0 -1
- package/dist/core/StoredValue.js +0 -38
- package/dist/core/StoredValue.js.map +0 -1
- package/dist/core/SyncGuard.d.ts +0 -57
- package/dist/core/SyncGuard.d.ts.map +0 -1
- package/dist/core/SyncGuard.js +0 -116
- package/dist/core/SyncGuard.js.map +0 -1
- package/dist/core/Telemetry.d.ts +0 -63
- package/dist/core/Telemetry.d.ts.map +0 -1
- package/dist/core/Telemetry.js +0 -83
- package/dist/core/Telemetry.js.map +0 -1
- package/dist/core/Twee.d.ts +0 -101
- package/dist/core/Twee.d.ts.map +0 -1
- package/dist/core/Twee.js +0 -174
- package/dist/core/Twee.js.map +0 -1
- package/dist/core/Tween.d.ts +0 -60
- package/dist/core/Tween.d.ts.map +0 -1
- package/dist/core/Tween.js +0 -98
- package/dist/core/Tween.js.map +0 -1
- package/dist/core/UndoHistory.d.ts +0 -52
- package/dist/core/UndoHistory.d.ts.map +0 -1
- package/dist/core/UndoHistory.js +0 -49
- package/dist/core/UndoHistory.js.map +0 -1
- package/dist/core/index.d.ts +0 -94
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -53
- package/dist/core/index.js.map +0 -1
- package/dist/headless/index.d.ts +0 -87
- package/dist/headless/index.d.ts.map +0 -1
- package/dist/headless/index.js +0 -87
- package/dist/headless/index.js.map +0 -1
- package/dist/i18n/Content.d.ts +0 -151
- package/dist/i18n/Content.d.ts.map +0 -1
- package/dist/i18n/Content.js +0 -218
- package/dist/i18n/Content.js.map +0 -1
- package/dist/i18n/EditSession.d.ts +0 -101
- package/dist/i18n/EditSession.d.ts.map +0 -1
- package/dist/i18n/EditSession.js +0 -150
- package/dist/i18n/EditSession.js.map +0 -1
- package/dist/i18n/Fluent.d.ts +0 -7
- package/dist/i18n/Fluent.d.ts.map +0 -1
- package/dist/i18n/Fluent.js +0 -98
- package/dist/i18n/Fluent.js.map +0 -1
- package/dist/i18n/Format.d.ts +0 -25
- package/dist/i18n/Format.d.ts.map +0 -1
- package/dist/i18n/Format.js +0 -32
- package/dist/i18n/Format.js.map +0 -1
- package/dist/i18n/FormatSpec.d.ts +0 -76
- package/dist/i18n/FormatSpec.d.ts.map +0 -1
- package/dist/i18n/FormatSpec.js +0 -306
- package/dist/i18n/FormatSpec.js.map +0 -1
- package/dist/i18n/Po.d.ts +0 -54
- package/dist/i18n/Po.d.ts.map +0 -1
- package/dist/i18n/Po.js +0 -192
- package/dist/i18n/Po.js.map +0 -1
- package/dist/i18n/SemanticMessage.d.ts +0 -84
- package/dist/i18n/SemanticMessage.d.ts.map +0 -1
- package/dist/i18n/SemanticMessage.js +0 -54
- package/dist/i18n/SemanticMessage.js.map +0 -1
- package/dist/i18n/SoundMarkers.d.ts +0 -38
- package/dist/i18n/SoundMarkers.d.ts.map +0 -1
- package/dist/i18n/SoundMarkers.js +0 -48
- package/dist/i18n/SoundMarkers.js.map +0 -1
- package/dist/i18n/Validate.d.ts +0 -82
- package/dist/i18n/Validate.d.ts.map +0 -1
- package/dist/i18n/Validate.js +0 -106
- package/dist/i18n/Validate.js.map +0 -1
- package/dist/i18n/index.d.ts +0 -177
- package/dist/i18n/index.d.ts.map +0 -1
- package/dist/i18n/index.js +0 -331
- package/dist/i18n/index.js.map +0 -1
- package/dist/index.d.ts +0 -26
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -26
- package/dist/index.js.map +0 -1
- package/dist/mw_games.global.js +0 -1407
- package/dist/mwl/MapFile.d.ts +0 -41
- package/dist/mwl/MapFile.d.ts.map +0 -1
- package/dist/mwl/MapFile.js +0 -53
- package/dist/mwl/MapFile.js.map +0 -1
- package/dist/mwl/actors.d.ts +0 -62
- package/dist/mwl/actors.d.ts.map +0 -1
- package/dist/mwl/actors.js +0 -82
- package/dist/mwl/actors.js.map +0 -1
- package/dist/mwl/campaign.d.ts +0 -51
- package/dist/mwl/campaign.d.ts.map +0 -1
- package/dist/mwl/campaign.js +0 -58
- package/dist/mwl/campaign.js.map +0 -1
- package/dist/mwl/carryover.d.ts +0 -86
- package/dist/mwl/carryover.d.ts.map +0 -1
- package/dist/mwl/carryover.js +0 -70
- package/dist/mwl/carryover.js.map +0 -1
- package/dist/mwl/catalog.d.ts +0 -98
- package/dist/mwl/catalog.d.ts.map +0 -1
- package/dist/mwl/catalog.js +0 -259
- package/dist/mwl/catalog.js.map +0 -1
- package/dist/mwl/compiler.d.ts +0 -135
- package/dist/mwl/compiler.d.ts.map +0 -1
- package/dist/mwl/compiler.js +0 -216
- package/dist/mwl/compiler.js.map +0 -1
- package/dist/mwl/conditions.d.ts +0 -18
- package/dist/mwl/conditions.d.ts.map +0 -1
- package/dist/mwl/conditions.js +0 -171
- package/dist/mwl/conditions.js.map +0 -1
- package/dist/mwl/content.d.ts +0 -140
- package/dist/mwl/content.d.ts.map +0 -1
- package/dist/mwl/content.js +0 -179
- package/dist/mwl/content.js.map +0 -1
- package/dist/mwl/expression.d.ts +0 -42
- package/dist/mwl/expression.d.ts.map +0 -1
- package/dist/mwl/expression.js +0 -164
- package/dist/mwl/expression.js.map +0 -1
- package/dist/mwl/grammar.d.ts +0 -100
- package/dist/mwl/grammar.d.ts.map +0 -1
- package/dist/mwl/grammar.js +0 -588
- package/dist/mwl/grammar.js.map +0 -1
- package/dist/mwl/hooks.d.ts +0 -201
- package/dist/mwl/hooks.d.ts.map +0 -1
- package/dist/mwl/hooks.js +0 -165
- package/dist/mwl/hooks.js.map +0 -1
- package/dist/mwl/index.d.ts +0 -40
- package/dist/mwl/index.d.ts.map +0 -1
- package/dist/mwl/index.js +0 -20
- package/dist/mwl/index.js.map +0 -1
- package/dist/mwl/objects.d.ts +0 -31
- package/dist/mwl/objects.d.ts.map +0 -1
- package/dist/mwl/objects.js +0 -83
- package/dist/mwl/objects.js.map +0 -1
- package/dist/mwl/persistence.d.ts +0 -67
- package/dist/mwl/persistence.d.ts.map +0 -1
- package/dist/mwl/persistence.js +0 -135
- package/dist/mwl/persistence.js.map +0 -1
- package/dist/mwl/presentation.d.ts +0 -86
- package/dist/mwl/presentation.d.ts.map +0 -1
- package/dist/mwl/presentation.js +0 -419
- package/dist/mwl/presentation.js.map +0 -1
- package/dist/mwl/pyroeis-runtime.d.ts +0 -82
- package/dist/mwl/pyroeis-runtime.d.ts.map +0 -1
- package/dist/mwl/pyroeis-runtime.js +0 -535
- package/dist/mwl/pyroeis-runtime.js.map +0 -1
- package/dist/mwl/pyroeis.d.ts +0 -54
- package/dist/mwl/pyroeis.d.ts.map +0 -1
- package/dist/mwl/pyroeis.js +0 -189
- package/dist/mwl/pyroeis.js.map +0 -1
- package/dist/mwl/readers.d.ts +0 -77
- package/dist/mwl/readers.d.ts.map +0 -1
- package/dist/mwl/readers.js +0 -150
- package/dist/mwl/readers.js.map +0 -1
- package/dist/mwl/report.d.ts +0 -44
- package/dist/mwl/report.d.ts.map +0 -1
- package/dist/mwl/report.js +0 -88
- package/dist/mwl/report.js.map +0 -1
- package/dist/mwl/runtime.d.ts +0 -577
- package/dist/mwl/runtime.d.ts.map +0 -1
- package/dist/mwl/runtime.js +0 -1741
- package/dist/mwl/runtime.js.map +0 -1
- package/dist/mwl/schema.d.ts +0 -151
- package/dist/mwl/schema.d.ts.map +0 -1
- package/dist/mwl/schema.js +0 -979
- package/dist/mwl/schema.js.map +0 -1
- package/dist/mwl/scripts.d.ts +0 -26
- package/dist/mwl/scripts.d.ts.map +0 -1
- package/dist/mwl/scripts.js +0 -34
- package/dist/mwl/scripts.js.map +0 -1
- package/dist/mwl/tables.d.ts +0 -95
- package/dist/mwl/tables.d.ts.map +0 -1
- package/dist/mwl/tables.js +0 -100
- package/dist/mwl/tables.js.map +0 -1
- package/dist/mwl/utils.d.ts +0 -10
- package/dist/mwl/utils.d.ts.map +0 -1
- package/dist/mwl/utils.js +0 -40
- package/dist/mwl/utils.js.map +0 -1
- package/dist/physics/PhysicsWorld.d.ts +0 -158
- package/dist/physics/PhysicsWorld.d.ts.map +0 -1
- package/dist/physics/PhysicsWorld.js +0 -375
- package/dist/physics/PhysicsWorld.js.map +0 -1
- package/dist/physics/XpbdWorld.d.ts +0 -213
- package/dist/physics/XpbdWorld.d.ts.map +0 -1
- package/dist/physics/XpbdWorld.js +0 -336
- package/dist/physics/XpbdWorld.js.map +0 -1
- package/dist/physics/cloth/index.d.ts +0 -99
- package/dist/physics/cloth/index.d.ts.map +0 -1
- package/dist/physics/cloth/index.js +0 -226
- package/dist/physics/cloth/index.js.map +0 -1
- package/dist/physics/index.d.ts +0 -7
- package/dist/physics/index.d.ts.map +0 -1
- package/dist/physics/index.js +0 -4
- package/dist/physics/index.js.map +0 -1
- package/dist/physics/spring/index.d.ts +0 -91
- package/dist/physics/spring/index.d.ts.map +0 -1
- package/dist/physics/spring/index.js +0 -120
- package/dist/physics/spring/index.js.map +0 -1
- package/dist/physics/xpbd.d.ts +0 -3
- package/dist/physics/xpbd.d.ts.map +0 -1
- package/dist/physics/xpbd.js +0 -2
- package/dist/physics/xpbd.js.map +0 -1
- package/dist/roguelike/Boss.d.ts +0 -79
- package/dist/roguelike/Boss.d.ts.map +0 -1
- package/dist/roguelike/Boss.js +0 -126
- package/dist/roguelike/Boss.js.map +0 -1
- package/dist/roguelike/Cave.d.ts +0 -124
- package/dist/roguelike/Cave.d.ts.map +0 -1
- package/dist/roguelike/Cave.js +0 -216
- package/dist/roguelike/Cave.js.map +0 -1
- package/dist/roguelike/Combat.d.ts +0 -35
- package/dist/roguelike/Combat.d.ts.map +0 -1
- package/dist/roguelike/Combat.js +0 -33
- package/dist/roguelike/Combat.js.map +0 -1
- package/dist/roguelike/ContentRoll.d.ts +0 -53
- package/dist/roguelike/ContentRoll.d.ts.map +0 -1
- package/dist/roguelike/ContentRoll.js +0 -48
- package/dist/roguelike/ContentRoll.js.map +0 -1
- package/dist/roguelike/Doors.d.ts +0 -73
- package/dist/roguelike/Doors.d.ts.map +0 -1
- package/dist/roguelike/Doors.js +0 -115
- package/dist/roguelike/Doors.js.map +0 -1
- package/dist/roguelike/DungeonParity.d.ts +0 -57
- package/dist/roguelike/DungeonParity.d.ts.map +0 -1
- package/dist/roguelike/DungeonParity.js +0 -87
- package/dist/roguelike/DungeonParity.js.map +0 -1
- package/dist/roguelike/Elevation.d.ts +0 -41
- package/dist/roguelike/Elevation.d.ts.map +0 -1
- package/dist/roguelike/Elevation.js +0 -52
- package/dist/roguelike/Elevation.js.map +0 -1
- package/dist/roguelike/Features.d.ts +0 -59
- package/dist/roguelike/Features.d.ts.map +0 -1
- package/dist/roguelike/Features.js +0 -76
- package/dist/roguelike/Features.js.map +0 -1
- package/dist/roguelike/FieldOfView.d.ts +0 -86
- package/dist/roguelike/FieldOfView.d.ts.map +0 -1
- package/dist/roguelike/FieldOfView.js +0 -148
- package/dist/roguelike/FieldOfView.js.map +0 -1
- package/dist/roguelike/Level.d.ts +0 -139
- package/dist/roguelike/Level.d.ts.map +0 -1
- package/dist/roguelike/Level.js +0 -189
- package/dist/roguelike/Level.js.map +0 -1
- package/dist/roguelike/MonsterAI.d.ts +0 -54
- package/dist/roguelike/MonsterAI.d.ts.map +0 -1
- package/dist/roguelike/MonsterAI.js +0 -83
- package/dist/roguelike/MonsterAI.js.map +0 -1
- package/dist/roguelike/MultiStageAbility.d.ts +0 -59
- package/dist/roguelike/MultiStageAbility.d.ts.map +0 -1
- package/dist/roguelike/MultiStageAbility.js +0 -76
- package/dist/roguelike/MultiStageAbility.js.map +0 -1
- package/dist/roguelike/MultiTurnBeam.d.ts +0 -108
- package/dist/roguelike/MultiTurnBeam.d.ts.map +0 -1
- package/dist/roguelike/MultiTurnBeam.js +0 -164
- package/dist/roguelike/MultiTurnBeam.js.map +0 -1
- package/dist/roguelike/Overworld.d.ts +0 -89
- package/dist/roguelike/Overworld.d.ts.map +0 -1
- package/dist/roguelike/Overworld.js +0 -325
- package/dist/roguelike/Overworld.js.map +0 -1
- package/dist/roguelike/Pathfinder.d.ts +0 -103
- package/dist/roguelike/Pathfinder.d.ts.map +0 -1
- package/dist/roguelike/Pathfinder.js +0 -213
- package/dist/roguelike/Pathfinder.js.map +0 -1
- package/dist/roguelike/Placement.d.ts +0 -62
- package/dist/roguelike/Placement.d.ts.map +0 -1
- package/dist/roguelike/Placement.js +0 -79
- package/dist/roguelike/Placement.js.map +0 -1
- package/dist/roguelike/RoomBuilders.d.ts +0 -60
- package/dist/roguelike/RoomBuilders.d.ts.map +0 -1
- package/dist/roguelike/RoomBuilders.js +0 -57
- package/dist/roguelike/RoomBuilders.js.map +0 -1
- package/dist/roguelike/Scheduler.d.ts +0 -96
- package/dist/roguelike/Scheduler.d.ts.map +0 -1
- package/dist/roguelike/Scheduler.js +0 -154
- package/dist/roguelike/Scheduler.js.map +0 -1
- package/dist/roguelike/Secrets.d.ts +0 -57
- package/dist/roguelike/Secrets.d.ts.map +0 -1
- package/dist/roguelike/Secrets.js +0 -77
- package/dist/roguelike/Secrets.js.map +0 -1
- package/dist/roguelike/Stealth.d.ts +0 -47
- package/dist/roguelike/Stealth.d.ts.map +0 -1
- package/dist/roguelike/Stealth.js +0 -48
- package/dist/roguelike/Stealth.js.map +0 -1
- package/dist/roguelike/Targeting.d.ts +0 -312
- package/dist/roguelike/Targeting.d.ts.map +0 -1
- package/dist/roguelike/Targeting.js +0 -483
- package/dist/roguelike/Targeting.js.map +0 -1
- package/dist/roguelike/TriggerTracker.d.ts +0 -46
- package/dist/roguelike/TriggerTracker.d.ts.map +0 -1
- package/dist/roguelike/TriggerTracker.js +0 -59
- package/dist/roguelike/TriggerTracker.js.map +0 -1
- package/dist/roguelike/generate.d.ts +0 -139
- package/dist/roguelike/generate.d.ts.map +0 -1
- package/dist/roguelike/generate.js +0 -166
- package/dist/roguelike/generate.js.map +0 -1
- package/dist/roguelike/index.d.ts +0 -48
- package/dist/roguelike/index.d.ts.map +0 -1
- package/dist/roguelike/index.js +0 -27
- package/dist/roguelike/index.js.map +0 -1
- package/dist/rpg/Collision.d.ts +0 -61
- package/dist/rpg/Collision.d.ts.map +0 -1
- package/dist/rpg/Collision.js +0 -94
- package/dist/rpg/Collision.js.map +0 -1
- package/dist/rpg/Event.d.ts +0 -50
- package/dist/rpg/Event.d.ts.map +0 -1
- package/dist/rpg/Event.js +0 -36
- package/dist/rpg/Event.js.map +0 -1
- package/dist/rpg/EventRunner.d.ts +0 -139
- package/dist/rpg/EventRunner.d.ts.map +0 -1
- package/dist/rpg/EventRunner.js +0 -125
- package/dist/rpg/EventRunner.js.map +0 -1
- package/dist/rpg/FreeMover.d.ts +0 -59
- package/dist/rpg/FreeMover.d.ts.map +0 -1
- package/dist/rpg/FreeMover.js +0 -79
- package/dist/rpg/FreeMover.js.map +0 -1
- package/dist/rpg/GameState.d.ts +0 -36
- package/dist/rpg/GameState.d.ts.map +0 -1
- package/dist/rpg/GameState.js +0 -49
- package/dist/rpg/GameState.js.map +0 -1
- package/dist/rpg/GridMover.d.ts +0 -71
- package/dist/rpg/GridMover.d.ts.map +0 -1
- package/dist/rpg/GridMover.js +0 -119
- package/dist/rpg/GridMover.js.map +0 -1
- package/dist/rpg/Marshal.d.ts +0 -81
- package/dist/rpg/Marshal.d.ts.map +0 -1
- package/dist/rpg/Marshal.js +0 -422
- package/dist/rpg/Marshal.js.map +0 -1
- package/dist/rpg/MovableSprite.d.ts +0 -31
- package/dist/rpg/MovableSprite.d.ts.map +0 -1
- package/dist/rpg/MovableSprite.js +0 -10
- package/dist/rpg/MovableSprite.js.map +0 -1
- package/dist/rpg/MoveRoute.d.ts +0 -118
- package/dist/rpg/MoveRoute.d.ts.map +0 -1
- package/dist/rpg/MoveRoute.js +0 -139
- package/dist/rpg/MoveRoute.js.map +0 -1
- package/dist/rpg/Quest.d.ts +0 -173
- package/dist/rpg/Quest.d.ts.map +0 -1
- package/dist/rpg/Quest.js +0 -221
- package/dist/rpg/Quest.js.map +0 -1
- package/dist/rpg/automap.d.ts +0 -81
- package/dist/rpg/automap.d.ts.map +0 -1
- package/dist/rpg/automap.js +0 -107
- package/dist/rpg/automap.js.map +0 -1
- package/dist/rpg/dialogue-text.d.ts +0 -81
- package/dist/rpg/dialogue-text.d.ts.map +0 -1
- package/dist/rpg/dialogue-text.js +0 -88
- package/dist/rpg/dialogue-text.js.map +0 -1
- package/dist/rpg/index.d.ts +0 -25
- package/dist/rpg/index.d.ts.map +0 -1
- package/dist/rpg/index.js +0 -14
- package/dist/rpg/index.js.map +0 -1
- package/dist/rpg/twee-events.d.ts +0 -48
- package/dist/rpg/twee-events.d.ts.map +0 -1
- package/dist/rpg/twee-events.js +0 -35
- package/dist/rpg/twee-events.js.map +0 -1
- package/dist/simulation/Campaign.d.ts +0 -60
- package/dist/simulation/Campaign.d.ts.map +0 -1
- package/dist/simulation/Campaign.js +0 -89
- package/dist/simulation/Campaign.js.map +0 -1
- package/dist/simulation/CampaignSave.d.ts +0 -68
- package/dist/simulation/CampaignSave.d.ts.map +0 -1
- package/dist/simulation/CampaignSave.js +0 -54
- package/dist/simulation/CampaignSave.js.map +0 -1
- package/dist/simulation/EventPresentation.d.ts +0 -111
- package/dist/simulation/EventPresentation.d.ts.map +0 -1
- package/dist/simulation/EventPresentation.js +0 -120
- package/dist/simulation/EventPresentation.js.map +0 -1
- package/dist/simulation/Harness.d.ts +0 -26
- package/dist/simulation/Harness.d.ts.map +0 -1
- package/dist/simulation/Harness.js +0 -26
- package/dist/simulation/Harness.js.map +0 -1
- package/dist/simulation/Runtime.d.ts +0 -189
- package/dist/simulation/Runtime.d.ts.map +0 -1
- package/dist/simulation/Runtime.js +0 -244
- package/dist/simulation/Runtime.js.map +0 -1
- package/dist/simulation/Scenario.d.ts +0 -44
- package/dist/simulation/Scenario.d.ts.map +0 -1
- package/dist/simulation/Scenario.js +0 -40
- package/dist/simulation/Scenario.js.map +0 -1
- package/dist/simulation/Training.d.ts +0 -220
- package/dist/simulation/Training.d.ts.map +0 -1
- package/dist/simulation/Training.js +0 -366
- package/dist/simulation/Training.js.map +0 -1
- package/dist/simulation/Turns.d.ts +0 -40
- package/dist/simulation/Turns.d.ts.map +0 -1
- package/dist/simulation/Turns.js +0 -41
- package/dist/simulation/Turns.js.map +0 -1
- package/dist/simulation/index.d.ts +0 -25
- package/dist/simulation/index.d.ts.map +0 -1
- package/dist/simulation/index.js +0 -16
- package/dist/simulation/index.js.map +0 -1
- package/dist/skeleton/index.d.ts +0 -212
- package/dist/skeleton/index.d.ts.map +0 -1
- package/dist/skeleton/index.js +0 -325
- package/dist/skeleton/index.js.map +0 -1
- package/dist/testing/SceneControls.d.ts +0 -35
- package/dist/testing/SceneControls.d.ts.map +0 -1
- package/dist/testing/SceneControls.js +0 -49
- package/dist/testing/SceneControls.js.map +0 -1
- package/dist/testing/index.d.ts +0 -123
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js +0 -156
- package/dist/testing/index.js.map +0 -1
- package/dist/threads/index.d.ts +0 -3
- package/dist/threads/index.d.ts.map +0 -1
- package/dist/threads/index.js +0 -2
- package/dist/threads/index.js.map +0 -1
- package/dist/threads/spawn.d.ts +0 -41
- package/dist/threads/spawn.d.ts.map +0 -1
- package/dist/threads/spawn.js +0 -143
- package/dist/threads/spawn.js.map +0 -1
- package/dist/threads/worker.d.ts +0 -51
- package/dist/threads/worker.d.ts.map +0 -1
- package/dist/threads/worker.js +0 -84
- package/dist/threads/worker.js.map +0 -1
- package/dist/three-d/Character3D.d.ts +0 -74
- package/dist/three-d/Character3D.d.ts.map +0 -1
- package/dist/three-d/Character3D.js +0 -122
- package/dist/three-d/Character3D.js.map +0 -1
- package/dist/three-d/Collision3D.d.ts +0 -111
- package/dist/three-d/Collision3D.d.ts.map +0 -1
- package/dist/three-d/Collision3D.js +0 -119
- package/dist/three-d/Collision3D.js.map +0 -1
- package/dist/three-d/Engine3D.d.ts +0 -25
- package/dist/three-d/Engine3D.d.ts.map +0 -1
- package/dist/three-d/Engine3D.js +0 -45
- package/dist/three-d/Engine3D.js.map +0 -1
- package/dist/three-d/Grid.d.ts +0 -30
- package/dist/three-d/Grid.d.ts.map +0 -1
- package/dist/three-d/Grid.js +0 -24
- package/dist/three-d/Grid.js.map +0 -1
- package/dist/three-d/Heightmap.d.ts +0 -38
- package/dist/three-d/Heightmap.d.ts.map +0 -1
- package/dist/three-d/Heightmap.js +0 -29
- package/dist/three-d/Heightmap.js.map +0 -1
- package/dist/three-d/Models.d.ts +0 -49
- package/dist/three-d/Models.d.ts.map +0 -1
- package/dist/three-d/Models.js +0 -77
- package/dist/three-d/Models.js.map +0 -1
- package/dist/three-d/TileGrid3D.d.ts +0 -27
- package/dist/three-d/TileGrid3D.d.ts.map +0 -1
- package/dist/three-d/TileGrid3D.js +0 -66
- package/dist/three-d/TileGrid3D.js.map +0 -1
- package/dist/three-d/Vox.d.ts +0 -43
- package/dist/three-d/Vox.d.ts.map +0 -1
- package/dist/three-d/Vox.js +0 -108
- package/dist/three-d/Vox.js.map +0 -1
- package/dist/three-d/index.d.ts +0 -15
- package/dist/three-d/index.d.ts.map +0 -1
- package/dist/three-d/index.js +0 -8
- package/dist/three-d/index.js.map +0 -1
- package/dist/two-d/Game.d.ts +0 -229
- package/dist/two-d/Game.d.ts.map +0 -1
- package/dist/two-d/Game.js +0 -463
- package/dist/two-d/Game.js.map +0 -1
- package/dist/two-d/QualityScaler.d.ts +0 -63
- package/dist/two-d/QualityScaler.d.ts.map +0 -1
- package/dist/two-d/QualityScaler.js +0 -92
- package/dist/two-d/QualityScaler.js.map +0 -1
- package/dist/two-d/ResolutionFit.d.ts +0 -28
- package/dist/two-d/ResolutionFit.d.ts.map +0 -1
- package/dist/two-d/ResolutionFit.js +0 -39
- package/dist/two-d/ResolutionFit.js.map +0 -1
- package/dist/two-d/Scene2D.d.ts +0 -43
- package/dist/two-d/Scene2D.d.ts.map +0 -1
- package/dist/two-d/Scene2D.js +0 -53
- package/dist/two-d/Scene2D.js.map +0 -1
- package/dist/two-d/index.d.ts +0 -22
- package/dist/two-d/index.d.ts.map +0 -1
- package/dist/two-d/index.js +0 -19
- package/dist/two-d/index.js.map +0 -1
- package/dist/two-d/pixi-interop.d.ts +0 -66
- package/dist/two-d/pixi-interop.d.ts.map +0 -1
- package/dist/two-d/pixi-interop.js +0 -72
- package/dist/two-d/pixi-interop.js.map +0 -1
- package/dist/two-d/presentation/MwlPresentation.d.ts +0 -117
- package/dist/two-d/presentation/MwlPresentation.d.ts.map +0 -1
- package/dist/two-d/presentation/MwlPresentation.js +0 -755
- package/dist/two-d/presentation/MwlPresentation.js.map +0 -1
- package/dist/two-d/presentation/index.d.ts +0 -3
- package/dist/two-d/presentation/index.d.ts.map +0 -1
- package/dist/two-d/presentation/index.js +0 -2
- package/dist/two-d/presentation/index.js.map +0 -1
- package/dist/two-d/render/ActorAnimator.d.ts +0 -92
- package/dist/two-d/render/ActorAnimator.d.ts.map +0 -1
- package/dist/two-d/render/ActorAnimator.js +0 -97
- package/dist/two-d/render/ActorAnimator.js.map +0 -1
- package/dist/two-d/render/AnimatedSprite.d.ts +0 -154
- package/dist/two-d/render/AnimatedSprite.d.ts.map +0 -1
- package/dist/two-d/render/AnimatedSprite.js +0 -197
- package/dist/two-d/render/AnimatedSprite.js.map +0 -1
- package/dist/two-d/render/Autotile.d.ts +0 -74
- package/dist/two-d/render/Autotile.d.ts.map +0 -1
- package/dist/two-d/render/Autotile.js +0 -149
- package/dist/two-d/render/Autotile.js.map +0 -1
- package/dist/two-d/render/Beam.d.ts +0 -136
- package/dist/two-d/render/Beam.d.ts.map +0 -1
- package/dist/two-d/render/Beam.js +0 -203
- package/dist/two-d/render/Beam.js.map +0 -1
- package/dist/two-d/render/Camera.d.ts +0 -255
- package/dist/two-d/render/Camera.d.ts.map +0 -1
- package/dist/two-d/render/Camera.js +0 -376
- package/dist/two-d/render/Camera.js.map +0 -1
- package/dist/two-d/render/Capabilities.d.ts +0 -84
- package/dist/two-d/render/Capabilities.d.ts.map +0 -1
- package/dist/two-d/render/Capabilities.js +0 -129
- package/dist/two-d/render/Capabilities.js.map +0 -1
- package/dist/two-d/render/ClothSprite.d.ts +0 -83
- package/dist/two-d/render/ClothSprite.d.ts.map +0 -1
- package/dist/two-d/render/ClothSprite.js +0 -105
- package/dist/two-d/render/ClothSprite.js.map +0 -1
- package/dist/two-d/render/ColorBlindness.d.ts +0 -39
- package/dist/two-d/render/ColorBlindness.d.ts.map +0 -1
- package/dist/two-d/render/ColorBlindness.js +0 -45
- package/dist/two-d/render/ColorBlindness.js.map +0 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts +0 -143
- package/dist/two-d/render/ColorTransformBatcher.d.ts.map +0 -1
- package/dist/two-d/render/ColorTransformBatcher.js +0 -395
- package/dist/two-d/render/ColorTransformBatcher.js.map +0 -1
- package/dist/two-d/render/Flights.d.ts +0 -90
- package/dist/two-d/render/Flights.d.ts.map +0 -1
- package/dist/two-d/render/Flights.js +0 -135
- package/dist/two-d/render/Flights.js.map +0 -1
- package/dist/two-d/render/FogLayer.d.ts +0 -68
- package/dist/two-d/render/FogLayer.d.ts.map +0 -1
- package/dist/two-d/render/FogLayer.js +0 -83
- package/dist/two-d/render/FogLayer.js.map +0 -1
- package/dist/two-d/render/Halo.d.ts +0 -58
- package/dist/two-d/render/Halo.d.ts.map +0 -1
- package/dist/two-d/render/Halo.js +0 -48
- package/dist/two-d/render/Halo.js.map +0 -1
- package/dist/two-d/render/HazeLayer.d.ts +0 -112
- package/dist/two-d/render/HazeLayer.d.ts.map +0 -1
- package/dist/two-d/render/HazeLayer.js +0 -185
- package/dist/two-d/render/HazeLayer.js.map +0 -1
- package/dist/two-d/render/ImageModifiers.d.ts +0 -310
- package/dist/two-d/render/ImageModifiers.d.ts.map +0 -1
- package/dist/two-d/render/ImageModifiers.js +0 -723
- package/dist/two-d/render/ImageModifiers.js.map +0 -1
- package/dist/two-d/render/LayeredSprite.d.ts +0 -54
- package/dist/two-d/render/LayeredSprite.d.ts.map +0 -1
- package/dist/two-d/render/LayeredSprite.js +0 -80
- package/dist/two-d/render/LayeredSprite.js.map +0 -1
- package/dist/two-d/render/LightningArc.d.ts +0 -57
- package/dist/two-d/render/LightningArc.d.ts.map +0 -1
- package/dist/two-d/render/LightningArc.js +0 -91
- package/dist/two-d/render/LightningArc.js.map +0 -1
- package/dist/two-d/render/LiquidLayer.d.ts +0 -62
- package/dist/two-d/render/LiquidLayer.d.ts.map +0 -1
- package/dist/two-d/render/LiquidLayer.js +0 -102
- package/dist/two-d/render/LiquidLayer.js.map +0 -1
- package/dist/two-d/render/Minimap.d.ts +0 -100
- package/dist/two-d/render/Minimap.d.ts.map +0 -1
- package/dist/two-d/render/Minimap.js +0 -157
- package/dist/two-d/render/Minimap.js.map +0 -1
- package/dist/two-d/render/NeonGlow.d.ts +0 -100
- package/dist/two-d/render/NeonGlow.d.ts.map +0 -1
- package/dist/two-d/render/NeonGlow.js +0 -183
- package/dist/two-d/render/NeonGlow.js.map +0 -1
- package/dist/two-d/render/PaletteRemap.d.ts +0 -154
- package/dist/two-d/render/PaletteRemap.d.ts.map +0 -1
- package/dist/two-d/render/PaletteRemap.js +0 -217
- package/dist/two-d/render/PaletteRemap.js.map +0 -1
- package/dist/two-d/render/Particles.d.ts +0 -262
- package/dist/two-d/render/Particles.d.ts.map +0 -1
- package/dist/two-d/render/Particles.js +0 -370
- package/dist/two-d/render/Particles.js.map +0 -1
- package/dist/two-d/render/Projectile.d.ts +0 -67
- package/dist/two-d/render/Projectile.d.ts.map +0 -1
- package/dist/two-d/render/Projectile.js +0 -78
- package/dist/two-d/render/Projectile.js.map +0 -1
- package/dist/two-d/render/RpgmAutotile.d.ts +0 -324
- package/dist/two-d/render/RpgmAutotile.d.ts.map +0 -1
- package/dist/two-d/render/RpgmAutotile.js +0 -933
- package/dist/two-d/render/RpgmAutotile.js.map +0 -1
- package/dist/two-d/render/SceneTransition.d.ts +0 -272
- package/dist/two-d/render/SceneTransition.d.ts.map +0 -1
- package/dist/two-d/render/SceneTransition.js +0 -431
- package/dist/two-d/render/SceneTransition.js.map +0 -1
- package/dist/two-d/render/ScreenEffects.d.ts +0 -124
- package/dist/two-d/render/ScreenEffects.d.ts.map +0 -1
- package/dist/two-d/render/ScreenEffects.js +0 -214
- package/dist/two-d/render/ScreenEffects.js.map +0 -1
- package/dist/two-d/render/Shape2D.d.ts +0 -146
- package/dist/two-d/render/Shape2D.d.ts.map +0 -1
- package/dist/two-d/render/Shape2D.js +0 -166
- package/dist/two-d/render/Shape2D.js.map +0 -1
- package/dist/two-d/render/SkeletalSprite.d.ts +0 -121
- package/dist/two-d/render/SkeletalSprite.d.ts.map +0 -1
- package/dist/two-d/render/SkeletalSprite.js +0 -213
- package/dist/two-d/render/SkeletalSprite.js.map +0 -1
- package/dist/two-d/render/SpringSprite.d.ts +0 -40
- package/dist/two-d/render/SpringSprite.d.ts.map +0 -1
- package/dist/two-d/render/SpringSprite.js +0 -39
- package/dist/two-d/render/SpringSprite.js.map +0 -1
- package/dist/two-d/render/SpriteAttachment.d.ts +0 -55
- package/dist/two-d/render/SpriteAttachment.d.ts.map +0 -1
- package/dist/two-d/render/SpriteAttachment.js +0 -60
- package/dist/two-d/render/SpriteAttachment.js.map +0 -1
- package/dist/two-d/render/SpriteDeform.d.ts +0 -156
- package/dist/two-d/render/SpriteDeform.d.ts.map +0 -1
- package/dist/two-d/render/SpriteDeform.js +0 -278
- package/dist/two-d/render/SpriteDeform.js.map +0 -1
- package/dist/two-d/render/SpriteGroup.d.ts +0 -83
- package/dist/two-d/render/SpriteGroup.d.ts.map +0 -1
- package/dist/two-d/render/SpriteGroup.js +0 -107
- package/dist/two-d/render/SpriteGroup.js.map +0 -1
- package/dist/two-d/render/SpriteMotion.d.ts +0 -121
- package/dist/two-d/render/SpriteMotion.d.ts.map +0 -1
- package/dist/two-d/render/SpriteMotion.js +0 -193
- package/dist/two-d/render/SpriteMotion.js.map +0 -1
- package/dist/two-d/render/SpriteSheet.d.ts +0 -62
- package/dist/two-d/render/SpriteSheet.d.ts.map +0 -1
- package/dist/two-d/render/SpriteSheet.js +0 -122
- package/dist/two-d/render/SpriteSheet.js.map +0 -1
- package/dist/two-d/render/StatusVisuals.d.ts +0 -86
- package/dist/two-d/render/StatusVisuals.d.ts.map +0 -1
- package/dist/two-d/render/StatusVisuals.js +0 -111
- package/dist/two-d/render/StatusVisuals.js.map +0 -1
- package/dist/two-d/render/SvgSkeleton.d.ts +0 -54
- package/dist/two-d/render/SvgSkeleton.d.ts.map +0 -1
- package/dist/two-d/render/SvgSkeleton.js +0 -112
- package/dist/two-d/render/SvgSkeleton.js.map +0 -1
- package/dist/two-d/render/TerrainGraphics.d.ts +0 -142
- package/dist/two-d/render/TerrainGraphics.d.ts.map +0 -1
- package/dist/two-d/render/TerrainGraphics.js +0 -161
- package/dist/two-d/render/TerrainGraphics.js.map +0 -1
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts +0 -55
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts.map +0 -1
- package/dist/two-d/render/TerrainGraphicsLayer.js +0 -54
- package/dist/two-d/render/TerrainGraphicsLayer.js.map +0 -1
- package/dist/two-d/render/TileMap.d.ts +0 -395
- package/dist/two-d/render/TileMap.d.ts.map +0 -1
- package/dist/two-d/render/TileMap.js +0 -967
- package/dist/two-d/render/TileMap.js.map +0 -1
- package/dist/two-d/render/TiledMap.d.ts +0 -113
- package/dist/two-d/render/TiledMap.d.ts.map +0 -1
- package/dist/two-d/render/TiledMap.js +0 -129
- package/dist/two-d/render/TiledMap.js.map +0 -1
- package/dist/two-d/render/TintedSprite.d.ts +0 -60
- package/dist/two-d/render/TintedSprite.d.ts.map +0 -1
- package/dist/two-d/render/TintedSprite.js +0 -88
- package/dist/two-d/render/TintedSprite.js.map +0 -1
- package/dist/two-d/render/Types2D.d.ts +0 -56
- package/dist/two-d/render/Types2D.d.ts.map +0 -1
- package/dist/two-d/render/Types2D.js +0 -45
- package/dist/two-d/render/Types2D.js.map +0 -1
- package/dist/two-d/render/Viewport.d.ts +0 -68
- package/dist/two-d/render/Viewport.d.ts.map +0 -1
- package/dist/two-d/render/Viewport.js +0 -74
- package/dist/two-d/render/Viewport.js.map +0 -1
- package/dist/two-d/render/index.d.ts +0 -81
- package/dist/two-d/render/index.d.ts.map +0 -1
- package/dist/two-d/render/index.js +0 -43
- package/dist/two-d/render/index.js.map +0 -1
- package/dist/two-d/stage/DialogueStage.d.ts +0 -90
- package/dist/two-d/stage/DialogueStage.d.ts.map +0 -1
- package/dist/two-d/stage/DialogueStage.js +0 -218
- package/dist/two-d/stage/DialogueStage.js.map +0 -1
- package/dist/two-d/stage/StoryScreen.d.ts +0 -110
- package/dist/two-d/stage/StoryScreen.d.ts.map +0 -1
- package/dist/two-d/stage/StoryScreen.js +0 -178
- package/dist/two-d/stage/StoryScreen.js.map +0 -1
- package/dist/two-d/stage/dialogue-text.d.ts +0 -81
- package/dist/two-d/stage/dialogue-text.d.ts.map +0 -1
- package/dist/two-d/stage/dialogue-text.js +0 -95
- package/dist/two-d/stage/dialogue-text.js.map +0 -1
- package/dist/two-d/stage/index.d.ts +0 -10
- package/dist/two-d/stage/index.d.ts.map +0 -1
- package/dist/two-d/stage/index.js +0 -6
- package/dist/two-d/stage/index.js.map +0 -1
- package/dist/two-d/stage/script.d.ts +0 -160
- package/dist/two-d/stage/script.d.ts.map +0 -1
- package/dist/two-d/stage/script.js +0 -207
- package/dist/two-d/stage/script.js.map +0 -1
- package/dist/two-d/stage/twee.d.ts +0 -35
- package/dist/two-d/stage/twee.d.ts.map +0 -1
- package/dist/two-d/stage/twee.js +0 -28
- package/dist/two-d/stage/twee.js.map +0 -1
- package/dist/two-d/ui/Bar.d.ts +0 -83
- package/dist/two-d/ui/Bar.d.ts.map +0 -1
- package/dist/two-d/ui/Bar.js +0 -112
- package/dist/two-d/ui/Bar.js.map +0 -1
- package/dist/two-d/ui/BitmapLabel.d.ts +0 -58
- package/dist/two-d/ui/BitmapLabel.d.ts.map +0 -1
- package/dist/two-d/ui/BitmapLabel.js +0 -82
- package/dist/two-d/ui/BitmapLabel.js.map +0 -1
- package/dist/two-d/ui/Button.d.ts +0 -133
- package/dist/two-d/ui/Button.d.ts.map +0 -1
- package/dist/two-d/ui/Button.js +0 -254
- package/dist/two-d/ui/Button.js.map +0 -1
- package/dist/two-d/ui/Checkbox.d.ts +0 -44
- package/dist/two-d/ui/Checkbox.d.ts.map +0 -1
- package/dist/two-d/ui/Checkbox.js +0 -89
- package/dist/two-d/ui/Checkbox.js.map +0 -1
- package/dist/two-d/ui/DataTable.d.ts +0 -79
- package/dist/two-d/ui/DataTable.d.ts.map +0 -1
- package/dist/two-d/ui/DataTable.js +0 -164
- package/dist/two-d/ui/DataTable.js.map +0 -1
- package/dist/two-d/ui/Dropdown.d.ts +0 -75
- package/dist/two-d/ui/Dropdown.d.ts.map +0 -1
- package/dist/two-d/ui/Dropdown.js +0 -129
- package/dist/two-d/ui/Dropdown.js.map +0 -1
- package/dist/two-d/ui/DropdownView.d.ts +0 -86
- package/dist/two-d/ui/DropdownView.d.ts.map +0 -1
- package/dist/two-d/ui/DropdownView.js +0 -216
- package/dist/two-d/ui/DropdownView.js.map +0 -1
- package/dist/two-d/ui/EventDialogue.d.ts +0 -23
- package/dist/two-d/ui/EventDialogue.d.ts.map +0 -1
- package/dist/two-d/ui/EventDialogue.js +0 -33
- package/dist/two-d/ui/EventDialogue.js.map +0 -1
- package/dist/two-d/ui/FloatingText.d.ts +0 -123
- package/dist/two-d/ui/FloatingText.d.ts.map +0 -1
- package/dist/two-d/ui/FloatingText.js +0 -152
- package/dist/two-d/ui/FloatingText.js.map +0 -1
- package/dist/two-d/ui/FloatingTextStack.d.ts +0 -150
- package/dist/two-d/ui/FloatingTextStack.d.ts.map +0 -1
- package/dist/two-d/ui/FloatingTextStack.js +0 -170
- package/dist/two-d/ui/FloatingTextStack.js.map +0 -1
- package/dist/two-d/ui/HelpScreen.d.ts +0 -45
- package/dist/two-d/ui/HelpScreen.d.ts.map +0 -1
- package/dist/two-d/ui/HelpScreen.js +0 -59
- package/dist/two-d/ui/HelpScreen.js.map +0 -1
- package/dist/two-d/ui/IconGrid.d.ts +0 -143
- package/dist/two-d/ui/IconGrid.d.ts.map +0 -1
- package/dist/two-d/ui/IconGrid.js +0 -326
- package/dist/two-d/ui/IconGrid.js.map +0 -1
- package/dist/two-d/ui/Label.d.ts +0 -63
- package/dist/two-d/ui/Label.d.ts.map +0 -1
- package/dist/two-d/ui/Label.js +0 -134
- package/dist/two-d/ui/Label.js.map +0 -1
- package/dist/two-d/ui/Layout.d.ts +0 -139
- package/dist/two-d/ui/Layout.d.ts.map +0 -1
- package/dist/two-d/ui/Layout.js +0 -221
- package/dist/two-d/ui/Layout.js.map +0 -1
- package/dist/two-d/ui/ListView.d.ts +0 -130
- package/dist/two-d/ui/ListView.d.ts.map +0 -1
- package/dist/two-d/ui/ListView.js +0 -325
- package/dist/two-d/ui/ListView.js.map +0 -1
- package/dist/two-d/ui/LoadingScreen.d.ts +0 -54
- package/dist/two-d/ui/LoadingScreen.d.ts.map +0 -1
- package/dist/two-d/ui/LoadingScreen.js +0 -87
- package/dist/two-d/ui/LoadingScreen.js.map +0 -1
- package/dist/two-d/ui/MarkupText.d.ts +0 -66
- package/dist/two-d/ui/MarkupText.d.ts.map +0 -1
- package/dist/two-d/ui/MarkupText.js +0 -156
- package/dist/two-d/ui/MarkupText.js.map +0 -1
- package/dist/two-d/ui/MessageBox.d.ts +0 -134
- package/dist/two-d/ui/MessageBox.d.ts.map +0 -1
- package/dist/two-d/ui/MessageBox.js +0 -263
- package/dist/two-d/ui/MessageBox.js.map +0 -1
- package/dist/two-d/ui/MessageLog.d.ts +0 -90
- package/dist/two-d/ui/MessageLog.d.ts.map +0 -1
- package/dist/two-d/ui/MessageLog.js +0 -131
- package/dist/two-d/ui/MessageLog.js.map +0 -1
- package/dist/two-d/ui/Meter.d.ts +0 -76
- package/dist/two-d/ui/Meter.d.ts.map +0 -1
- package/dist/two-d/ui/Meter.js +0 -134
- package/dist/two-d/ui/Meter.js.map +0 -1
- package/dist/two-d/ui/NinePatch.d.ts +0 -49
- package/dist/two-d/ui/NinePatch.d.ts.map +0 -1
- package/dist/two-d/ui/NinePatch.js +0 -59
- package/dist/two-d/ui/NinePatch.js.map +0 -1
- package/dist/two-d/ui/OnScreenKeyboard.d.ts +0 -91
- package/dist/two-d/ui/OnScreenKeyboard.d.ts.map +0 -1
- package/dist/two-d/ui/OnScreenKeyboard.js +0 -109
- package/dist/two-d/ui/OnScreenKeyboard.js.map +0 -1
- package/dist/two-d/ui/RadioGroup.d.ts +0 -68
- package/dist/two-d/ui/RadioGroup.d.ts.map +0 -1
- package/dist/two-d/ui/RadioGroup.js +0 -177
- package/dist/two-d/ui/RadioGroup.js.map +0 -1
- package/dist/two-d/ui/RebindScreen.d.ts +0 -70
- package/dist/two-d/ui/RebindScreen.d.ts.map +0 -1
- package/dist/two-d/ui/RebindScreen.js +0 -129
- package/dist/two-d/ui/RebindScreen.js.map +0 -1
- package/dist/two-d/ui/RichLabel.d.ts +0 -62
- package/dist/two-d/ui/RichLabel.d.ts.map +0 -1
- package/dist/two-d/ui/RichLabel.js +0 -146
- package/dist/two-d/ui/RichLabel.js.map +0 -1
- package/dist/two-d/ui/ScrollBox.d.ts +0 -157
- package/dist/two-d/ui/ScrollBox.d.ts.map +0 -1
- package/dist/two-d/ui/ScrollBox.js +0 -329
- package/dist/two-d/ui/ScrollBox.js.map +0 -1
- package/dist/two-d/ui/ScrollText.d.ts +0 -122
- package/dist/two-d/ui/ScrollText.d.ts.map +0 -1
- package/dist/two-d/ui/ScrollText.js +0 -202
- package/dist/two-d/ui/ScrollText.js.map +0 -1
- package/dist/two-d/ui/SelectionModel.d.ts +0 -50
- package/dist/two-d/ui/SelectionModel.d.ts.map +0 -1
- package/dist/two-d/ui/SelectionModel.js +0 -73
- package/dist/two-d/ui/SelectionModel.js.map +0 -1
- package/dist/two-d/ui/SettingsScreen.d.ts +0 -112
- package/dist/two-d/ui/SettingsScreen.d.ts.map +0 -1
- package/dist/two-d/ui/SettingsScreen.js +0 -338
- package/dist/two-d/ui/SettingsScreen.js.map +0 -1
- package/dist/two-d/ui/Skins.d.ts +0 -59
- package/dist/two-d/ui/Skins.d.ts.map +0 -1
- package/dist/two-d/ui/Skins.js +0 -77
- package/dist/two-d/ui/Skins.js.map +0 -1
- package/dist/two-d/ui/Slider.d.ts +0 -91
- package/dist/two-d/ui/Slider.d.ts.map +0 -1
- package/dist/two-d/ui/Slider.js +0 -170
- package/dist/two-d/ui/Slider.js.map +0 -1
- package/dist/two-d/ui/Spinner.d.ts +0 -67
- package/dist/two-d/ui/Spinner.d.ts.map +0 -1
- package/dist/two-d/ui/Spinner.js +0 -137
- package/dist/two-d/ui/Spinner.js.map +0 -1
- package/dist/two-d/ui/StatsScreen.d.ts +0 -40
- package/dist/two-d/ui/StatsScreen.d.ts.map +0 -1
- package/dist/two-d/ui/StatsScreen.js +0 -42
- package/dist/two-d/ui/StatsScreen.js.map +0 -1
- package/dist/two-d/ui/TabbedList.d.ts +0 -118
- package/dist/two-d/ui/TabbedList.d.ts.map +0 -1
- package/dist/two-d/ui/TabbedList.js +0 -221
- package/dist/two-d/ui/TabbedList.js.map +0 -1
- package/dist/two-d/ui/TextModel.d.ts +0 -90
- package/dist/two-d/ui/TextModel.d.ts.map +0 -1
- package/dist/two-d/ui/TextModel.js +0 -175
- package/dist/two-d/ui/TextModel.js.map +0 -1
- package/dist/two-d/ui/TextPrompt.d.ts +0 -122
- package/dist/two-d/ui/TextPrompt.d.ts.map +0 -1
- package/dist/two-d/ui/TextPrompt.js +0 -236
- package/dist/two-d/ui/TextPrompt.js.map +0 -1
- package/dist/two-d/ui/TextSharpness.d.ts +0 -33
- package/dist/two-d/ui/TextSharpness.d.ts.map +0 -1
- package/dist/two-d/ui/TextSharpness.js +0 -56
- package/dist/two-d/ui/TextSharpness.js.map +0 -1
- package/dist/two-d/ui/Toast.d.ts +0 -57
- package/dist/two-d/ui/Toast.d.ts.map +0 -1
- package/dist/two-d/ui/Toast.js +0 -101
- package/dist/two-d/ui/Toast.js.map +0 -1
- package/dist/two-d/ui/Tooltip.d.ts +0 -177
- package/dist/two-d/ui/Tooltip.d.ts.map +0 -1
- package/dist/two-d/ui/Tooltip.js +0 -275
- package/dist/two-d/ui/Tooltip.js.map +0 -1
- package/dist/two-d/ui/TreeView.d.ts +0 -68
- package/dist/two-d/ui/TreeView.d.ts.map +0 -1
- package/dist/two-d/ui/TreeView.js +0 -133
- package/dist/two-d/ui/TreeView.js.map +0 -1
- package/dist/two-d/ui/VerticalLabel.d.ts +0 -69
- package/dist/two-d/ui/VerticalLabel.d.ts.map +0 -1
- package/dist/two-d/ui/VerticalLabel.js +0 -110
- package/dist/two-d/ui/VerticalLabel.js.map +0 -1
- package/dist/two-d/ui/Window.d.ts +0 -188
- package/dist/two-d/ui/Window.d.ts.map +0 -1
- package/dist/two-d/ui/Window.js +0 -311
- package/dist/two-d/ui/Window.js.map +0 -1
- package/dist/two-d/ui/WindowStack.d.ts +0 -63
- package/dist/two-d/ui/WindowStack.d.ts.map +0 -1
- package/dist/two-d/ui/WindowStack.js +0 -132
- package/dist/two-d/ui/WindowStack.js.map +0 -1
- package/dist/two-d/ui/a11y.d.ts +0 -43
- package/dist/two-d/ui/a11y.d.ts.map +0 -1
- package/dist/two-d/ui/a11y.js +0 -79
- package/dist/two-d/ui/a11y.js.map +0 -1
- package/dist/two-d/ui/contrast.d.ts +0 -30
- package/dist/two-d/ui/contrast.d.ts.map +0 -1
- package/dist/two-d/ui/contrast.js +0 -42
- package/dist/two-d/ui/contrast.js.map +0 -1
- package/dist/two-d/ui/index.d.ts +0 -96
- package/dist/two-d/ui/index.d.ts.map +0 -1
- package/dist/two-d/ui/index.js +0 -49
- package/dist/two-d/ui/index.js.map +0 -1
- package/dist/two-d/ui/markdown.d.ts +0 -55
- package/dist/two-d/ui/markdown.d.ts.map +0 -1
- package/dist/two-d/ui/markdown.js +0 -147
- package/dist/two-d/ui/markdown.js.map +0 -1
- package/dist/two-d/ui/markup.d.ts +0 -189
- package/dist/two-d/ui/markup.d.ts.map +0 -1
- package/dist/two-d/ui/markup.js +0 -387
- package/dist/two-d/ui/markup.js.map +0 -1
- package/dist/two-d/ui/reveal.d.ts +0 -41
- package/dist/two-d/ui/reveal.d.ts.map +0 -1
- package/dist/two-d/ui/reveal.js +0 -22
- package/dist/two-d/ui/reveal.js.map +0 -1
- package/dist/two-d/ui/theme.d.ts +0 -133
- package/dist/two-d/ui/theme.d.ts.map +0 -1
- package/dist/two-d/ui/theme.js +0 -122
- package/dist/two-d/ui/theme.js.map +0 -1
- package/dist/two-d/ui/themedText.d.ts +0 -20
- package/dist/two-d/ui/themedText.d.ts.map +0 -1
- package/dist/two-d/ui/themedText.js +0 -9
- package/dist/two-d/ui/themedText.js.map +0 -1
- package/dist/version.d.ts +0 -13
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -13
- package/dist/version.js.map +0 -1
- package/dist/world/Encounters.d.ts +0 -32
- package/dist/world/Encounters.d.ts.map +0 -1
- package/dist/world/Encounters.js +0 -9
- package/dist/world/Encounters.js.map +0 -1
- package/dist/world/Environment.d.ts +0 -58
- package/dist/world/Environment.d.ts.map +0 -1
- package/dist/world/Environment.js +0 -89
- package/dist/world/Environment.js.map +0 -1
- package/dist/world/Overworld.d.ts +0 -39
- package/dist/world/Overworld.d.ts.map +0 -1
- package/dist/world/Overworld.js +0 -40
- package/dist/world/Overworld.js.map +0 -1
- package/dist/world/SideTurns.d.ts +0 -115
- package/dist/world/SideTurns.d.ts.map +0 -1
- package/dist/world/SideTurns.js +0 -138
- package/dist/world/SideTurns.js.map +0 -1
- package/dist/world/TurnClock.d.ts +0 -41
- package/dist/world/TurnClock.d.ts.map +0 -1
- package/dist/world/TurnClock.js +0 -49
- package/dist/world/TurnClock.js.map +0 -1
- package/dist/world/World.d.ts +0 -64
- package/dist/world/World.d.ts.map +0 -1
- package/dist/world/World.js +0 -91
- package/dist/world/World.js.map +0 -1
- package/dist/world/index.d.ts +0 -12
- package/dist/world/index.d.ts.map +0 -1
- package/dist/world/index.js +0 -7
- package/dist/world/index.js.map +0 -1
- package/sbom.cdx.json +0 -5996
- package/tools/mwl.mjs +0 -324
- package/tools/vendored/rgssad-wasm/LICENSE-MIT +0 -21
- package/tools/vendored/rgssad-wasm/README.md +0 -15
- package/tools/vendored/rgssad-wasm/package.json +0 -17
- package/tools/vendored/rgssad-wasm/rgssad_wasm.d.ts +0 -41
- package/tools/vendored/rgssad-wasm/rgssad_wasm.js +0 -6
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.js +0 -399
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm +0 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm.d.ts +0 -17
- package/tools.md +0 -219
package/dist/mwl/runtime.js
DELETED
|
@@ -1,1741 +0,0 @@
|
|
|
1
|
-
import { ActionJournal } from '../core/ActionJournal.js';
|
|
2
|
-
import { Generator } from '../core/Random.js';
|
|
3
|
-
import { decodeSaveEnvelope, encodeSave } from './persistence.js';
|
|
4
|
-
import { evaluateCondition } from './conditions.js';
|
|
5
|
-
import { evaluateExpression } from './expression.js';
|
|
6
|
-
import { booleanAttribute, booleanValue, integerAttribute, numberAttribute, requiredAttribute } from './utils.js';
|
|
7
|
-
import { endLevelCarryover } from './carryover.js';
|
|
8
|
-
const required = requiredAttribute;
|
|
9
|
-
const integer = (node, attribute, fallback) => integerAttribute(node, attribute, fallback) ?? fallback;
|
|
10
|
-
/**
|
|
11
|
-
* A fresh, empty world: no sides, units, maps or variables, at turn 1 and `playing`.
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```ts
|
|
15
|
-
* import { createWorld } from '@datamoc/mw_games/mwl';
|
|
16
|
-
*
|
|
17
|
-
* const world = createWorld();
|
|
18
|
-
* console.log(world.turn, world.status); // 1 'playing'
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export function createWorld() {
|
|
22
|
-
return {
|
|
23
|
-
variables: {},
|
|
24
|
-
units: {},
|
|
25
|
-
sides: {},
|
|
26
|
-
maps: {},
|
|
27
|
-
gold: {},
|
|
28
|
-
turn: 1,
|
|
29
|
-
status: 'playing',
|
|
30
|
-
sideStatus: {},
|
|
31
|
-
map: null,
|
|
32
|
-
timeOfDay: '',
|
|
33
|
-
scheduleIndex: 0,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
/** 1024x1024: far past any hand-made map, and short of a grid that exhausts memory while filling */
|
|
37
|
-
const MAX_TERRAIN_CELLS = 1024 * 1024;
|
|
38
|
-
/**
|
|
39
|
-
* Parse map text: one row per line, comma-separated codes. A token may be
|
|
40
|
-
* `<side> <code>` to mark that side's keep/start, which is how a leader knows
|
|
41
|
-
* where to appear.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* ```ts
|
|
45
|
-
* import { parseTerrain } from '@datamoc/mw_games/mwl';
|
|
46
|
-
*
|
|
47
|
-
* const map = parseTerrain('Gg,Gg\nGg,1 Kh');
|
|
48
|
-
* console.log(map.width, map.starts['1']); // 2 [{ x: 1, y: 1 }]
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export function parseTerrain(text) {
|
|
52
|
-
const rows = text
|
|
53
|
-
.split(/\r?\n/)
|
|
54
|
-
.filter((line) => line.trim() !== '')
|
|
55
|
-
.map((line) => line.split(',').map((token) => token.trim()));
|
|
56
|
-
const height = rows.length;
|
|
57
|
-
//a reduce, not `Math.max(...rows)`: spreading a hundred thousand rows overflows the stack
|
|
58
|
-
const width = rows.reduce((widest, row) => Math.max(widest, row.length), 0);
|
|
59
|
-
if (width * height > MAX_TERRAIN_CELLS)
|
|
60
|
-
throw new Error(`MWL terrain is ${width}x${height}, more than ${MAX_TERRAIN_CELLS} cells`);
|
|
61
|
-
const codes = [];
|
|
62
|
-
const starts = {};
|
|
63
|
-
for (let y = 0; y < height; y++) {
|
|
64
|
-
for (let x = 0; x < width; x++) {
|
|
65
|
-
const token = rows[y]?.[x] ?? '_off^_usr';
|
|
66
|
-
//`<side> <code>`: the side is the id `[side]` declares, so a named side works here too
|
|
67
|
-
const keep = /^([A-Za-z0-9_][\w.-]*)\s+(\S.*)$/.exec(token);
|
|
68
|
-
if (keep) {
|
|
69
|
-
codes.push(keep[2]);
|
|
70
|
-
(starts[keep[1]] ??= []).push({ x, y });
|
|
71
|
-
}
|
|
72
|
-
else
|
|
73
|
-
codes.push(token);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return { width, height, codes, starts };
|
|
77
|
-
}
|
|
78
|
-
/** The two reference forms MWL text writes: `$(expression)` and `$name`. */
|
|
79
|
-
const expressionReference = /\$\(([^)]*)\)/g;
|
|
80
|
-
const variableReference = /\$([A-Za-z_][A-Za-z0-9_.]*)/g;
|
|
81
|
-
/**
|
|
82
|
-
* Runtime for compiled MWL content. It never parses source text during play.
|
|
83
|
-
*
|
|
84
|
-
* The framework runtime owns what is game-agnostic: maps, sides, units, turn
|
|
85
|
-
* order, the schedule, objectives, events, and save/load. Game rules that need
|
|
86
|
-
* real data (pathfinding costs, combat formulas) stay in the engine adapter;
|
|
87
|
-
* this runtime's `move` is a bounds and occupancy check, and `attack` applies
|
|
88
|
-
* the amount the content asks for.
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```ts
|
|
92
|
-
* import { compile, MwlRuntime } from '@datamoc/mw_games/mwl';
|
|
93
|
-
*
|
|
94
|
-
* const runtime = new MwlRuntime(compile("[{ tag: 'game', schema: 0.1 }]"), {
|
|
95
|
-
* resolveMap: () => 'Gg,Gg\nGg,Gg',
|
|
96
|
-
* });
|
|
97
|
-
* console.log(runtime.world.turn); // 1
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export class MwlRuntime {
|
|
101
|
-
constructor(game, options = {}) {
|
|
102
|
-
this.journal = new ActionJournal();
|
|
103
|
-
this.unitTypes = new Map();
|
|
104
|
-
this.schedule = [];
|
|
105
|
-
this.pendingDialogue = null;
|
|
106
|
-
this.dialogueCounter = 0;
|
|
107
|
-
this.traceBatch = null;
|
|
108
|
-
this.game = game;
|
|
109
|
-
this.world = options.world ?? createWorld();
|
|
110
|
-
this.onMessage = options.onMessage;
|
|
111
|
-
this.resolveMap = options.resolveMap;
|
|
112
|
-
this.hooks = options.hooks;
|
|
113
|
-
this.onTrace = options.onTrace;
|
|
114
|
-
this.persistence = options.persistence ?? { version: 1 };
|
|
115
|
-
this.random = options.random ?? new Generator();
|
|
116
|
-
if (!options.random && this.world.random)
|
|
117
|
-
this.random.setState(this.world.random);
|
|
118
|
-
this.loadUnitTypes();
|
|
119
|
-
this.loadSchedule();
|
|
120
|
-
this.loadInitialContent();
|
|
121
|
-
this.loadInitialUnits();
|
|
122
|
-
this.loadLeaders();
|
|
123
|
-
//roles filter over the units, so this runs once they and the leaders are in the world
|
|
124
|
-
this.loadScenarioExtras();
|
|
125
|
-
}
|
|
126
|
-
run(trigger) {
|
|
127
|
-
this.recordAction({ type: 'run', trigger }, () => this.runInternal(trigger));
|
|
128
|
-
}
|
|
129
|
-
runInternal(trigger) {
|
|
130
|
-
for (const event of this.nodes('event')) {
|
|
131
|
-
if ((event.attributes.on ?? event.attributes.trigger) !== trigger)
|
|
132
|
-
continue;
|
|
133
|
-
if (!this.eventFiltersMatch(event))
|
|
134
|
-
continue;
|
|
135
|
-
if (!this.claimEvent(event))
|
|
136
|
-
continue;
|
|
137
|
-
this.executeTracedEvent(event, trigger);
|
|
138
|
-
}
|
|
139
|
-
this.checkObjectives();
|
|
140
|
-
}
|
|
141
|
-
/** Fire one named event through the same filter, claim, and execution path as a trigger. */
|
|
142
|
-
fireEvent(id) {
|
|
143
|
-
return this.recordAction({ type: 'fire_event', id }, () => this.fireEventInternal(id));
|
|
144
|
-
}
|
|
145
|
-
fireEventInternal(id) {
|
|
146
|
-
const event = this.nodes('event').find((candidate) => candidate.attributes.id === id);
|
|
147
|
-
if (!event || !this.eventFiltersMatch(event) || !this.claimEvent(event))
|
|
148
|
-
return false;
|
|
149
|
-
this.executeTracedEvent(event, 'fireEvent');
|
|
150
|
-
this.checkObjectives();
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Fire the `on=moveto` events for a unit that has just arrived somewhere.
|
|
155
|
-
* The runtime's own `[move]` command calls this, and so does a game whose
|
|
156
|
-
* engine moved the unit: write the new position into `world.units` first,
|
|
157
|
-
* then call this with the unit id.
|
|
158
|
-
*
|
|
159
|
-
* An event matches when `x`/`y` (when given) are the unit's position, and
|
|
160
|
-
* `unit`/`side` (when given) are the unit's. A moveto event fires once by
|
|
161
|
-
* default; pass `once=false` on the event to let it fire every time.
|
|
162
|
-
*/
|
|
163
|
-
fireMoveto(id) {
|
|
164
|
-
this.recordAction({ type: 'fire_moveto', unit: id }, () => this.fireMovetoInternal(id));
|
|
165
|
-
}
|
|
166
|
-
fireMovetoInternal(id) {
|
|
167
|
-
const unit = this.world.units[id];
|
|
168
|
-
if (!unit || !unit.alive)
|
|
169
|
-
return;
|
|
170
|
-
for (const event of this.nodes('event')) {
|
|
171
|
-
if ((event.attributes.on ?? event.attributes.trigger) !== 'moveto')
|
|
172
|
-
continue;
|
|
173
|
-
if (event.attributes.x !== undefined && !coordinateMatches(event.attributes.x, unit.x))
|
|
174
|
-
continue;
|
|
175
|
-
if (event.attributes.y !== undefined && !coordinateMatches(event.attributes.y, unit.y))
|
|
176
|
-
continue;
|
|
177
|
-
if (event.attributes.unit !== undefined && event.attributes.unit !== id)
|
|
178
|
-
continue;
|
|
179
|
-
if (event.attributes.side !== undefined && event.attributes.side !== unit.side)
|
|
180
|
-
continue;
|
|
181
|
-
if (!this.eventFiltersMatch(event))
|
|
182
|
-
continue;
|
|
183
|
-
if (!this.claimEvent(event))
|
|
184
|
-
continue;
|
|
185
|
-
this.executeTracedEvent(event, 'moveto');
|
|
186
|
-
}
|
|
187
|
-
this.checkObjectives();
|
|
188
|
-
}
|
|
189
|
-
/** A `moveto` event is a story beat: it fires once unless told otherwise. */
|
|
190
|
-
claimEvent(event) {
|
|
191
|
-
const once = event.attributes.once === undefined ? event.attributes.on === 'moveto' : event.attributes.once !== 'false';
|
|
192
|
-
if (!once)
|
|
193
|
-
return true;
|
|
194
|
-
const key = event.attributes.id ??
|
|
195
|
-
`${event.attributes.on ?? event.attributes.trigger ?? 'event'}@${event.location?.line ?? 0}`;
|
|
196
|
-
const fired = (this.world.firedEvents ??= []);
|
|
197
|
-
if (fired.includes(key))
|
|
198
|
-
return false;
|
|
199
|
-
fired.push(key);
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
eventFiltersMatch(event) {
|
|
203
|
-
if (!this.conditionMatches(event))
|
|
204
|
-
return false;
|
|
205
|
-
if (!this.filterConditionMatches(event))
|
|
206
|
-
return false;
|
|
207
|
-
const filter = event.children.find((child) => child.tag === 'filter');
|
|
208
|
-
return !filter || this.filterMatches(filter);
|
|
209
|
-
}
|
|
210
|
-
executeEvent(event) {
|
|
211
|
-
this.runBlock(this.commandChildren(event));
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Runs a sequence of commands, with `say` and `dialogue` taking the message path rather
|
|
215
|
-
* than `executeNode`. Shared by an event's top level, an `[if]`/`[else]` body and a
|
|
216
|
-
* dialogue branch, so all three treat a nested pair the same way.
|
|
217
|
-
*/
|
|
218
|
-
runBlock(children) {
|
|
219
|
-
for (let index = 0; index < children.length; index++) {
|
|
220
|
-
const child = children[index];
|
|
221
|
-
if (this.isConsumedElse(children, index))
|
|
222
|
-
continue;
|
|
223
|
-
if (child.tag === 'say') {
|
|
224
|
-
this.showSay(child);
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
if (child.tag === 'dialogue') {
|
|
228
|
-
this.showDialogue(child);
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
this.executeNode(child);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Whether an `[else]` at `index` is the branch its immediately preceding `[if]` already ran.
|
|
236
|
-
* A taken `[if]` runs its own body and owns the `[else]`, so the loop skips that `[else]`;
|
|
237
|
-
* a false `[if]` ran nothing, so the `[else]` is left for the loop to run as its fallback.
|
|
238
|
-
* A free-standing `[else]` with no `[if]` before it is never consumed.
|
|
239
|
-
*/
|
|
240
|
-
isConsumedElse(children, index) {
|
|
241
|
-
const previous = children[index - 1];
|
|
242
|
-
return children[index]?.tag === 'else' && previous?.tag === 'if' && this.nodeConditionMatches(previous);
|
|
243
|
-
}
|
|
244
|
-
executeTracedEvent(event, trigger) {
|
|
245
|
-
const id = event.attributes.id ??
|
|
246
|
-
`${event.attributes.on ?? event.attributes.trigger ?? 'event'}@${event.location?.line ?? 0}`;
|
|
247
|
-
this.trace({ type: 'event', phase: 'claimed', id, trigger });
|
|
248
|
-
try {
|
|
249
|
-
this.executeEvent(event);
|
|
250
|
-
this.trace({ type: 'event', phase: 'completed', id, trigger });
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
this.trace({ type: 'error', message: String(error), event: id });
|
|
254
|
-
throw error;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Deliver a `dialogue`: its `message`/`say` lines first, then one message
|
|
259
|
-
* carrying the offered `choice`s. A choice names the event answering runs;
|
|
260
|
-
* the game answers later with `answerDialogue`, so content keeps any
|
|
261
|
-
* follow-up commands inside the referenced events rather than after the
|
|
262
|
-
* dialogue. Choices gated by `variable`/`equals` are skipped unless the
|
|
263
|
-
* world variable matches.
|
|
264
|
-
*/
|
|
265
|
-
showDialogue(node) {
|
|
266
|
-
let last = null;
|
|
267
|
-
for (const child of node.children) {
|
|
268
|
-
if (child.tag === 'message') {
|
|
269
|
-
this.showMessage(child.attributes);
|
|
270
|
-
last = {
|
|
271
|
-
text: child.attributes.text ?? child.attributes.value ?? '',
|
|
272
|
-
...(child.attributes.speaker === undefined ? {} : { speaker: child.attributes.speaker }),
|
|
273
|
-
...(child.attributes.portrait === undefined ? {} : { portrait: child.attributes.portrait }),
|
|
274
|
-
...(child.attributes.side === undefined || child.attributes.side === ''
|
|
275
|
-
? {}
|
|
276
|
-
: { side: child.attributes.side }),
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
else if (child.tag === 'say') {
|
|
280
|
-
this.showSay(child);
|
|
281
|
-
last = { text: child.attributes.text ?? '', speaker: child.attributes.speaker };
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
const choices = [];
|
|
285
|
-
for (const child of node.children) {
|
|
286
|
-
if (child.tag !== 'choice' || !child.attributes.text)
|
|
287
|
-
continue;
|
|
288
|
-
if (child.attributes.variable !== undefined &&
|
|
289
|
-
!sameValue(this.variableAt(child.attributes.variable), child.attributes.equals))
|
|
290
|
-
continue;
|
|
291
|
-
const branches = child.children.filter((branch) => branch.tag === 'branch');
|
|
292
|
-
if (branches.length) {
|
|
293
|
-
for (const branch of branches) {
|
|
294
|
-
choices.push({
|
|
295
|
-
text: branch.attributes.text ?? child.attributes.text,
|
|
296
|
-
branch: branch.children,
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
else if (child.attributes.event)
|
|
301
|
-
choices.push({ text: child.attributes.text, event: child.attributes.event });
|
|
302
|
-
}
|
|
303
|
-
if (choices.length === 0)
|
|
304
|
-
return;
|
|
305
|
-
this.dialogueCounter += 1;
|
|
306
|
-
const id = `dialogue-${this.dialogueCounter}`;
|
|
307
|
-
this.pendingDialogue = { id, choices };
|
|
308
|
-
this.world.pendingDialogue = { id, choices };
|
|
309
|
-
this.onMessage?.({
|
|
310
|
-
text: last?.text ?? '',
|
|
311
|
-
...(last?.speaker === undefined ? {} : { speaker: last.speaker }),
|
|
312
|
-
choices,
|
|
313
|
-
dialogueId: id,
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
showSay(node) {
|
|
317
|
-
if (!this.onMessage)
|
|
318
|
-
return;
|
|
319
|
-
this.onMessage({
|
|
320
|
-
text: node.attributes.text ?? '',
|
|
321
|
-
...(node.attributes.speaker === undefined ? {} : { speaker: node.attributes.speaker }),
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Answer a pending dialogue: run the chosen choice's event and clear the
|
|
326
|
-
* pending state. Returns false when there is no such pending dialogue or
|
|
327
|
-
* choice; throws when the referenced event does not exist (content error).
|
|
328
|
-
*/
|
|
329
|
-
answerDialogue(dialogueId, choiceIndex) {
|
|
330
|
-
return this.recordAction({ type: 'answer_dialogue', dialogueId, choiceIndex }, () => this.answerDialogueInternal(dialogueId, choiceIndex));
|
|
331
|
-
}
|
|
332
|
-
answerDialogueInternal(dialogueId, choiceIndex) {
|
|
333
|
-
const pending = this.pendingDialogue;
|
|
334
|
-
if (!pending || pending.id !== dialogueId)
|
|
335
|
-
return false;
|
|
336
|
-
const choice = pending.choices[choiceIndex];
|
|
337
|
-
if (!choice)
|
|
338
|
-
return false;
|
|
339
|
-
this.pendingDialogue = null;
|
|
340
|
-
delete this.world.pendingDialogue;
|
|
341
|
-
if (choice.event) {
|
|
342
|
-
const event = this.nodes('event').find((candidate) => candidate.attributes.id === choice.event);
|
|
343
|
-
if (!event)
|
|
344
|
-
throw new Error(`MWL dialogue choice points at unknown event: ${choice.event}`);
|
|
345
|
-
if (!this.claimEvent(event))
|
|
346
|
-
return true;
|
|
347
|
-
this.executeEvent(event);
|
|
348
|
-
}
|
|
349
|
-
else {
|
|
350
|
-
this.runBlock(choice.branch ?? []);
|
|
351
|
-
}
|
|
352
|
-
this.checkObjectives();
|
|
353
|
-
return true;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Evaluate `[objectives]` now and return the resulting status. A game whose
|
|
357
|
-
* own engine resolved the actions (real movement, combat) calls this after
|
|
358
|
-
* writing the results into `world`; `run` already calls it itself.
|
|
359
|
-
*/
|
|
360
|
-
evaluate() {
|
|
361
|
-
this.checkObjectives();
|
|
362
|
-
return this.world.status;
|
|
363
|
-
}
|
|
364
|
-
save() {
|
|
365
|
-
const state = this.hooks?.saveable;
|
|
366
|
-
const hookState = state
|
|
367
|
-
? Object.fromEntries(Object.entries(state).map(([id, hook]) => [id, hook.save()]))
|
|
368
|
-
: undefined;
|
|
369
|
-
return encodeSave(this.world, this.persistence, hookState, this.journal.toJSON());
|
|
370
|
-
}
|
|
371
|
-
snapshot() {
|
|
372
|
-
return JSON.stringify(this.world);
|
|
373
|
-
}
|
|
374
|
-
restore(snapshot) {
|
|
375
|
-
const envelope = decodeSaveEnvelope(snapshot, this.persistence);
|
|
376
|
-
const restored = envelope.world;
|
|
377
|
-
Object.assign(this.world.variables, restored.variables);
|
|
378
|
-
Object.assign(this.world.units, restored.units);
|
|
379
|
-
Object.assign(this.world.sides, restored.sides ?? {});
|
|
380
|
-
Object.assign(this.world.maps, restored.maps ?? {});
|
|
381
|
-
Object.assign(this.world.gold, restored.gold ?? {});
|
|
382
|
-
this.world.turn = restored.turn;
|
|
383
|
-
this.world.status = restored.status;
|
|
384
|
-
this.world.sideStatus = { ...(restored.sideStatus ?? {}) };
|
|
385
|
-
this.world.map = restored.map ?? null;
|
|
386
|
-
this.world.timeOfDay = restored.timeOfDay ?? this.schedule[0] ?? '';
|
|
387
|
-
this.world.scheduleIndex = restored.scheduleIndex ?? 0;
|
|
388
|
-
// A save predating this field, or one from a game that never drew hook randomness, has
|
|
389
|
-
// nothing to resume: reseed fresh rather than let a hook's first post-restore draw depend
|
|
390
|
-
// on wherever this runtime's own generator happened to be before the load.
|
|
391
|
-
this.world.random = restored.random;
|
|
392
|
-
this.random.setState(restored.random ?? new Generator().getState());
|
|
393
|
-
// One-shot events stay spent across a load.
|
|
394
|
-
this.world.firedEvents = [...(restored.firedEvents ?? [])];
|
|
395
|
-
// Scenario data a command may have changed, restored wholesale rather than merged: a load
|
|
396
|
-
// is that save's world, not this scenario's with a few fields over it.
|
|
397
|
-
this.world.villages = restored.villages ? structuredClone(restored.villages) : undefined;
|
|
398
|
-
this.world.clearedShroud = restored.clearedShroud ? structuredClone(restored.clearedShroud) : undefined;
|
|
399
|
-
this.world.roles = restored.roles ? structuredClone(restored.roles) : undefined;
|
|
400
|
-
this.world.objects = restored.objects ? structuredClone(restored.objects) : undefined;
|
|
401
|
-
this.world.story = restored.story ? structuredClone(restored.story) : undefined;
|
|
402
|
-
this.world.pendingDialogue = restored.pendingDialogue;
|
|
403
|
-
this.pendingDialogue = restored.pendingDialogue
|
|
404
|
-
? { id: restored.pendingDialogue.id, choices: [...restored.pendingDialogue.choices] }
|
|
405
|
-
: null;
|
|
406
|
-
const dialogueNumber = restored.pendingDialogue?.id.match(/^dialogue-(\d+)$/);
|
|
407
|
-
if (dialogueNumber)
|
|
408
|
-
this.dialogueCounter = Math.max(this.dialogueCounter, Number(dialogueNumber[1]));
|
|
409
|
-
for (const [id, state] of Object.entries(envelope.hookState ?? {}))
|
|
410
|
-
this.hooks?.saveable?.[id]?.restore(state);
|
|
411
|
-
this.journal.replace((envelope.journal ?? []));
|
|
412
|
-
}
|
|
413
|
-
recordAction(action, body) {
|
|
414
|
-
const outer = this.traceBatch === null;
|
|
415
|
-
if (outer)
|
|
416
|
-
this.traceBatch = [];
|
|
417
|
-
try {
|
|
418
|
-
const result = body();
|
|
419
|
-
if (outer)
|
|
420
|
-
this.journal.append(action, this.traceBatch ?? []);
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
finally {
|
|
424
|
-
if (outer)
|
|
425
|
-
this.traceBatch = null;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
trace(event) {
|
|
429
|
-
this.traceBatch?.push(event);
|
|
430
|
-
this.onTrace?.(event);
|
|
431
|
-
}
|
|
432
|
-
loadUnitTypes() {
|
|
433
|
-
for (const node of this.nodes('unit_type')) {
|
|
434
|
-
const id = node.attributes.id;
|
|
435
|
-
if (id)
|
|
436
|
-
this.unitTypes.set(id, {
|
|
437
|
-
hitpoints: integer(node, 'hitpoints', 1),
|
|
438
|
-
movement: integer(node, 'movement', 0),
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
loadSchedule() {
|
|
443
|
-
this.schedule = this.nodes('schedule').flatMap((schedule) => schedule.children
|
|
444
|
-
.filter((child) => child.tag === 'time')
|
|
445
|
-
.map((child) => child.attributes.id)
|
|
446
|
-
.filter((id) => Boolean(id)));
|
|
447
|
-
this.world.scheduleIndex = 0;
|
|
448
|
-
this.world.timeOfDay = this.schedule[0] ?? '';
|
|
449
|
-
}
|
|
450
|
-
loadInitialContent() {
|
|
451
|
-
for (const side of this.nodes('side')) {
|
|
452
|
-
const entry = {
|
|
453
|
-
gold: integer(side, 'gold', 0),
|
|
454
|
-
income: integer(side, 'income', 0),
|
|
455
|
-
};
|
|
456
|
-
if (side.attributes.leader !== undefined)
|
|
457
|
-
entry.leader = side.attributes.leader;
|
|
458
|
-
if (side.attributes.controller !== undefined)
|
|
459
|
-
entry.controller = side.attributes.controller;
|
|
460
|
-
if (side.attributes.recruit !== undefined)
|
|
461
|
-
entry.recruit = side.attributes.recruit;
|
|
462
|
-
//only what was written, so a world stays as small as the content that made it
|
|
463
|
-
if (side.attributes.team_name !== undefined)
|
|
464
|
-
entry.teamName = side.attributes.team_name;
|
|
465
|
-
if (side.attributes.user_team_name !== undefined)
|
|
466
|
-
entry.userTeamName = side.attributes.user_team_name;
|
|
467
|
-
if (side.attributes.share_vision !== undefined)
|
|
468
|
-
entry.shareVision = side.attributes.share_vision;
|
|
469
|
-
if (side.attributes.flag !== undefined)
|
|
470
|
-
entry.flag = side.attributes.flag;
|
|
471
|
-
if (side.attributes.village_gold !== undefined)
|
|
472
|
-
entry.villageGold = integer(side, 'village_gold', 0);
|
|
473
|
-
for (const key of ['heal', 'fog', 'shroud', 'hidden']) {
|
|
474
|
-
const written = side.attributes[key];
|
|
475
|
-
if (written !== undefined)
|
|
476
|
-
entry[key] = written === 'yes' || written === 'true';
|
|
477
|
-
}
|
|
478
|
-
this.world.sides[required(side, 'id')] = entry;
|
|
479
|
-
}
|
|
480
|
-
for (const map of this.nodes('map')) {
|
|
481
|
-
const id = map.attributes.id ?? map.attributes.name ?? 'map';
|
|
482
|
-
this.world.maps[id] = { terrain: map.attributes.terrain ?? '', file: map.attributes.file };
|
|
483
|
-
if (!this.world.map)
|
|
484
|
-
this.world.map = this.buildMap(id, map);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
/** Direct children of `[game]` with a tag, as opposed to `nodes` which searches the whole tree. */
|
|
488
|
-
topLevelNodes(tag) {
|
|
489
|
-
const game = this.game.roots.find((root) => root.tag === 'game');
|
|
490
|
-
return (game?.children ?? this.game.roots).filter((root) => root.tag === tag);
|
|
491
|
-
}
|
|
492
|
-
/**
|
|
493
|
-
* Scenario-level data that is not a side, a map or a unit: `[object]` placements, the `[story]`
|
|
494
|
-
* beats, and the `[role]` table. Kept as plain data on the world - the framework sequences and
|
|
495
|
-
* serialises it, and the game decides what an object does, what a story beat looks like, and
|
|
496
|
-
* what a role is for.
|
|
497
|
-
*/
|
|
498
|
-
loadScenarioExtras() {
|
|
499
|
-
for (const object of this.topLevelNodes('object')) {
|
|
500
|
-
const x = integer(object, 'x', 0);
|
|
501
|
-
const y = integer(object, 'y', 0);
|
|
502
|
-
const entry = { x, y };
|
|
503
|
-
if (object.attributes.id !== undefined)
|
|
504
|
-
entry.id = object.attributes.id;
|
|
505
|
-
if (object.attributes.name !== undefined)
|
|
506
|
-
entry.name = object.attributes.name;
|
|
507
|
-
if (object.attributes.image !== undefined)
|
|
508
|
-
entry.image = object.attributes.image;
|
|
509
|
-
if (object.attributes.side !== undefined)
|
|
510
|
-
entry.side = object.attributes.side;
|
|
511
|
-
(this.world.objects ??= []).push(entry);
|
|
512
|
-
}
|
|
513
|
-
for (const story of this.topLevelNodes('story')) {
|
|
514
|
-
const text = story.attributes.text ?? story.attributes.value;
|
|
515
|
-
if (text === undefined)
|
|
516
|
-
continue;
|
|
517
|
-
const entry = { text };
|
|
518
|
-
if (story.attributes.title !== undefined)
|
|
519
|
-
entry.title = story.attributes.title;
|
|
520
|
-
if (story.attributes.image !== undefined)
|
|
521
|
-
entry.image = story.attributes.image;
|
|
522
|
-
if (story.attributes.music !== undefined)
|
|
523
|
-
entry.music = story.attributes.music;
|
|
524
|
-
(this.world.story ??= []).push(entry);
|
|
525
|
-
}
|
|
526
|
-
for (const role of this.topLevelNodes('role')) {
|
|
527
|
-
const name = role.attributes.role ?? role.attributes.name;
|
|
528
|
-
if (name === undefined)
|
|
529
|
-
continue;
|
|
530
|
-
//`role`/`name` on this tag name the role being assigned, not a unit to match, so the
|
|
531
|
-
//filter must not read either back as one - the same double duty `[store_unit]`'s
|
|
532
|
-
//`variable`/`name` has
|
|
533
|
-
const filter = withoutAttributes(role.attributes, 'role', 'name');
|
|
534
|
-
const matched = Object.entries(this.world.units).filter(([id, unit]) => unit.alive && unitMatchesFilter(unit, id, filter));
|
|
535
|
-
//a unit learns the role it was assigned, so a later `[filter] role=courier` finds it
|
|
536
|
-
for (const [, unit] of matched)
|
|
537
|
-
unit.role = name;
|
|
538
|
-
(this.world.roles ??= {})[name] = matched.map(([id]) => id);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
buildMap(id, node) {
|
|
542
|
-
let text = node.attributes.terrain;
|
|
543
|
-
if (!text && node.attributes.file && this.resolveMap)
|
|
544
|
-
text = this.resolveMap(node.attributes.file);
|
|
545
|
-
if (!text)
|
|
546
|
-
return null;
|
|
547
|
-
const parsed = parseTerrain(text);
|
|
548
|
-
for (const start of node.children) {
|
|
549
|
-
if (start.tag !== 'start')
|
|
550
|
-
continue;
|
|
551
|
-
const side = start.attributes.side;
|
|
552
|
-
const x = optionalInteger(start, 'x');
|
|
553
|
-
const y = optionalInteger(start, 'y');
|
|
554
|
-
if (side !== undefined && x !== undefined && y !== undefined)
|
|
555
|
-
(parsed.starts[side] ??= []).push({ x, y });
|
|
556
|
-
}
|
|
557
|
-
return { id, ...parsed };
|
|
558
|
-
}
|
|
559
|
-
loadInitialUnits() {
|
|
560
|
-
for (const unit of this.nodes('unit')) {
|
|
561
|
-
const id = required(unit, 'id');
|
|
562
|
-
const entry = {
|
|
563
|
-
hp: integer(unit, 'hp', 1),
|
|
564
|
-
x: integer(unit, 'x', 0),
|
|
565
|
-
y: integer(unit, 'y', 0),
|
|
566
|
-
alive: true,
|
|
567
|
-
};
|
|
568
|
-
if (unit.attributes.type !== undefined) {
|
|
569
|
-
entry.type = unit.attributes.type;
|
|
570
|
-
const stats = this.unitTypes.get(unit.attributes.type);
|
|
571
|
-
if (stats)
|
|
572
|
-
entry.moves = stats.movement;
|
|
573
|
-
}
|
|
574
|
-
if (unit.attributes.side !== undefined)
|
|
575
|
-
entry.side = unit.attributes.side;
|
|
576
|
-
if (unit.attributes.name !== undefined)
|
|
577
|
-
entry.name = unit.attributes.name;
|
|
578
|
-
if (unit.attributes.role !== undefined)
|
|
579
|
-
entry.role = unit.attributes.role;
|
|
580
|
-
const can_recruit = booleanAttribute(unit, 'can_recruit');
|
|
581
|
-
if (can_recruit !== undefined)
|
|
582
|
-
entry.can_recruit = can_recruit;
|
|
583
|
-
this.world.units[id] = entry;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
loadLeaders() {
|
|
587
|
-
for (const side of this.nodes('side')) {
|
|
588
|
-
const leader = side.attributes.leader;
|
|
589
|
-
if (!leader)
|
|
590
|
-
continue;
|
|
591
|
-
const sideId = side.attributes.id;
|
|
592
|
-
if (!sideId)
|
|
593
|
-
continue;
|
|
594
|
-
const starts = this.world.map?.starts[sideId];
|
|
595
|
-
if (!starts?.length)
|
|
596
|
-
continue;
|
|
597
|
-
//a leader naming a declared [unit] is that unit, not a type to spawn a second one of
|
|
598
|
-
if (this.world.units[leader])
|
|
599
|
-
continue;
|
|
600
|
-
const stats = this.unitTypes.get(leader);
|
|
601
|
-
if (!stats)
|
|
602
|
-
throw new Error(`MWL side ${sideId} leader "${leader}" is neither a unit nor a unit type`);
|
|
603
|
-
for (const start of starts) {
|
|
604
|
-
if (this.unitAt(start.x, start.y))
|
|
605
|
-
continue;
|
|
606
|
-
const id = `${leader} ${sideId} (${start.x},${start.y})`;
|
|
607
|
-
this.world.units[id] = {
|
|
608
|
-
hp: stats.hitpoints,
|
|
609
|
-
x: start.x,
|
|
610
|
-
y: start.y,
|
|
611
|
-
alive: true,
|
|
612
|
-
type: leader,
|
|
613
|
-
side: sideId,
|
|
614
|
-
moves: stats.movement,
|
|
615
|
-
can_recruit: true,
|
|
616
|
-
leader: true,
|
|
617
|
-
};
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
unitAt(x, y) {
|
|
622
|
-
return Object.values(this.world.units).find((unit) => unit.alive && unit.x === x && unit.y === y);
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* One entry per MWL command tag, keyed exactly as `executeNode` used to switch on. Each
|
|
626
|
-
* handler is a small, independently-named method below rather than a case body, so a
|
|
627
|
-
* command's own logic is a search away instead of one branch inside a 200-line function -
|
|
628
|
-
* the decomposition this project's own review flagged `mwl/runtime.ts`'s size for for,
|
|
629
|
-
* done for the one function that was actually a single undifferentiated dispatch. State
|
|
630
|
-
* (`this.world` and the rest) still lives on the instance; only the dispatch itself moved.
|
|
631
|
-
*/
|
|
632
|
-
static { this.commandHandlers = {
|
|
633
|
-
message: (self, node) => self.showMessage(node.attributes),
|
|
634
|
-
spawn: (self, node) => self.cmdSpawn(node),
|
|
635
|
-
move: (self, node) => self.cmdMove(node),
|
|
636
|
-
kill: (self, node) => self.cmdKill(node),
|
|
637
|
-
fire_event: (self, node) => self.cmdFireEvent(node),
|
|
638
|
-
store_unit: (self, node) => self.cmdStoreUnit(node),
|
|
639
|
-
unstore_unit: (self, node) => self.cmdUnstoreUnit(node),
|
|
640
|
-
recall: (self, node) => self.cmdRecall(node),
|
|
641
|
-
modify_unit: (self, node) => self.cmdModifyUnit(node),
|
|
642
|
-
heal_unit: (self, node) => self.cmdHealUnit(node),
|
|
643
|
-
set_terrain: (self, node) => self.setTerrain(integer(node, 'x', 0), integer(node, 'y', 0), required(node, 'terrain')),
|
|
644
|
-
capture_village: (self, node) => self.cmdCaptureVillage(node),
|
|
645
|
-
clear_shroud: (self, node) => self.cmdClearShroud(node),
|
|
646
|
-
role: (self, node) => self.cmdRole(node),
|
|
647
|
-
attack: (self, node) => self.attack(node.attributes.defender ?? node.attributes.target ?? required(node, 'target'), integer(node, 'amount', 0)),
|
|
648
|
-
modify_gold: (self, node) => self.addGold(node.attributes.side ?? required(node, 'target'), integer(node, 'delta', integer(node, 'amount', 0))),
|
|
649
|
-
gold: (self, node) => self.addGold(required(node, 'side'), integer(node, 'delta', integer(node, 'amount', 0))),
|
|
650
|
-
set_variable: (self, node) => self.cmdSetVariable(node),
|
|
651
|
-
while: (self, node) => self.cmdWhile(node),
|
|
652
|
-
foreach: (self, node) => self.cmdForeach(node),
|
|
653
|
-
switch: (self, node) => self.cmdSwitch(node),
|
|
654
|
-
end_turn: (self) => self.endTurn(),
|
|
655
|
-
win: (self, node) => self.cmdWin(node),
|
|
656
|
-
lose: (self, node) => self.cmdLose(node),
|
|
657
|
-
endlevel: (self, node) => self.cmdEndlevel(node),
|
|
658
|
-
if: (self, node) => self.cmdIf(node),
|
|
659
|
-
//reachable at top level for a free-standing [else]; a paired one is run by its [if]
|
|
660
|
-
else: (self, node) => self.runBlock(self.commandChildren(node)),
|
|
661
|
-
hook: (self, node) => self.runHook(node),
|
|
662
|
-
}; }
|
|
663
|
-
executeNode(node) {
|
|
664
|
-
const name = node.tag === 'command' ? node.attributes.name : node.tag;
|
|
665
|
-
if (!name)
|
|
666
|
-
throw new Error('MWL command is missing name');
|
|
667
|
-
const handler = MwlRuntime.commandHandlers[name];
|
|
668
|
-
if (!handler)
|
|
669
|
-
throw new Error(`unknown MWL command: ${name}`);
|
|
670
|
-
handler(this, node);
|
|
671
|
-
}
|
|
672
|
-
cmdSpawn(node) {
|
|
673
|
-
this.spawnUnit(node.attributes.type ?? '', node.attributes.side, integer(node, 'x', 0), integer(node, 'y', 0), node.attributes.id ?? node.attributes.target, node.attributes.hp === undefined ? undefined : integer(node, 'hp', 1));
|
|
674
|
-
}
|
|
675
|
-
cmdMove(node) {
|
|
676
|
-
this.applyMove(node.attributes.unit ?? required(node, 'target'), integer(node, 'x', 0), integer(node, 'y', 0));
|
|
677
|
-
}
|
|
678
|
-
cmdKill(node) {
|
|
679
|
-
//a named unit that is not there is a content error; a filter that matches nobody is not,
|
|
680
|
-
//which is what WML's own `[kill]` does. An empty filter matches every unit, there as
|
|
681
|
-
//here, which is worth knowing before writing one.
|
|
682
|
-
const named = node.attributes.unit ?? node.attributes.target;
|
|
683
|
-
if (named === undefined)
|
|
684
|
-
killMatching(this.world, node.attributes);
|
|
685
|
-
else
|
|
686
|
-
this.killUnit(named);
|
|
687
|
-
}
|
|
688
|
-
cmdFireEvent(node) {
|
|
689
|
-
const id = node.attributes.id ?? node.attributes.name;
|
|
690
|
-
if (!id)
|
|
691
|
-
throw new Error('[fire_event] requires id');
|
|
692
|
-
this.fireEvent(id);
|
|
693
|
-
}
|
|
694
|
-
cmdStoreUnit(node) {
|
|
695
|
-
const variable = node.attributes.variable ?? node.attributes.name ?? required(node, 'variable');
|
|
696
|
-
this.setVariableAt(variable, this.matchingUnits(node, ['variable', 'name']).map(([id, unit]) => ({ id, ...unitSnapshot(unit) })));
|
|
697
|
-
}
|
|
698
|
-
cmdUnstoreUnit(node) {
|
|
699
|
-
const variable = required(node, 'variable');
|
|
700
|
-
for (const entry of this.storedUnits(variable))
|
|
701
|
-
this.restoreUnit(entry, {});
|
|
702
|
-
}
|
|
703
|
-
cmdRecall(node) {
|
|
704
|
-
const stored = this.storedUnits(required(node, 'variable'));
|
|
705
|
-
const wanted = node.attributes.id ?? node.attributes.unit;
|
|
706
|
-
const entry = wanted === undefined ? stored[0] : stored.find((candidate) => candidate.id === wanted);
|
|
707
|
-
if (!entry)
|
|
708
|
-
throw new Error(`[recall] found no stored unit${wanted === undefined ? '' : ` named ${wanted}`}`);
|
|
709
|
-
const placement = {};
|
|
710
|
-
if (node.attributes.x !== undefined)
|
|
711
|
-
placement.x = integer(node, 'x', 0);
|
|
712
|
-
if (node.attributes.y !== undefined)
|
|
713
|
-
placement.y = integer(node, 'y', 0);
|
|
714
|
-
if (node.attributes.side !== undefined)
|
|
715
|
-
placement.side = node.attributes.side;
|
|
716
|
-
this.restoreUnit(entry, placement);
|
|
717
|
-
}
|
|
718
|
-
cmdModifyUnit(node) {
|
|
719
|
-
//WML separates which units (`[filter]`) from what changes (`[set]`); a bare
|
|
720
|
-
//`[modify_unit] hp=5` with no `[set]` changes every unit it matches
|
|
721
|
-
const changes = node.children.find((child) => child.tag === 'set')?.attributes ?? node.attributes;
|
|
722
|
-
for (const [, unit] of this.matchingUnits(node))
|
|
723
|
-
applyUnitChanges(unit, changes);
|
|
724
|
-
}
|
|
725
|
-
cmdHealUnit(node) {
|
|
726
|
-
const amount = optionalInteger(node, 'amount');
|
|
727
|
-
const absolute = optionalInteger(node, 'hp');
|
|
728
|
-
if (amount === undefined && absolute === undefined)
|
|
729
|
-
throw new Error('[heal_unit] requires amount or hp');
|
|
730
|
-
for (const [, unit] of this.matchingUnits(node))
|
|
731
|
-
unit.hp = absolute ?? unit.hp + (amount ?? 0);
|
|
732
|
-
}
|
|
733
|
-
cmdCaptureVillage(node) {
|
|
734
|
-
const x = integer(node, 'x', 0);
|
|
735
|
-
const y = integer(node, 'y', 0);
|
|
736
|
-
const entry = { x, y, side: required(node, 'side') };
|
|
737
|
-
if (node.attributes.name !== undefined)
|
|
738
|
-
entry.name = node.attributes.name;
|
|
739
|
-
(this.world.villages ??= {})[`${x},${y}`] = entry;
|
|
740
|
-
}
|
|
741
|
-
cmdClearShroud(node) {
|
|
742
|
-
const side = required(node, 'side');
|
|
743
|
-
const x = integer(node, 'x', 0);
|
|
744
|
-
const y = integer(node, 'y', 0);
|
|
745
|
-
const radius = integer(node, 'radius', 1);
|
|
746
|
-
const cleared = new Set(this.world.clearedShroud?.[side] ?? []);
|
|
747
|
-
for (let dy = -radius; dy <= radius; dy++)
|
|
748
|
-
for (let dx = -radius; dx <= radius; dx++)
|
|
749
|
-
cleared.add(`${x + dx},${y + dy}`);
|
|
750
|
-
(this.world.clearedShroud ??= {})[side] = [...cleared];
|
|
751
|
-
}
|
|
752
|
-
cmdRole(node) {
|
|
753
|
-
const name = node.attributes.role ?? node.attributes.name;
|
|
754
|
-
if (!name)
|
|
755
|
-
throw new Error('[role] requires role');
|
|
756
|
-
//`role`/`name` here name the role being assigned, not a unit to match, so the filter
|
|
757
|
-
//must not read either back as one - the same exclusion the scenario-level role uses
|
|
758
|
-
const matched = this.matchingUnits(node, ['role', 'name']);
|
|
759
|
-
for (const [, unit] of matched)
|
|
760
|
-
unit.role = name;
|
|
761
|
-
(this.world.roles ??= {})[name] = matched.map(([id]) => id);
|
|
762
|
-
}
|
|
763
|
-
cmdSetVariable(node) {
|
|
764
|
-
// `name`/`target` is a path written out, `path` is one content builds from
|
|
765
|
-
// variables. Only the second goes through expansion: a `$` in `name` is not
|
|
766
|
-
// a reference today, and reading it as one would change what content means.
|
|
767
|
-
const computed = node.attributes.path;
|
|
768
|
-
this.setVariable(computed === undefined
|
|
769
|
-
? node.tag === 'command'
|
|
770
|
-
? required(node, 'target')
|
|
771
|
-
: required(node, 'name')
|
|
772
|
-
: this.expandPath(computed), node.attributes.value ?? '', node.attributes.mode);
|
|
773
|
-
}
|
|
774
|
-
cmdWhile(node) {
|
|
775
|
-
const limit = integer(node, 'max_iterations', 1000);
|
|
776
|
-
if (limit < 1 || limit > 100_000)
|
|
777
|
-
throw new Error('MWL while max_iterations must be between 1 and 100000');
|
|
778
|
-
let iteration = 0;
|
|
779
|
-
while (iteration < limit && this.nodeConditionMatches(node)) {
|
|
780
|
-
this.runBlock(this.commandChildren(node));
|
|
781
|
-
iteration++;
|
|
782
|
-
}
|
|
783
|
-
//the cap is observable: reaching it with the condition still true traces a
|
|
784
|
-
//while_limit, and on_limit=error turns that into a hard failure instead
|
|
785
|
-
if (iteration === limit && this.nodeConditionMatches(node)) {
|
|
786
|
-
if (node.attributes.on_limit === 'error')
|
|
787
|
-
throw new Error(`MWL while reached its max_iterations cap of ${limit}`);
|
|
788
|
-
this.onTrace?.({ type: 'while_limit', iterations: limit });
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
cmdForeach(node) {
|
|
792
|
-
const source = this.variableAt(required(node, 'variable'));
|
|
793
|
-
const entries = Array.isArray(source)
|
|
794
|
-
? source.map((value, index) => [String(index), value])
|
|
795
|
-
: typeof source === 'string'
|
|
796
|
-
? source
|
|
797
|
-
.split(',')
|
|
798
|
-
.map((value, index) => [String(index), value.trim()])
|
|
799
|
-
.filter(([, value]) => value !== '')
|
|
800
|
-
: source && typeof source === 'object'
|
|
801
|
-
? Object.entries(source)
|
|
802
|
-
: [];
|
|
803
|
-
const item = node.attributes.item ?? 'item';
|
|
804
|
-
const indexName = node.attributes.index ?? 'index';
|
|
805
|
-
for (let index = 0; index < entries.length; index++) {
|
|
806
|
-
this.setVariableAt(item, entries[index][1]);
|
|
807
|
-
this.setVariableAt(indexName, index);
|
|
808
|
-
this.runBlock(this.commandChildren(node));
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
cmdSwitch(node) {
|
|
812
|
-
const value = this.variableAt(required(node, 'variable'));
|
|
813
|
-
const selected = node.children.find((child) => child.tag === 'case' &&
|
|
814
|
-
child.attributes.equals !== undefined &&
|
|
815
|
-
sameValue(value, child.attributes.equals));
|
|
816
|
-
const fallback = node.children.find((child) => child.tag === 'default');
|
|
817
|
-
this.runBlock((selected ?? fallback)?.children ?? []);
|
|
818
|
-
}
|
|
819
|
-
cmdWin(node) {
|
|
820
|
-
this.markSideResult(node.attributes.side, 'won');
|
|
821
|
-
this.world.status = 'won';
|
|
822
|
-
}
|
|
823
|
-
cmdLose(node) {
|
|
824
|
-
this.markSideResult(node.attributes.side, 'lost');
|
|
825
|
-
this.world.status = 'lost';
|
|
826
|
-
}
|
|
827
|
-
cmdEndlevel(node) {
|
|
828
|
-
const result = node.attributes.result === 'defeat' ? 'defeat' : 'victory';
|
|
829
|
-
this.world.status = result === 'defeat' ? 'lost' : 'won';
|
|
830
|
-
this.world.carryover = endLevelCarryover(this.world, endLevelSide(this.world, node.attributes.side), {
|
|
831
|
-
result,
|
|
832
|
-
bonus: integerAttribute(node, 'bonus'),
|
|
833
|
-
carryoverPercentage: numberAttribute(node, 'carryover_percentage'),
|
|
834
|
-
carryoverAdd: booleanAttribute(node, 'carryover_add'),
|
|
835
|
-
nextScenario: node.attributes.next_scenario ?? null,
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
cmdIf(node) {
|
|
839
|
-
//an immediately following [else] is this branch's other half, not a separate
|
|
840
|
-
//command: the condition picks one body, and runBlock skips the [else] itself
|
|
841
|
-
const fallback = node.children.find((child) => child.tag === 'else');
|
|
842
|
-
const taken = this.nodeConditionMatches(node) ? node : fallback;
|
|
843
|
-
this.runBlock(taken ? this.commandChildren(taken) : []);
|
|
844
|
-
}
|
|
845
|
-
/**
|
|
846
|
-
* A node's children that are commands to run, dropping the condition children the schema
|
|
847
|
-
* allows a branch to carry. A `[condition]` is read by the branch itself, never executed:
|
|
848
|
-
* `[if]`/`[while]` evaluate one through `nodeConditionMatches`, where running it as a command
|
|
849
|
-
* would be an unknown tag.
|
|
850
|
-
*/
|
|
851
|
-
commandChildren(node) {
|
|
852
|
-
return node.children.filter((child) => child.tag !== 'condition' && child.tag !== 'filter' && child.tag !== 'filter_condition');
|
|
853
|
-
}
|
|
854
|
-
runHook(node) {
|
|
855
|
-
const reference = node.attributes.name ?? '';
|
|
856
|
-
const hook = this.hooks?.command?.[reference];
|
|
857
|
-
if (!hook)
|
|
858
|
-
throw new Error(`MWL hook ${reference} is not implemented`);
|
|
859
|
-
const { name: _name, ...context } = node.attributes;
|
|
860
|
-
hook(this.worldView(), this.emit(), context);
|
|
861
|
-
}
|
|
862
|
-
applyMove(id, x, y) {
|
|
863
|
-
const unit = this.world.units[id];
|
|
864
|
-
if (!unit || !unit.alive)
|
|
865
|
-
throw new Error(`MWL unit is not alive: ${id}`);
|
|
866
|
-
const map = this.world.map ?? null;
|
|
867
|
-
if (map) {
|
|
868
|
-
if (x < 0 || y < 0 || x >= map.width || y >= map.height)
|
|
869
|
-
throw new Error(`MWL move out of bounds: ${x},${y}`);
|
|
870
|
-
const occupant = this.unitAt(x, y);
|
|
871
|
-
if (occupant && occupant !== unit)
|
|
872
|
-
throw new Error(`MWL move onto an occupied cell: ${x},${y}`);
|
|
873
|
-
}
|
|
874
|
-
if (typeof unit.moves === 'number') {
|
|
875
|
-
if (unit.moves <= 0)
|
|
876
|
-
throw new Error(`MWL unit has no moves left: ${id}`);
|
|
877
|
-
unit.moves -= 1;
|
|
878
|
-
}
|
|
879
|
-
unit.x = x;
|
|
880
|
-
unit.y = y;
|
|
881
|
-
this.fireMoveto(id);
|
|
882
|
-
}
|
|
883
|
-
/** Deliver a `[message]` to the game, with speaker and portrait when given. */
|
|
884
|
-
showMessage(attributes) {
|
|
885
|
-
if (!this.onMessage)
|
|
886
|
-
return;
|
|
887
|
-
const message = {
|
|
888
|
-
text: this.interpolate(attributes.text ?? attributes.value ?? ''),
|
|
889
|
-
...(attributes.speaker === undefined ? {} : { speaker: attributes.speaker }),
|
|
890
|
-
...(attributes.portrait === undefined ? {} : { portrait: attributes.portrait }),
|
|
891
|
-
...(attributes.side === undefined || attributes.side === '' ? {} : { side: attributes.side }),
|
|
892
|
-
};
|
|
893
|
-
this.onMessage(message);
|
|
894
|
-
}
|
|
895
|
-
/**
|
|
896
|
-
* Substitute `$name` and `$(expression)` references in message text from
|
|
897
|
-
* the world variables (numbers evaluate, missing reads as empty), the
|
|
898
|
-
* same interpolation WML authors expect in story and dialogue strings.
|
|
899
|
-
*/
|
|
900
|
-
interpolate(text) {
|
|
901
|
-
const numeric = this.numericVariables();
|
|
902
|
-
const expanded = text.replace(expressionReference, (_whole, expression) => {
|
|
903
|
-
try {
|
|
904
|
-
return String(evaluateExpression(expression, numeric));
|
|
905
|
-
}
|
|
906
|
-
catch {
|
|
907
|
-
return '';
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
return expanded.replace(variableReference, (_whole, name) => {
|
|
911
|
-
const value = this.variableAt(name);
|
|
912
|
-
return value === undefined || typeof value === 'boolean' ? '' : String(value);
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
/**
|
|
916
|
-
* Expands the references a computed variable path is built from, so content can write
|
|
917
|
-
* `zombies[$index].allow_recruit` or `$target` (a variable holding a path) the way an author
|
|
918
|
-
* expects. Unlike a message, a reference here may not resolve to nothing: an empty segment
|
|
919
|
-
* would name a different variable than the one the content meant.
|
|
920
|
-
*/
|
|
921
|
-
expandPath(path) {
|
|
922
|
-
const expanded = path.replace(expressionReference, (_whole, expression) => String(evaluateExpression(expression, this.numericVariables())));
|
|
923
|
-
return expanded.replace(variableReference, (_whole, name) => {
|
|
924
|
-
const value = this.variableAt(name);
|
|
925
|
-
if (value === undefined)
|
|
926
|
-
throw new Error(`MWL variable path reference "$${name}" names no variable`);
|
|
927
|
-
if (typeof value === 'boolean' || typeof value === 'object')
|
|
928
|
-
throw new Error(`MWL variable path reference "$${name}" is not a name or number`);
|
|
929
|
-
return String(value);
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
setVariable(name, raw, mode) {
|
|
933
|
-
// `mode` is content declaring what its own text means. A compiler target always
|
|
934
|
-
// knows, so it never has to rely on the shape-guessing below: a literal containing
|
|
935
|
-
// `+` or `(` stays text, and a literal that spells a numeric variable's name stays
|
|
936
|
-
// text rather than reading that variable.
|
|
937
|
-
if (mode === 'literal') {
|
|
938
|
-
this.setVariableAt(name, raw);
|
|
939
|
-
return;
|
|
940
|
-
}
|
|
941
|
-
if (mode === 'number') {
|
|
942
|
-
const value = Number(raw);
|
|
943
|
-
if (raw.trim() === '' || !Number.isFinite(value))
|
|
944
|
-
throw new Error(`MWL set_variable mode="number" needs a number, got "${raw}"`);
|
|
945
|
-
this.setVariableAt(name, value);
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
if (mode === 'expression') {
|
|
949
|
-
this.setVariableAt(name, evaluateExpression(raw, this.numericVariables()));
|
|
950
|
-
return;
|
|
951
|
-
}
|
|
952
|
-
if (mode !== undefined)
|
|
953
|
-
throw new Error(`unknown MWL set_variable mode "${mode}"`);
|
|
954
|
-
const numeric = Number(raw);
|
|
955
|
-
if (raw.trim() !== '' && Number.isFinite(numeric)) {
|
|
956
|
-
this.setVariableAt(name, numeric);
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
// A bare `$name` copies another variable (missing reads as empty),
|
|
960
|
-
// so content can alias changing values without arithmetic.
|
|
961
|
-
const reference = /^\$([A-Za-z_][A-Za-z0-9_.]*)$/.exec(raw.trim());
|
|
962
|
-
if (reference) {
|
|
963
|
-
const value = this.variableAt(reference[1]);
|
|
964
|
-
this.setVariableAt(name, value === undefined ? '' : value);
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
|
-
const context = this.numericVariables();
|
|
968
|
-
if (/[+*/^()]|\s-\s/.test(raw) || Object.prototype.hasOwnProperty.call(context, raw.trim())) {
|
|
969
|
-
this.setVariableAt(name, evaluateExpression(raw, context));
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
this.setVariableAt(name, raw);
|
|
973
|
-
}
|
|
974
|
-
/** The numeric half of the world variables: the context every MWL expression evaluates in. */
|
|
975
|
-
numericVariables() {
|
|
976
|
-
return Object.fromEntries(Object.entries(this.world.variables).filter((entry) => typeof entry[1] === 'number'));
|
|
977
|
-
}
|
|
978
|
-
variableAt(path) {
|
|
979
|
-
return variableAtPath(this.world.variables, path);
|
|
980
|
-
}
|
|
981
|
-
setVariableAt(path, value) {
|
|
982
|
-
const previous = this.variableAt(path);
|
|
983
|
-
setVariableAtPath(this.world.variables, path, value);
|
|
984
|
-
this.trace({ type: 'variable', name: path, ...(previous === undefined ? {} : { previous }), value });
|
|
985
|
-
}
|
|
986
|
-
spawnUnit(type, side, x, y, id, hp) {
|
|
987
|
-
const stats = type ? this.unitTypes.get(type) : undefined;
|
|
988
|
-
const key = id ?? `${type || 'unit'}#${side ?? ''}@${x},${y}`;
|
|
989
|
-
this.world.units[key] = {
|
|
990
|
-
hp: hp ?? stats?.hitpoints ?? 1,
|
|
991
|
-
x,
|
|
992
|
-
y,
|
|
993
|
-
alive: true,
|
|
994
|
-
...(type ? { type } : {}),
|
|
995
|
-
...(side === undefined ? {} : { side }),
|
|
996
|
-
...(stats ? { moves: stats.movement } : {}),
|
|
997
|
-
};
|
|
998
|
-
}
|
|
999
|
-
killUnit(id) {
|
|
1000
|
-
const unit = this.world.units[id];
|
|
1001
|
-
if (!unit || !unit.alive)
|
|
1002
|
-
throw new Error(`MWL unit is not alive: ${id}`);
|
|
1003
|
-
unit.alive = false;
|
|
1004
|
-
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Live units a command's filter selects: its `[filter]` child when it has one, otherwise its
|
|
1007
|
-
* own attributes, read by the same `unitMatchesFilter` an event filter and `[kill]` use. An
|
|
1008
|
-
* empty filter matches every live unit, the rule `[kill]` already documents.
|
|
1009
|
-
*/
|
|
1010
|
-
matchingUnits(node, exclude = []) {
|
|
1011
|
-
const filter = node.children.find((child) => child.tag === 'filter');
|
|
1012
|
-
//a `[filter]` child is a real unit filter and keeps every attribute; the node's own
|
|
1013
|
-
//attributes are the fallback, minus whatever they mean to this command instead of a unit
|
|
1014
|
-
const attributes = filter ? filter.attributes : withoutAttributes(node.attributes, ...exclude);
|
|
1015
|
-
return Object.entries(this.world.units).filter(([id, unit]) => unit.alive && unitMatchesFilter(unit, id, attributes));
|
|
1016
|
-
}
|
|
1017
|
-
/** The unit snapshots `[store_unit]` wrote into a world variable, or a named content error. */
|
|
1018
|
-
storedUnits(variable) {
|
|
1019
|
-
const stored = this.variableAt(variable);
|
|
1020
|
-
if (!Array.isArray(stored))
|
|
1021
|
-
throw new Error(`MWL variable ${variable} is not a stored unit list; store one first`);
|
|
1022
|
-
return stored.filter((entry) => !!entry && typeof entry === 'object' && !Array.isArray(entry));
|
|
1023
|
-
}
|
|
1024
|
-
/** Writes a stored snapshot back into the world, applying any placement overrides. */
|
|
1025
|
-
restoreUnit(entry, placement) {
|
|
1026
|
-
const id = typeof entry.id === 'string' ? entry.id : undefined;
|
|
1027
|
-
if (!id)
|
|
1028
|
-
throw new Error('a stored unit snapshot is missing its id');
|
|
1029
|
-
const unit = {
|
|
1030
|
-
hp: typeof entry.hp === 'number' ? entry.hp : 1,
|
|
1031
|
-
x: placement.x ?? (typeof entry.x === 'number' ? entry.x : 0),
|
|
1032
|
-
y: placement.y ?? (typeof entry.y === 'number' ? entry.y : 0),
|
|
1033
|
-
alive: entry.alive !== false,
|
|
1034
|
-
};
|
|
1035
|
-
if (typeof entry.type === 'string')
|
|
1036
|
-
unit.type = entry.type;
|
|
1037
|
-
const side = placement.side ?? (typeof entry.side === 'string' ? entry.side : undefined);
|
|
1038
|
-
if (side !== undefined)
|
|
1039
|
-
unit.side = side;
|
|
1040
|
-
if (typeof entry.moves === 'number')
|
|
1041
|
-
unit.moves = entry.moves;
|
|
1042
|
-
if (typeof entry.name === 'string')
|
|
1043
|
-
unit.name = entry.name;
|
|
1044
|
-
if (typeof entry.role === 'string')
|
|
1045
|
-
unit.role = entry.role;
|
|
1046
|
-
if (typeof entry.can_recruit === 'boolean')
|
|
1047
|
-
unit.can_recruit = entry.can_recruit;
|
|
1048
|
-
if (typeof entry.leader === 'boolean')
|
|
1049
|
-
unit.leader = entry.leader;
|
|
1050
|
-
this.world.units[id] = unit;
|
|
1051
|
-
}
|
|
1052
|
-
/** Changes one cell of the primary map, keeping the parsed grid and its size in step. */
|
|
1053
|
-
setTerrain(x, y, terrain) {
|
|
1054
|
-
const map = this.world.map;
|
|
1055
|
-
if (!map)
|
|
1056
|
-
throw new Error('[set_terrain] needs a loaded map');
|
|
1057
|
-
if (x < 0 || y < 0 || x >= map.width || y >= map.height)
|
|
1058
|
-
throw new Error(`[set_terrain] is outside the map: ${x},${y}`);
|
|
1059
|
-
const codes = [...map.codes];
|
|
1060
|
-
codes[y * map.width + x] = terrain;
|
|
1061
|
-
this.world.map = { ...map, codes };
|
|
1062
|
-
}
|
|
1063
|
-
addGold(side, delta) {
|
|
1064
|
-
this.world.gold[side] = (this.world.gold[side] ?? 0) + delta;
|
|
1065
|
-
}
|
|
1066
|
-
endTurn() {
|
|
1067
|
-
this.world.turn += 1;
|
|
1068
|
-
this.advanceSchedule();
|
|
1069
|
-
this.resetMoves();
|
|
1070
|
-
this.run('turn');
|
|
1071
|
-
this.checkTimeOver();
|
|
1072
|
-
}
|
|
1073
|
-
/**
|
|
1074
|
-
* Wesnoth's "time over", as a framework native: once the scenario's `turn_limit` has passed,
|
|
1075
|
-
* `time_over` becomes a variable content can test and an event trigger it can answer. The
|
|
1076
|
-
* framework reports it rather than ending anything, because a turn limit is usually a defeat and
|
|
1077
|
-
* occasionally the whole point of the scenario ("hold out until then"), so what it means is
|
|
1078
|
-
* content's business - `[endlevel]` is right there for it. Fired once, and derived from the turn
|
|
1079
|
-
* counter rather than kept in step with it.
|
|
1080
|
-
*/
|
|
1081
|
-
checkTimeOver() {
|
|
1082
|
-
const limit = integerAttribute(this.game.roots[0], 'turn_limit');
|
|
1083
|
-
if (limit === undefined || this.world.turn <= limit || this.world.variables.time_over === 'yes')
|
|
1084
|
-
return;
|
|
1085
|
-
this.world.variables.time_over = 'yes';
|
|
1086
|
-
this.run('time_over');
|
|
1087
|
-
}
|
|
1088
|
-
advanceSchedule() {
|
|
1089
|
-
if (!this.schedule.length)
|
|
1090
|
-
return;
|
|
1091
|
-
const index = ((this.world.scheduleIndex ?? 0) + 1) % this.schedule.length;
|
|
1092
|
-
this.world.scheduleIndex = index;
|
|
1093
|
-
this.world.timeOfDay = this.schedule[index];
|
|
1094
|
-
}
|
|
1095
|
-
resetMoves() {
|
|
1096
|
-
for (const unit of Object.values(this.world.units)) {
|
|
1097
|
-
if (!unit.alive)
|
|
1098
|
-
continue;
|
|
1099
|
-
const stats = unit.type ? this.unitTypes.get(unit.type) : undefined;
|
|
1100
|
-
if (stats)
|
|
1101
|
-
unit.moves = stats.movement;
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
filterMatches(node) {
|
|
1105
|
-
return Object.entries(this.world.units).some(([id, unit]) => unit.alive && unitMatchesFilter(unit, id, node.attributes));
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
* Every `condition` child must match (conjunction). Each child names a
|
|
1109
|
-
* world variable and states one comparison: `equals` (the default, numeric
|
|
1110
|
-
* aware), `not_equals`, comma-list `in`/`not_in`, or the numeric
|
|
1111
|
-
* `less_than`/`greater_than`/`less_than_or_equal_to`/
|
|
1112
|
-
* `greater_than_or_equal_to` (false when either side is not a number).
|
|
1113
|
-
*/
|
|
1114
|
-
conditionMatches(node) {
|
|
1115
|
-
return node.children
|
|
1116
|
-
.filter((child) => child.tag === 'condition')
|
|
1117
|
-
.every((condition) => {
|
|
1118
|
-
if (condition.attributes.condition === 'hook') {
|
|
1119
|
-
const hookName = condition.attributes.hook;
|
|
1120
|
-
const predicateName = hookName?.startsWith('predicate:')
|
|
1121
|
-
? hookName.slice('predicate:'.length)
|
|
1122
|
-
: undefined;
|
|
1123
|
-
const predicate = predicateName ? this.hooks?.predicate?.[predicateName] : undefined;
|
|
1124
|
-
if (!predicate)
|
|
1125
|
-
throw new Error(`MWL predicate ${predicateName ?? '<missing>'} is not implemented`);
|
|
1126
|
-
const { condition: _condition, hook: _hook, ...context } = condition.attributes;
|
|
1127
|
-
return Boolean(predicate(this.worldView(), context));
|
|
1128
|
-
}
|
|
1129
|
-
return variableMatches(this.variableAt(condition.attributes.variable), condition.attributes, resolveVariable(this.world.variables));
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
nodeConditionMatches(node) {
|
|
1133
|
-
if (node.attributes.test !== undefined)
|
|
1134
|
-
return evaluateCondition(node.attributes.test, primitiveVariables(this.world.variables), {
|
|
1135
|
-
helpers: this.conditionHelpers(),
|
|
1136
|
-
});
|
|
1137
|
-
return this.conditionMatches(node);
|
|
1138
|
-
}
|
|
1139
|
-
/**
|
|
1140
|
-
* The helpers a `test=` expression may call (item 406): the built-in `have_unit` and
|
|
1141
|
-
* `have_location` queries over this world, plus one entry per registered predicate
|
|
1142
|
-
* hook, so a compound predicate no longer has to detour through `condition=hook` with
|
|
1143
|
-
* a `[condition]` tree. Each argument is one `key=value` pair (a bare argument names
|
|
1144
|
-
* `value`), matching the string-shaped context predicates already receive.
|
|
1145
|
-
*/
|
|
1146
|
-
conditionHelpers() {
|
|
1147
|
-
if (this.testHelpers)
|
|
1148
|
-
return this.testHelpers;
|
|
1149
|
-
const filterFromArgs = (args) => {
|
|
1150
|
-
const filter = {};
|
|
1151
|
-
for (const arg of args) {
|
|
1152
|
-
const text = String(arg);
|
|
1153
|
-
const split = text.indexOf('=');
|
|
1154
|
-
if (split <= 0)
|
|
1155
|
-
filter.value = text;
|
|
1156
|
-
else
|
|
1157
|
-
filter[text.slice(0, split)] = text.slice(split + 1);
|
|
1158
|
-
}
|
|
1159
|
-
return filter;
|
|
1160
|
-
};
|
|
1161
|
-
const helpers = {
|
|
1162
|
-
have_unit: (...args) => {
|
|
1163
|
-
const filter = filterFromArgs(args);
|
|
1164
|
-
return Object.entries(this.world.units).some(([id, unit]) => unit.alive &&
|
|
1165
|
-
(filter.id === undefined || id === filter.id) &&
|
|
1166
|
-
unitMatchesFilter(unit, id, filter));
|
|
1167
|
-
},
|
|
1168
|
-
have_location: (...args) => {
|
|
1169
|
-
const filter = filterFromArgs(args);
|
|
1170
|
-
const map = this.world.map;
|
|
1171
|
-
const x = Number(filter.x);
|
|
1172
|
-
const y = Number(filter.y);
|
|
1173
|
-
if (!map ||
|
|
1174
|
-
!Number.isInteger(x) ||
|
|
1175
|
-
!Number.isInteger(y) ||
|
|
1176
|
-
x < 0 ||
|
|
1177
|
-
y < 0 ||
|
|
1178
|
-
x >= map.width ||
|
|
1179
|
-
y >= map.height)
|
|
1180
|
-
return false;
|
|
1181
|
-
const code = map.codes[y * map.width + x];
|
|
1182
|
-
return filter.terrain === undefined || code === filter.terrain;
|
|
1183
|
-
},
|
|
1184
|
-
};
|
|
1185
|
-
for (const [name, predicate] of Object.entries(this.hooks?.predicate ?? {}))
|
|
1186
|
-
helpers[name] = (...args) => Boolean(predicate(this.worldView(), filterFromArgs(args)));
|
|
1187
|
-
this.testHelpers = helpers;
|
|
1188
|
-
return helpers;
|
|
1189
|
-
}
|
|
1190
|
-
/**
|
|
1191
|
-
* A `filter_condition` child holds `variable` comparisons (same operators
|
|
1192
|
-
* as `condition`) and `have_unit` existence checks (an alive unit matching
|
|
1193
|
-
* the given id/type/side/x/y, reusing the `filter` semantics). All must
|
|
1194
|
-
* hold for the event to fire.
|
|
1195
|
-
*/
|
|
1196
|
-
filterConditionMatches(node) {
|
|
1197
|
-
const wrapper = node.children.find((child) => child.tag === 'filter_condition');
|
|
1198
|
-
if (!wrapper)
|
|
1199
|
-
return true;
|
|
1200
|
-
return wrapper.children.every((child) => {
|
|
1201
|
-
if (child.tag === 'variable') {
|
|
1202
|
-
const name = child.attributes.name;
|
|
1203
|
-
if (name === undefined)
|
|
1204
|
-
return false;
|
|
1205
|
-
return variableMatches(this.variableAt(name), child.attributes, resolveVariable(this.world.variables));
|
|
1206
|
-
}
|
|
1207
|
-
if (child.tag === 'predicate') {
|
|
1208
|
-
const name = child.attributes.name;
|
|
1209
|
-
const predicate = name ? this.hooks?.predicate?.[name] : undefined;
|
|
1210
|
-
if (!predicate)
|
|
1211
|
-
throw new Error(`MWL predicate ${name ?? '<missing>'} is not implemented`);
|
|
1212
|
-
const { name: _name, ...context } = child.attributes;
|
|
1213
|
-
return Boolean(predicate(this.worldView(), context));
|
|
1214
|
-
}
|
|
1215
|
-
// `have_unit` names the world key with `id` where a `filter`
|
|
1216
|
-
// would say `unit`; everything else matches `filter` semantics.
|
|
1217
|
-
if (child.tag === 'have_unit')
|
|
1218
|
-
return Object.entries(this.world.units).some(([id, unit]) => unit.alive &&
|
|
1219
|
-
(child.attributes.id === undefined || id === child.attributes.id) &&
|
|
1220
|
-
unitMatchesFilter(unit, id, child.attributes));
|
|
1221
|
-
return true;
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
/**
|
|
1225
|
-
* Whether one objective's condition holds. `defaultSide` is the side whose own
|
|
1226
|
-
* `[victory]`/`[defeat]` node this is, so a condition that names no side (a side losing
|
|
1227
|
-
* when its own units are gone) reads as that side rather than as nobody.
|
|
1228
|
-
*/
|
|
1229
|
-
conditionMet(node, defaultSide) {
|
|
1230
|
-
const condition = node.attributes.condition ?? '';
|
|
1231
|
-
const side = node.attributes.side ?? defaultSide;
|
|
1232
|
-
switch (condition) {
|
|
1233
|
-
case 'units_dead': {
|
|
1234
|
-
const target = node.attributes.side_filter ?? side;
|
|
1235
|
-
if (target === undefined)
|
|
1236
|
-
return false;
|
|
1237
|
-
return !Object.values(this.world.units).some((unit) => unit.alive && unit.side === target);
|
|
1238
|
-
}
|
|
1239
|
-
case 'turns_elapsed': {
|
|
1240
|
-
const turns = optionalInteger(node, 'turns');
|
|
1241
|
-
return turns !== undefined && this.world.turn >= turns;
|
|
1242
|
-
}
|
|
1243
|
-
case 'gold_at_least': {
|
|
1244
|
-
const gold = optionalInteger(node, 'gold');
|
|
1245
|
-
const goldSide = node.attributes.side ?? defaultSide;
|
|
1246
|
-
return gold !== undefined && goldSide !== undefined && (this.world.gold[goldSide] ?? 0) >= gold;
|
|
1247
|
-
}
|
|
1248
|
-
case 'unit_at': {
|
|
1249
|
-
const x = optionalInteger(node, 'x');
|
|
1250
|
-
const y = optionalInteger(node, 'y');
|
|
1251
|
-
const targetSide = node.attributes.side_filter ?? side;
|
|
1252
|
-
return Object.values(this.world.units).some((unit) => unit.alive &&
|
|
1253
|
-
(targetSide === undefined || unit.side === targetSide) &&
|
|
1254
|
-
(node.attributes.type === undefined || unit.type === node.attributes.type) &&
|
|
1255
|
-
unit.x === x &&
|
|
1256
|
-
unit.y === y);
|
|
1257
|
-
}
|
|
1258
|
-
case 'hook': {
|
|
1259
|
-
const reference = node.attributes.hook ?? '';
|
|
1260
|
-
const hook = this.hooks?.predicate?.[reference];
|
|
1261
|
-
if (!hook)
|
|
1262
|
-
throw new Error(`MWL hook ${reference} is not implemented`);
|
|
1263
|
-
// The predicate receives the objective's other attributes as its
|
|
1264
|
-
// context, so content can parameterize an engine predicate.
|
|
1265
|
-
const { hook: _hook, condition: _condition, ...context } = node.attributes;
|
|
1266
|
-
return Boolean(hook(this.worldView(), context));
|
|
1267
|
-
}
|
|
1268
|
-
default:
|
|
1269
|
-
return false;
|
|
1270
|
-
}
|
|
1271
|
-
}
|
|
1272
|
-
/**
|
|
1273
|
-
* Evaluates the scenario-wide `[objectives]` conditions first, exactly as before, then each
|
|
1274
|
-
* side's own `[victory]`/`[defeat]` children. The scenario ends on the first side whose own
|
|
1275
|
-
* condition fires, recording that side in `world.sideStatus`; a side's victory outranks
|
|
1276
|
-
* another side's defeat when both fire in the same evaluation, which is the same precedence
|
|
1277
|
-
* the scenario-wide pair has always had. A side condition with no `side`/`side_filter` reads
|
|
1278
|
-
* as that side's own, so "this side loses when it has no units left" is written without
|
|
1279
|
-
* repeating the id.
|
|
1280
|
-
*/
|
|
1281
|
-
checkObjectives() {
|
|
1282
|
-
if (this.world.status !== 'playing')
|
|
1283
|
-
return;
|
|
1284
|
-
// a `[victory]`/`[defeat]` under a `[side]` is that side's own, never the scenario's
|
|
1285
|
-
const sideConditions = new Set();
|
|
1286
|
-
const sides = this.nodes('side');
|
|
1287
|
-
for (const side of sides) {
|
|
1288
|
-
for (const child of side.children) {
|
|
1289
|
-
if (child.tag === 'victory' || child.tag === 'defeat')
|
|
1290
|
-
sideConditions.add(child);
|
|
1291
|
-
}
|
|
1292
|
-
}
|
|
1293
|
-
if (this.nodes('victory').some((node) => !sideConditions.has(node) && this.conditionMet(node))) {
|
|
1294
|
-
this.world.status = 'won';
|
|
1295
|
-
return;
|
|
1296
|
-
}
|
|
1297
|
-
if (this.nodes('defeat').some((node) => !sideConditions.has(node) && this.conditionMet(node))) {
|
|
1298
|
-
this.world.status = 'lost';
|
|
1299
|
-
return;
|
|
1300
|
-
}
|
|
1301
|
-
let sideWon = false;
|
|
1302
|
-
let sideLost = false;
|
|
1303
|
-
for (const side of sides) {
|
|
1304
|
-
const id = side.attributes.id;
|
|
1305
|
-
if (!id || (this.world.sideStatus?.[id] ?? 'playing') !== 'playing')
|
|
1306
|
-
continue;
|
|
1307
|
-
if (side.children.some((child) => child.tag === 'victory' && this.conditionMet(child, id))) {
|
|
1308
|
-
this.markSideResult(id, 'won');
|
|
1309
|
-
sideWon = true;
|
|
1310
|
-
}
|
|
1311
|
-
else if (side.children.some((child) => child.tag === 'defeat' && this.conditionMet(child, id))) {
|
|
1312
|
-
this.markSideResult(id, 'lost');
|
|
1313
|
-
sideLost = true;
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
if (sideWon)
|
|
1317
|
-
this.world.status = 'won';
|
|
1318
|
-
else if (sideLost)
|
|
1319
|
-
this.world.status = 'lost';
|
|
1320
|
-
}
|
|
1321
|
-
/** Records one side's own result; the scenario status is set by whichever side fired first. */
|
|
1322
|
-
markSideResult(side, result) {
|
|
1323
|
-
if (side === undefined || side === '')
|
|
1324
|
-
return;
|
|
1325
|
-
(this.world.sideStatus ??= {})[side] = result;
|
|
1326
|
-
}
|
|
1327
|
-
worldView() {
|
|
1328
|
-
return {
|
|
1329
|
-
variables: this.world.variables,
|
|
1330
|
-
variableAt: (path) => this.variableAt(path),
|
|
1331
|
-
units: this.world.units,
|
|
1332
|
-
sides: this.world.sides,
|
|
1333
|
-
turn: this.world.turn,
|
|
1334
|
-
random: {
|
|
1335
|
-
float: () => this.drawRandom((random) => random.float()),
|
|
1336
|
-
int: (bound) => this.drawRandom((random) => random.int(bound)),
|
|
1337
|
-
},
|
|
1338
|
-
};
|
|
1339
|
-
}
|
|
1340
|
-
/** Draws from the hook-facing stream and immediately persists its new position onto
|
|
1341
|
-
* `world`, so a snapshot taken at any point after a draw resumes the same stream. */
|
|
1342
|
-
drawRandom(draw) {
|
|
1343
|
-
const value = draw(this.random);
|
|
1344
|
-
this.world.random = this.random.getState();
|
|
1345
|
-
return value;
|
|
1346
|
-
}
|
|
1347
|
-
emit() {
|
|
1348
|
-
return {
|
|
1349
|
-
move: (unit, x, y) => this.applyMove(unit, x, y),
|
|
1350
|
-
attack: (_attacker, _defender, _weapon) => {
|
|
1351
|
-
throw new Error('MWL hook attack is not available in the framework runtime; the engine adapter owns combat');
|
|
1352
|
-
},
|
|
1353
|
-
spawn: (type, side, x, y) => this.spawnUnit(type, side, x, y),
|
|
1354
|
-
kill: (unit) => this.killUnit(unit),
|
|
1355
|
-
gold: (side, delta) => this.addGold(side, delta),
|
|
1356
|
-
setVariable: (name, value) => {
|
|
1357
|
-
setVariableAtPath(this.world.variables, name, value);
|
|
1358
|
-
},
|
|
1359
|
-
message: (speaker, text) => this.onMessage?.({ text, ...(speaker ? { speaker } : {}) }),
|
|
1360
|
-
endTurn: () => this.endTurn(),
|
|
1361
|
-
win: (side) => {
|
|
1362
|
-
this.markSideResult(side, 'won');
|
|
1363
|
-
this.world.status = 'won';
|
|
1364
|
-
},
|
|
1365
|
-
lose: (side) => {
|
|
1366
|
-
this.markSideResult(side, 'lost');
|
|
1367
|
-
this.world.status = 'lost';
|
|
1368
|
-
},
|
|
1369
|
-
};
|
|
1370
|
-
}
|
|
1371
|
-
attack(target, amount) {
|
|
1372
|
-
const unit = this.world.units[target];
|
|
1373
|
-
if (!unit || !unit.alive)
|
|
1374
|
-
throw new Error(`MWL unit is not alive: ${target}`);
|
|
1375
|
-
unit.hp = Math.max(0, unit.hp - amount);
|
|
1376
|
-
if (unit.hp === 0)
|
|
1377
|
-
unit.alive = false;
|
|
1378
|
-
}
|
|
1379
|
-
nodes(tag) {
|
|
1380
|
-
const result = [];
|
|
1381
|
-
const visit = (node) => {
|
|
1382
|
-
if (node.tag === tag)
|
|
1383
|
-
result.push(node);
|
|
1384
|
-
node.children.forEach(visit);
|
|
1385
|
-
};
|
|
1386
|
-
this.game.roots.forEach(visit);
|
|
1387
|
-
return result;
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
/**
|
|
1391
|
-
* Applies one already-validated `MwlCommand` to a world, without a runtime around it.
|
|
1392
|
-
*
|
|
1393
|
-
* @example
|
|
1394
|
-
* ```ts
|
|
1395
|
-
* import { createWorld, execute } from '@datamoc/mw_games/mwl';
|
|
1396
|
-
*
|
|
1397
|
-
* const world = createWorld();
|
|
1398
|
-
* execute(world, { name: 'set_variable', target: 'gold', value: 50 });
|
|
1399
|
-
* console.log(world.variables.gold); // 50
|
|
1400
|
-
* ```
|
|
1401
|
-
*/
|
|
1402
|
-
export function execute(world, command) {
|
|
1403
|
-
if (world.status !== 'playing' && command.name !== 'win' && command.name !== 'lose')
|
|
1404
|
-
return;
|
|
1405
|
-
switch (command.name) {
|
|
1406
|
-
case 'set_variable':
|
|
1407
|
-
setVariableAtPath(world.variables, command.target, command.value);
|
|
1408
|
-
break;
|
|
1409
|
-
case 'modify_gold':
|
|
1410
|
-
world.gold[command.target] = (world.gold[command.target] ?? 0) + command.amount;
|
|
1411
|
-
break;
|
|
1412
|
-
case 'move': {
|
|
1413
|
-
const unit = requireUnit(world, command.target);
|
|
1414
|
-
unit.x = command.x;
|
|
1415
|
-
unit.y = command.y;
|
|
1416
|
-
break;
|
|
1417
|
-
}
|
|
1418
|
-
case 'spawn':
|
|
1419
|
-
world.units[command.target] = { hp: command.hp, x: command.x, y: command.y, alive: true };
|
|
1420
|
-
break;
|
|
1421
|
-
case 'kill':
|
|
1422
|
-
if (command.target !== undefined)
|
|
1423
|
-
requireUnit(world, command.target).alive = false;
|
|
1424
|
-
else
|
|
1425
|
-
killMatching(world, command.filter ?? {});
|
|
1426
|
-
break;
|
|
1427
|
-
case 'end_turn':
|
|
1428
|
-
world.turn++;
|
|
1429
|
-
break;
|
|
1430
|
-
case 'win':
|
|
1431
|
-
if (command.side !== undefined && command.side !== '')
|
|
1432
|
-
(world.sideStatus ??= {})[command.side] = 'won';
|
|
1433
|
-
world.status = 'won';
|
|
1434
|
-
break;
|
|
1435
|
-
case 'lose':
|
|
1436
|
-
if (command.side !== undefined && command.side !== '')
|
|
1437
|
-
(world.sideStatus ??= {})[command.side] = 'lost';
|
|
1438
|
-
world.status = 'lost';
|
|
1439
|
-
break;
|
|
1440
|
-
case 'endlevel':
|
|
1441
|
-
world.status = command.result === 'defeat' ? 'lost' : 'won';
|
|
1442
|
-
world.carryover = endLevelCarryover(world, command.side ?? null, command);
|
|
1443
|
-
break;
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
/**
|
|
1447
|
-
* Which side an `[endlevel]` carries: the one it names, or the human-controlled side when it names
|
|
1448
|
-
* none. `null` when there is no such side, which is not an error - a scenario can end with nobody
|
|
1449
|
-
* to carry.
|
|
1450
|
-
*/
|
|
1451
|
-
function endLevelSide(world, named) {
|
|
1452
|
-
const id = named ?? Object.entries(world.sides).find(([, side]) => side.controller === 'human')?.[0];
|
|
1453
|
-
if (!id || !(id in world.sides))
|
|
1454
|
-
return null;
|
|
1455
|
-
return { id };
|
|
1456
|
-
}
|
|
1457
|
-
/**
|
|
1458
|
-
* The sides a scenario's content says see together, as groups ready for `FactionFog.share`.
|
|
1459
|
-
*
|
|
1460
|
-
* Wesnoth groups sides into teams with `[side] team_name`, and `share_vision` says whether a side
|
|
1461
|
-
* shares what it sees with its team. `none` does not; `all` and `shroud` are treated alike here
|
|
1462
|
-
* because `FactionFog` shares sight and memory as one thing rather than keeping them apart, and a
|
|
1463
|
-
* fog that separated them would be the place to tell the two apart. A side with no `team_name`
|
|
1464
|
-
* shares with nobody, and a team of one is not returned, since sharing with nobody is what it
|
|
1465
|
-
* already does.
|
|
1466
|
-
*
|
|
1467
|
-
* @example
|
|
1468
|
-
* ```ts
|
|
1469
|
-
* import { sideVisionGroups, type MwlWorld } from '@datamoc/mw_games/mwl';
|
|
1470
|
-
*
|
|
1471
|
-
* declare const world: MwlWorld;
|
|
1472
|
-
*
|
|
1473
|
-
* // sides 1 and 2 both wrote team_name=north, and side 3 asked for share_vision=none
|
|
1474
|
-
* console.log(sideVisionGroups(world)); // [['1', '2']]
|
|
1475
|
-
* ```
|
|
1476
|
-
*/
|
|
1477
|
-
export function sideVisionGroups(world) {
|
|
1478
|
-
const teams = new Map();
|
|
1479
|
-
for (const [id, side] of Object.entries(world.sides)) {
|
|
1480
|
-
if (!side.teamName || side.shareVision === 'none')
|
|
1481
|
-
continue;
|
|
1482
|
-
const group = teams.get(side.teamName);
|
|
1483
|
-
if (group)
|
|
1484
|
-
group.push(id);
|
|
1485
|
-
else
|
|
1486
|
-
teams.set(side.teamName, [id]);
|
|
1487
|
-
}
|
|
1488
|
-
return [...teams.values()].filter((group) => group.length > 1);
|
|
1489
|
-
}
|
|
1490
|
-
function requireUnit(world, id) {
|
|
1491
|
-
const unit = world.units[id];
|
|
1492
|
-
if (!unit || !unit.alive)
|
|
1493
|
-
throw new Error(`MWL unit is not alive: ${id}`);
|
|
1494
|
-
return unit;
|
|
1495
|
-
}
|
|
1496
|
-
/** Kills every alive unit a `[kill]` filter matches, and says how many it killed. */
|
|
1497
|
-
function killMatching(world, attributes) {
|
|
1498
|
-
let killed = 0;
|
|
1499
|
-
for (const [id, unit] of Object.entries(world.units)) {
|
|
1500
|
-
if (!unit.alive || !unitMatchesFilter(unit, id, attributes))
|
|
1501
|
-
continue;
|
|
1502
|
-
unit.alive = false;
|
|
1503
|
-
killed++;
|
|
1504
|
-
}
|
|
1505
|
-
return killed;
|
|
1506
|
-
}
|
|
1507
|
-
/** One unit as `[store_unit]` writes it: only the fields it has, so a variable stays small. */
|
|
1508
|
-
function unitSnapshot(unit) {
|
|
1509
|
-
const snapshot = { hp: unit.hp, x: unit.x, y: unit.y, alive: unit.alive };
|
|
1510
|
-
if (unit.type !== undefined)
|
|
1511
|
-
snapshot.type = unit.type;
|
|
1512
|
-
if (unit.side !== undefined)
|
|
1513
|
-
snapshot.side = unit.side;
|
|
1514
|
-
if (unit.moves !== undefined)
|
|
1515
|
-
snapshot.moves = unit.moves;
|
|
1516
|
-
if (unit.name !== undefined)
|
|
1517
|
-
snapshot.name = unit.name;
|
|
1518
|
-
if (unit.role !== undefined)
|
|
1519
|
-
snapshot.role = unit.role;
|
|
1520
|
-
if (unit.can_recruit !== undefined)
|
|
1521
|
-
snapshot.can_recruit = unit.can_recruit;
|
|
1522
|
-
if (unit.leader !== undefined)
|
|
1523
|
-
snapshot.leader = unit.leader;
|
|
1524
|
-
return snapshot;
|
|
1525
|
-
}
|
|
1526
|
-
/** Applies `[modify_unit]`'s chosen attributes to one unit, ignoring anything it did not name. */
|
|
1527
|
-
function applyUnitChanges(unit, changes) {
|
|
1528
|
-
const hp = finiteNumber(changes.hp);
|
|
1529
|
-
if (hp !== undefined)
|
|
1530
|
-
unit.hp = hp;
|
|
1531
|
-
const moves = finiteNumber(changes.moves);
|
|
1532
|
-
if (moves !== undefined)
|
|
1533
|
-
unit.moves = moves;
|
|
1534
|
-
if (changes.type !== undefined)
|
|
1535
|
-
unit.type = changes.type;
|
|
1536
|
-
if (changes.side !== undefined)
|
|
1537
|
-
unit.side = changes.side;
|
|
1538
|
-
const alive = booleanValue(changes.alive);
|
|
1539
|
-
if (alive !== undefined)
|
|
1540
|
-
unit.alive = alive;
|
|
1541
|
-
if (changes.name !== undefined)
|
|
1542
|
-
unit.name = changes.name;
|
|
1543
|
-
if (changes.role !== undefined)
|
|
1544
|
-
unit.role = changes.role;
|
|
1545
|
-
const canRecruit = booleanValue(changes.can_recruit);
|
|
1546
|
-
if (canRecruit !== undefined)
|
|
1547
|
-
unit.can_recruit = canRecruit;
|
|
1548
|
-
}
|
|
1549
|
-
function finiteNumber(value) {
|
|
1550
|
-
if (value === undefined || value === '')
|
|
1551
|
-
return undefined;
|
|
1552
|
-
const parsed = Number(value);
|
|
1553
|
-
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1554
|
-
}
|
|
1555
|
-
function optionalInteger(node, attribute) {
|
|
1556
|
-
const value = node.attributes[attribute];
|
|
1557
|
-
if (value === undefined || value === '')
|
|
1558
|
-
return undefined;
|
|
1559
|
-
const parsed = Number.parseInt(value, 10);
|
|
1560
|
-
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1561
|
-
}
|
|
1562
|
-
/**
|
|
1563
|
-
* One variable comparison for `condition`/`variable` nodes. `equals` keeps
|
|
1564
|
-
* the historical numeric-aware match; the rest are strict about shape:
|
|
1565
|
-
* lists split on commas, comparisons coerce both sides with `Number` and
|
|
1566
|
-
* fail on anything non-numeric.
|
|
1567
|
-
*/
|
|
1568
|
-
function variableMatches(value, attributes, resolve) {
|
|
1569
|
-
const expected = (text) => {
|
|
1570
|
-
if (!text.startsWith('$'))
|
|
1571
|
-
return text;
|
|
1572
|
-
const resolved = resolve(text.slice(1));
|
|
1573
|
-
return typeof resolved === 'string' || typeof resolved === 'number' || typeof resolved === 'boolean'
|
|
1574
|
-
? resolved
|
|
1575
|
-
: undefined;
|
|
1576
|
-
};
|
|
1577
|
-
if (attributes.equals !== undefined)
|
|
1578
|
-
return sameValue(value, expected(attributes.equals));
|
|
1579
|
-
if (attributes.not_equals !== undefined)
|
|
1580
|
-
return !sameValue(value, expected(attributes.not_equals));
|
|
1581
|
-
if (attributes.in !== undefined) {
|
|
1582
|
-
const options = attributes.in.split(',').map((entry) => entry.trim());
|
|
1583
|
-
return options.some((option) => sameValue(value, option));
|
|
1584
|
-
}
|
|
1585
|
-
if (attributes.not_in !== undefined) {
|
|
1586
|
-
const options = attributes.not_in.split(',').map((entry) => entry.trim());
|
|
1587
|
-
return !options.some((option) => sameValue(value, option));
|
|
1588
|
-
}
|
|
1589
|
-
const actual = typeof value === 'number' ? value : Number(value);
|
|
1590
|
-
const wanted = (name) => Number(attributes[name]);
|
|
1591
|
-
if (attributes.less_than !== undefined ||
|
|
1592
|
-
attributes.greater_than !== undefined ||
|
|
1593
|
-
attributes.less_than_or_equal_to !== undefined ||
|
|
1594
|
-
attributes.greater_than_or_equal_to !== undefined) {
|
|
1595
|
-
if (typeof value === 'boolean' || !Number.isFinite(actual))
|
|
1596
|
-
return false;
|
|
1597
|
-
if (attributes.less_than !== undefined && !(actual < wanted('less_than')))
|
|
1598
|
-
return false;
|
|
1599
|
-
if (attributes.greater_than !== undefined && !(actual > wanted('greater_than')))
|
|
1600
|
-
return false;
|
|
1601
|
-
if (attributes.less_than_or_equal_to !== undefined && !(actual <= wanted('less_than_or_equal_to')))
|
|
1602
|
-
return false;
|
|
1603
|
-
if (attributes.greater_than_or_equal_to !== undefined && !(actual >= wanted('greater_than_or_equal_to')))
|
|
1604
|
-
return false;
|
|
1605
|
-
return true;
|
|
1606
|
-
}
|
|
1607
|
-
return value !== undefined;
|
|
1608
|
-
}
|
|
1609
|
-
/**
|
|
1610
|
-
* One alive unit against `filter`/`have_unit` attributes: side, type (with
|
|
1611
|
-
* comma-list `not_type` exclusion), the unit's own name and role, whether it
|
|
1612
|
-
* can recruit, whether it is its side's leader, world key (`unit`, or `id`
|
|
1613
|
-
* on `have_unit`), and coordinates all have to match when present.
|
|
1614
|
-
*/
|
|
1615
|
-
function unitMatchesFilter(unit, id, attributes) {
|
|
1616
|
-
const excluded = (attributes.not_type ?? '')
|
|
1617
|
-
.split(',')
|
|
1618
|
-
.map((entry) => entry.trim())
|
|
1619
|
-
.filter(Boolean);
|
|
1620
|
-
const wantedCanRecruit = booleanValue(attributes.can_recruit);
|
|
1621
|
-
const wantedLeader = booleanValue(attributes.leader);
|
|
1622
|
-
const key = attributes.unit ?? attributes.id;
|
|
1623
|
-
return ((key === undefined || id === key) &&
|
|
1624
|
-
(attributes.side === undefined || unit.side === attributes.side) &&
|
|
1625
|
-
(attributes.type === undefined || unit.type === attributes.type) &&
|
|
1626
|
-
(excluded.length === 0 || !excluded.includes(unit.type ?? '')) &&
|
|
1627
|
-
(attributes.name === undefined || unit.name === attributes.name) &&
|
|
1628
|
-
(attributes.role === undefined || unit.role === attributes.role) &&
|
|
1629
|
-
(wantedCanRecruit === undefined || (unit.can_recruit ?? false) === wantedCanRecruit) &&
|
|
1630
|
-
(wantedLeader === undefined || (unit.leader ?? false) === wantedLeader) &&
|
|
1631
|
-
(attributes.x === undefined || coordinateMatches(attributes.x, unit.x)) &&
|
|
1632
|
-
(attributes.y === undefined || coordinateMatches(attributes.y, unit.y)));
|
|
1633
|
-
}
|
|
1634
|
-
/** a copy of `attributes` without the given keys, for a command whose own attribute names are not a unit filter */
|
|
1635
|
-
function withoutAttributes(attributes, ...excluded) {
|
|
1636
|
-
if (excluded.length === 0)
|
|
1637
|
-
return { ...attributes };
|
|
1638
|
-
const copy = { ...attributes };
|
|
1639
|
-
for (const key of excluded)
|
|
1640
|
-
delete copy[key];
|
|
1641
|
-
return copy;
|
|
1642
|
-
}
|
|
1643
|
-
function sameValue(value, expected) {
|
|
1644
|
-
if (value === undefined || expected === undefined)
|
|
1645
|
-
return value === expected;
|
|
1646
|
-
if (typeof expected !== 'string')
|
|
1647
|
-
return value === expected;
|
|
1648
|
-
const numeric = Number(expected);
|
|
1649
|
-
return typeof value === 'number' && expected.trim() !== '' && Number.isFinite(numeric)
|
|
1650
|
-
? value === numeric
|
|
1651
|
-
: value === expected;
|
|
1652
|
-
}
|
|
1653
|
-
function primitiveVariables(variables) {
|
|
1654
|
-
return Object.fromEntries(Object.entries(variables).filter((entry) => typeof entry[1] === 'string' || typeof entry[1] === 'number' || typeof entry[1] === 'boolean'));
|
|
1655
|
-
}
|
|
1656
|
-
/** `a.b[0].c` -> `['a', 'b', { index: 0 }, 'c']`. */
|
|
1657
|
-
function variablePathParts(path) {
|
|
1658
|
-
return path
|
|
1659
|
-
.split('.')
|
|
1660
|
-
.flatMap((segment) => {
|
|
1661
|
-
const name = /^([^[\]]*)((?:\[[^\]]*\])*)$/.exec(segment);
|
|
1662
|
-
if (!name)
|
|
1663
|
-
return [segment];
|
|
1664
|
-
const parts = name[1] === '' ? [] : [name[1]];
|
|
1665
|
-
for (const bracket of name[2].matchAll(/\[([^\]]*)\]/g)) {
|
|
1666
|
-
const index = Number(bracket[1]);
|
|
1667
|
-
parts.push({ index: /^\d+$/.test(bracket[1].trim()) ? index : undefined });
|
|
1668
|
-
}
|
|
1669
|
-
return parts;
|
|
1670
|
-
})
|
|
1671
|
-
.filter((part) => typeof part !== 'string' || part !== '');
|
|
1672
|
-
}
|
|
1673
|
-
/** The path parts of a write, with any bracketed index that is not a whole number refused by name. */
|
|
1674
|
-
function validVariablePathParts(path) {
|
|
1675
|
-
const parts = variablePathParts(path);
|
|
1676
|
-
if (parts.some((part) => typeof part !== 'string' && part.index === undefined))
|
|
1677
|
-
throw new Error(`invalid variable path: ${path}`);
|
|
1678
|
-
return parts;
|
|
1679
|
-
}
|
|
1680
|
-
function isIndexedStep(step) {
|
|
1681
|
-
return typeof step !== 'string';
|
|
1682
|
-
}
|
|
1683
|
-
/**
|
|
1684
|
-
* The one write of a variable path, so `execute()`, the hook host and the runtime's own
|
|
1685
|
-
* `set_variable` all place a value at the same node a read walks to. A step after an index
|
|
1686
|
-
* grows an array, so `a[0]`/`a[1]` build a real list rather than an object with numbered keys.
|
|
1687
|
-
*/
|
|
1688
|
-
function setVariableAtPath(variables, path, value) {
|
|
1689
|
-
const parts = validVariablePathParts(path);
|
|
1690
|
-
const key = (step) => (typeof step === 'string' ? step : step.index);
|
|
1691
|
-
let current = variables;
|
|
1692
|
-
for (let index = 0; index < parts.length - 1; index++) {
|
|
1693
|
-
const step = key(parts[index]);
|
|
1694
|
-
const child = current[step];
|
|
1695
|
-
if (!child || typeof child !== 'object') {
|
|
1696
|
-
current[step] = isIndexedStep(parts[index + 1]) ? [] : {};
|
|
1697
|
-
}
|
|
1698
|
-
current = current[step];
|
|
1699
|
-
}
|
|
1700
|
-
current[key(parts[parts.length - 1])] = value;
|
|
1701
|
-
}
|
|
1702
|
-
/** The one read of a variable path, used by every reader that takes a name. */
|
|
1703
|
-
function variableAtPath(variables, path) {
|
|
1704
|
-
let value = variables;
|
|
1705
|
-
for (const part of variablePathParts(path)) {
|
|
1706
|
-
if (typeof part === 'string') {
|
|
1707
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1708
|
-
return undefined;
|
|
1709
|
-
value = value[part];
|
|
1710
|
-
}
|
|
1711
|
-
else {
|
|
1712
|
-
if (!Array.isArray(value) || part.index === undefined)
|
|
1713
|
-
return undefined;
|
|
1714
|
-
value = value[part.index];
|
|
1715
|
-
}
|
|
1716
|
-
}
|
|
1717
|
-
return value;
|
|
1718
|
-
}
|
|
1719
|
-
/** Resolves a `$name` reference (a path, not only a top-level key) from a variable tree. */
|
|
1720
|
-
function resolveVariable(variables) {
|
|
1721
|
-
return (reference) => variableAtPath(variables, reference);
|
|
1722
|
-
}
|
|
1723
|
-
/**
|
|
1724
|
-
* Whether a coordinate satisfies a filter value: a whole number, an `A-B` range, or a
|
|
1725
|
-
* comma-separated list of either (`x=10-99,13-99`). Wesnoth spells both a moveto event's
|
|
1726
|
-
* position and a unit filter's `x`/`y` this way, so a plain `Number()` comparison would
|
|
1727
|
-
* drop every event or filter a real scenario gates on a coordinate range.
|
|
1728
|
-
*/
|
|
1729
|
-
function coordinateMatches(specification, coordinate) {
|
|
1730
|
-
return specification.split(',').some((part) => {
|
|
1731
|
-
const value = part.trim();
|
|
1732
|
-
const range = value.match(/^(-?\d+)\s*-\s*(-?\d+)$/);
|
|
1733
|
-
if (range) {
|
|
1734
|
-
const from = Number(range[1]);
|
|
1735
|
-
const to = Number(range[2]);
|
|
1736
|
-
return coordinate >= Math.min(from, to) && coordinate <= Math.max(from, to);
|
|
1737
|
-
}
|
|
1738
|
-
return /^-?\d+$/.test(value) && Number(value) === coordinate;
|
|
1739
|
-
});
|
|
1740
|
-
}
|
|
1741
|
-
//# sourceMappingURL=runtime.js.map
|