@datamoc/mw_games 0.7.6 → 0.7.8
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/CHANGELOG.md +359 -0
- package/README.md +7 -7
- package/dist/actors/Inventory.d.ts +7 -1
- package/dist/actors/Inventory.d.ts.map +1 -1
- package/dist/actors/Inventory.js.map +1 -1
- package/dist/actors/Shop.d.ts.map +1 -1
- package/dist/actors/Shop.js +4 -1
- package/dist/actors/Shop.js.map +1 -1
- package/dist/actors/craft.d.ts +35 -14
- package/dist/actors/craft.d.ts.map +1 -1
- package/dist/actors/craft.js +56 -24
- package/dist/actors/craft.js.map +1 -1
- package/dist/actors/index.d.ts +1 -1
- package/dist/actors/index.d.ts.map +1 -1
- package/dist/ai/Heuristics.d.ts +240 -0
- package/dist/ai/Heuristics.d.ts.map +1 -0
- package/dist/ai/Heuristics.js +298 -0
- package/dist/ai/Heuristics.js.map +1 -0
- package/dist/ai/index.d.ts +4 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +2 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/lua.d.ts +21 -0
- package/dist/ai/lua.d.ts.map +1 -1
- package/dist/ai/lua.js +21 -0
- package/dist/ai/lua.js.map +1 -1
- package/dist/ai/score.d.ts +162 -0
- package/dist/ai/score.d.ts.map +1 -0
- package/dist/ai/score.js +147 -0
- package/dist/ai/score.js.map +1 -0
- package/dist/assets/loader.d.ts +18 -4
- package/dist/assets/loader.d.ts.map +1 -1
- package/dist/assets/loader.js +40 -11
- package/dist/assets/loader.js.map +1 -1
- package/dist/audio/Positional.d.ts +125 -0
- package/dist/audio/Positional.d.ts.map +1 -0
- package/dist/audio/Positional.js +135 -0
- package/dist/audio/Positional.js.map +1 -0
- package/dist/audio/Sound.d.ts +7 -1
- package/dist/audio/Sound.d.ts.map +1 -1
- package/dist/audio/Sound.js +8 -2
- package/dist/audio/Sound.js.map +1 -1
- package/dist/audio/index.d.ts +2 -0
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +1 -0
- package/dist/audio/index.js.map +1 -1
- package/dist/battle/AttackDialog.d.ts +75 -0
- package/dist/battle/AttackDialog.d.ts.map +1 -0
- package/dist/battle/AttackDialog.js +115 -0
- package/dist/battle/AttackDialog.js.map +1 -0
- package/dist/battle/AttackPreview.d.ts +70 -0
- package/dist/battle/AttackPreview.d.ts.map +1 -0
- package/dist/battle/AttackPreview.js +78 -0
- package/dist/battle/AttackPreview.js.map +1 -0
- package/dist/battle/BattleStats.d.ts +45 -0
- package/dist/battle/BattleStats.d.ts.map +1 -0
- package/dist/battle/BattleStats.js +63 -0
- package/dist/battle/BattleStats.js.map +1 -0
- package/dist/battle/UnitSelector.d.ts +72 -0
- package/dist/battle/UnitSelector.d.ts.map +1 -0
- package/dist/battle/UnitSelector.js +117 -0
- package/dist/battle/UnitSelector.js.map +1 -0
- package/dist/battle/Whiteboard.d.ts +50 -0
- package/dist/battle/Whiteboard.d.ts.map +1 -0
- package/dist/battle/Whiteboard.js +94 -0
- package/dist/battle/Whiteboard.js.map +1 -0
- package/dist/battle/index.d.ts +10 -0
- package/dist/battle/index.d.ts.map +1 -1
- package/dist/battle/index.js +5 -0
- package/dist/battle/index.js.map +1 -1
- package/dist/board/Classics.d.ts.map +1 -1
- package/dist/board/Classics.js +51 -39
- package/dist/board/Classics.js.map +1 -1
- package/dist/board/FogOfWar.d.ts +32 -2
- package/dist/board/FogOfWar.d.ts.map +1 -1
- package/dist/board/FogOfWar.js +70 -6
- package/dist/board/FogOfWar.js.map +1 -1
- package/dist/board/HexSkirmish.d.ts.map +1 -1
- package/dist/board/HexSkirmish.js +69 -20
- package/dist/board/HexSkirmish.js.map +1 -1
- package/dist/board/Tactics.d.ts +7 -0
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +2 -2
- package/dist/board/Tactics.js.map +1 -1
- package/dist/core/Achievements.d.ts +40 -7
- package/dist/core/Achievements.d.ts.map +1 -1
- package/dist/core/Achievements.js +53 -7
- package/dist/core/Achievements.js.map +1 -1
- package/dist/core/Hex.d.ts +26 -6
- package/dist/core/Hex.d.ts.map +1 -1
- package/dist/core/Hex.js +40 -13
- package/dist/core/Hex.js.map +1 -1
- package/dist/core/Input.d.ts +36 -0
- package/dist/core/Input.d.ts.map +1 -1
- package/dist/core/Input.js +63 -1
- package/dist/core/Input.js.map +1 -1
- package/dist/core/Random.d.ts +93 -0
- package/dist/core/Random.d.ts.map +1 -1
- package/dist/core/Random.js +177 -0
- package/dist/core/Random.js.map +1 -1
- package/dist/core/SyncGuard.d.ts +57 -0
- package/dist/core/SyncGuard.d.ts.map +1 -0
- package/dist/core/SyncGuard.js +116 -0
- package/dist/core/SyncGuard.js.map +1 -0
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/i18n/Po.d.ts +51 -0
- package/dist/i18n/Po.d.ts.map +1 -0
- package/dist/i18n/Po.js +176 -0
- package/dist/i18n/Po.js.map +1 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/index.js.map +1 -1
- package/dist/mw_games.global.js +104 -98
- package/dist/mwl/MapFile.d.ts +41 -0
- package/dist/mwl/MapFile.d.ts.map +1 -0
- package/dist/mwl/MapFile.js +43 -0
- package/dist/mwl/MapFile.js.map +1 -0
- package/dist/mwl/actors.d.ts +46 -2
- package/dist/mwl/actors.d.ts.map +1 -1
- package/dist/mwl/actors.js +46 -2
- package/dist/mwl/actors.js.map +1 -1
- package/dist/mwl/campaign.d.ts +51 -0
- package/dist/mwl/campaign.d.ts.map +1 -0
- package/dist/mwl/campaign.js +58 -0
- package/dist/mwl/campaign.js.map +1 -0
- package/dist/mwl/carryover.d.ts +86 -0
- package/dist/mwl/carryover.d.ts.map +1 -0
- package/dist/mwl/carryover.js +70 -0
- package/dist/mwl/carryover.js.map +1 -0
- package/dist/mwl/catalog.d.ts +10 -1
- package/dist/mwl/catalog.d.ts.map +1 -1
- package/dist/mwl/catalog.js +10 -1
- package/dist/mwl/catalog.js.map +1 -1
- package/dist/mwl/compiler.d.ts +70 -3
- package/dist/mwl/compiler.d.ts.map +1 -1
- package/dist/mwl/compiler.js +70 -3
- package/dist/mwl/compiler.js.map +1 -1
- package/dist/mwl/conditions.d.ts +10 -1
- package/dist/mwl/conditions.d.ts.map +1 -1
- package/dist/mwl/conditions.js +10 -1
- package/dist/mwl/conditions.js.map +1 -1
- package/dist/mwl/content.d.ts +21 -0
- package/dist/mwl/content.d.ts.map +1 -1
- package/dist/mwl/content.js +19 -0
- package/dist/mwl/content.js.map +1 -1
- package/dist/mwl/expression.d.ts +21 -0
- package/dist/mwl/expression.d.ts.map +1 -1
- package/dist/mwl/expression.js +21 -0
- package/dist/mwl/expression.js.map +1 -1
- package/dist/mwl/fengari.d.ts +12 -1
- package/dist/mwl/fengari.d.ts.map +1 -1
- package/dist/mwl/fengari.js +12 -1
- package/dist/mwl/fengari.js.map +1 -1
- package/dist/mwl/grammar.d.ts +45 -1
- package/dist/mwl/grammar.d.ts.map +1 -1
- package/dist/mwl/grammar.js +45 -1
- package/dist/mwl/grammar.js.map +1 -1
- package/dist/mwl/hooks.d.ts +51 -6
- package/dist/mwl/hooks.d.ts.map +1 -1
- package/dist/mwl/hooks.js +45 -1
- package/dist/mwl/hooks.js.map +1 -1
- package/dist/mwl/index.d.ts +9 -3
- package/dist/mwl/index.d.ts.map +1 -1
- package/dist/mwl/index.js +5 -2
- package/dist/mwl/index.js.map +1 -1
- package/dist/mwl/persistence.d.ts +32 -0
- package/dist/mwl/persistence.d.ts.map +1 -1
- package/dist/mwl/persistence.js +32 -0
- package/dist/mwl/persistence.js.map +1 -1
- package/dist/mwl/readers.d.ts +24 -2
- package/dist/mwl/readers.d.ts.map +1 -1
- package/dist/mwl/readers.js +27 -4
- package/dist/mwl/readers.js.map +1 -1
- package/dist/mwl/report.d.ts +21 -2
- package/dist/mwl/report.d.ts.map +1 -1
- package/dist/mwl/report.js +21 -2
- package/dist/mwl/report.js.map +1 -1
- package/dist/mwl/runtime.d.ts +212 -7
- package/dist/mwl/runtime.d.ts.map +1 -1
- package/dist/mwl/runtime.js +682 -90
- package/dist/mwl/runtime.js.map +1 -1
- package/dist/mwl/schema.d.ts +57 -1
- package/dist/mwl/schema.d.ts.map +1 -1
- package/dist/mwl/schema.js +181 -21
- package/dist/mwl/schema.js.map +1 -1
- package/dist/mwl/scripts.d.ts +12 -1
- package/dist/mwl/scripts.d.ts.map +1 -1
- package/dist/mwl/scripts.js +12 -1
- package/dist/mwl/scripts.js.map +1 -1
- package/dist/mwl/utils.d.ts +2 -0
- package/dist/mwl/utils.d.ts.map +1 -1
- package/dist/mwl/utils.js +4 -1
- package/dist/mwl/utils.js.map +1 -1
- package/dist/roguelike/MultiTurnBeam.d.ts +50 -12
- package/dist/roguelike/MultiTurnBeam.d.ts.map +1 -1
- package/dist/roguelike/MultiTurnBeam.js +100 -53
- package/dist/roguelike/MultiTurnBeam.js.map +1 -1
- package/dist/roguelike/Targeting.d.ts +94 -0
- package/dist/roguelike/Targeting.d.ts.map +1 -1
- package/dist/roguelike/Targeting.js +123 -0
- package/dist/roguelike/Targeting.js.map +1 -1
- package/dist/roguelike/index.d.ts +3 -1
- package/dist/roguelike/index.d.ts.map +1 -1
- package/dist/roguelike/index.js +1 -0
- package/dist/roguelike/index.js.map +1 -1
- package/dist/rpg/GameState.d.ts +2 -2
- package/dist/rpg/GameState.js +2 -2
- package/dist/simulation/CampaignSave.d.ts +68 -0
- package/dist/simulation/CampaignSave.d.ts.map +1 -0
- package/dist/simulation/CampaignSave.js +54 -0
- package/dist/simulation/CampaignSave.js.map +1 -0
- package/dist/simulation/EventPresentation.d.ts +111 -0
- package/dist/simulation/EventPresentation.d.ts.map +1 -0
- package/dist/simulation/EventPresentation.js +120 -0
- package/dist/simulation/EventPresentation.js.map +1 -0
- package/dist/simulation/index.d.ts +4 -0
- package/dist/simulation/index.d.ts.map +1 -1
- package/dist/simulation/index.js +2 -0
- package/dist/simulation/index.js.map +1 -1
- package/dist/two-d/pixi-interop.d.ts +18 -6
- package/dist/two-d/pixi-interop.d.ts.map +1 -1
- package/dist/two-d/pixi-interop.js +18 -6
- package/dist/two-d/pixi-interop.js.map +1 -1
- package/dist/two-d/render/AnimatedSprite.d.ts +74 -7
- package/dist/two-d/render/AnimatedSprite.d.ts.map +1 -1
- package/dist/two-d/render/AnimatedSprite.js +88 -26
- package/dist/two-d/render/AnimatedSprite.js.map +1 -1
- package/dist/two-d/render/Camera.d.ts +64 -4
- package/dist/two-d/render/Camera.d.ts.map +1 -1
- package/dist/two-d/render/Camera.js +132 -11
- package/dist/two-d/render/Camera.js.map +1 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts +7 -1
- package/dist/two-d/render/ColorTransformBatcher.d.ts.map +1 -1
- package/dist/two-d/render/ColorTransformBatcher.js +10 -1
- package/dist/two-d/render/ColorTransformBatcher.js.map +1 -1
- package/dist/two-d/render/Halo.d.ts +58 -0
- package/dist/two-d/render/Halo.d.ts.map +1 -0
- package/dist/two-d/render/Halo.js +48 -0
- package/dist/two-d/render/Halo.js.map +1 -0
- package/dist/two-d/render/ImageModifiers.d.ts +174 -0
- package/dist/two-d/render/ImageModifiers.d.ts.map +1 -1
- package/dist/two-d/render/ImageModifiers.js +454 -1
- package/dist/two-d/render/ImageModifiers.js.map +1 -1
- package/dist/two-d/render/LightningArc.d.ts +57 -0
- package/dist/two-d/render/LightningArc.d.ts.map +1 -0
- package/dist/two-d/render/LightningArc.js +91 -0
- package/dist/two-d/render/LightningArc.js.map +1 -0
- package/dist/two-d/render/PaletteRemap.d.ts +135 -0
- package/dist/two-d/render/PaletteRemap.d.ts.map +1 -0
- package/dist/two-d/render/PaletteRemap.js +181 -0
- package/dist/two-d/render/PaletteRemap.js.map +1 -0
- package/dist/two-d/render/Particles.d.ts +26 -0
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +23 -2
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/SpriteAttachment.d.ts +55 -0
- package/dist/two-d/render/SpriteAttachment.d.ts.map +1 -0
- package/dist/two-d/render/SpriteAttachment.js +60 -0
- package/dist/two-d/render/SpriteAttachment.js.map +1 -0
- package/dist/two-d/render/TerrainGraphics.d.ts +142 -0
- package/dist/two-d/render/TerrainGraphics.d.ts.map +1 -0
- package/dist/two-d/render/TerrainGraphics.js +161 -0
- package/dist/two-d/render/TerrainGraphics.js.map +1 -0
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts +55 -0
- package/dist/two-d/render/TerrainGraphicsLayer.d.ts.map +1 -0
- package/dist/two-d/render/TerrainGraphicsLayer.js +54 -0
- package/dist/two-d/render/TerrainGraphicsLayer.js.map +1 -0
- package/dist/two-d/render/TintedSprite.js +2 -2
- package/dist/two-d/render/TintedSprite.js.map +1 -1
- package/dist/two-d/render/index.d.ts +15 -3
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +7 -1
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/stage/StoryScreen.d.ts +110 -0
- package/dist/two-d/stage/StoryScreen.d.ts.map +1 -0
- package/dist/two-d/stage/StoryScreen.js +178 -0
- package/dist/two-d/stage/StoryScreen.js.map +1 -0
- package/dist/two-d/stage/index.d.ts +2 -0
- package/dist/two-d/stage/index.d.ts.map +1 -1
- package/dist/two-d/stage/index.js +1 -0
- package/dist/two-d/stage/index.js.map +1 -1
- package/dist/two-d/ui/Checkbox.d.ts +44 -0
- package/dist/two-d/ui/Checkbox.d.ts.map +1 -0
- package/dist/two-d/ui/Checkbox.js +89 -0
- package/dist/two-d/ui/Checkbox.js.map +1 -0
- package/dist/two-d/ui/DataTable.d.ts +79 -0
- package/dist/two-d/ui/DataTable.d.ts.map +1 -0
- package/dist/two-d/ui/DataTable.js +164 -0
- package/dist/two-d/ui/DataTable.js.map +1 -0
- package/dist/two-d/ui/Dropdown.d.ts +72 -0
- package/dist/two-d/ui/Dropdown.d.ts.map +1 -0
- package/dist/two-d/ui/Dropdown.js +126 -0
- package/dist/two-d/ui/Dropdown.js.map +1 -0
- package/dist/two-d/ui/FloatingText.d.ts +43 -4
- package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingText.js +52 -5
- package/dist/two-d/ui/FloatingText.js.map +1 -1
- package/dist/two-d/ui/FloatingTextStack.d.ts +86 -13
- package/dist/two-d/ui/FloatingTextStack.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingTextStack.js +89 -18
- package/dist/two-d/ui/FloatingTextStack.js.map +1 -1
- package/dist/two-d/ui/Layout.d.ts +105 -0
- package/dist/two-d/ui/Layout.d.ts.map +1 -0
- package/dist/two-d/ui/Layout.js +174 -0
- package/dist/two-d/ui/Layout.js.map +1 -0
- package/dist/two-d/ui/MarkupText.d.ts +53 -0
- package/dist/two-d/ui/MarkupText.d.ts.map +1 -0
- package/dist/two-d/ui/MarkupText.js +122 -0
- package/dist/two-d/ui/MarkupText.js.map +1 -0
- package/dist/two-d/ui/ScrollBox.d.ts +67 -0
- package/dist/two-d/ui/ScrollBox.d.ts.map +1 -0
- package/dist/two-d/ui/ScrollBox.js +127 -0
- package/dist/two-d/ui/ScrollBox.js.map +1 -0
- package/dist/two-d/ui/Skins.d.ts +59 -0
- package/dist/two-d/ui/Skins.d.ts.map +1 -0
- package/dist/two-d/ui/Skins.js +77 -0
- package/dist/two-d/ui/Skins.js.map +1 -0
- package/dist/two-d/ui/Slider.d.ts +91 -0
- package/dist/two-d/ui/Slider.d.ts.map +1 -0
- package/dist/two-d/ui/Slider.js +170 -0
- package/dist/two-d/ui/Slider.js.map +1 -0
- package/dist/two-d/ui/Spinner.d.ts +67 -0
- package/dist/two-d/ui/Spinner.d.ts.map +1 -0
- package/dist/two-d/ui/Spinner.js +137 -0
- package/dist/two-d/ui/Spinner.js.map +1 -0
- package/dist/two-d/ui/TabbedList.d.ts +118 -0
- package/dist/two-d/ui/TabbedList.d.ts.map +1 -0
- package/dist/two-d/ui/TabbedList.js +221 -0
- package/dist/two-d/ui/TabbedList.js.map +1 -0
- package/dist/two-d/ui/TextModel.d.ts +65 -0
- package/dist/two-d/ui/TextModel.d.ts.map +1 -0
- package/dist/two-d/ui/TextModel.js +126 -0
- package/dist/two-d/ui/TextModel.js.map +1 -0
- package/dist/two-d/ui/TreeView.d.ts +68 -0
- package/dist/two-d/ui/TreeView.d.ts.map +1 -0
- package/dist/two-d/ui/TreeView.js +133 -0
- package/dist/two-d/ui/TreeView.js.map +1 -0
- package/dist/two-d/ui/Window.d.ts +13 -0
- package/dist/two-d/ui/Window.d.ts.map +1 -1
- package/dist/two-d/ui/Window.js +23 -0
- package/dist/two-d/ui/Window.js.map +1 -1
- package/dist/two-d/ui/WindowStack.d.ts.map +1 -1
- package/dist/two-d/ui/WindowStack.js +2 -0
- package/dist/two-d/ui/WindowStack.js.map +1 -1
- package/dist/two-d/ui/index.d.ts +29 -3
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +15 -2
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/two-d/ui/markup.d.ts +181 -0
- package/dist/two-d/ui/markup.d.ts.map +1 -0
- package/dist/two-d/ui/markup.js +370 -0
- package/dist/two-d/ui/markup.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/world/SideTurns.d.ts +115 -0
- package/dist/world/SideTurns.d.ts.map +1 -0
- package/dist/world/SideTurns.js +138 -0
- package/dist/world/SideTurns.js.map +1 -0
- package/dist/world/index.d.ts +2 -0
- package/dist/world/index.d.ts.map +1 -1
- package/dist/world/index.js +1 -0
- package/dist/world/index.js.map +1 -1
- package/package.json +2 -1
package/dist/actors/craft.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
function matchesIngredient(item, ingredient) {
|
|
2
|
+
if (ingredient.matches)
|
|
3
|
+
return ingredient.matches(item);
|
|
4
|
+
if (ingredient.category !== undefined)
|
|
5
|
+
return item.category === ingredient.category;
|
|
6
|
+
if (typeof ingredient.id === 'string')
|
|
7
|
+
return item.id === ingredient.id;
|
|
8
|
+
return (ingredient.id ?? []).includes(item.id);
|
|
9
|
+
}
|
|
10
|
+
function ingredientHasMatcher(ingredient) {
|
|
11
|
+
return ingredient.matches !== undefined || ingredient.category !== undefined || ingredient.id !== undefined;
|
|
12
|
+
}
|
|
1
13
|
/**
|
|
2
14
|
* Resolves a recipe against an inventory: every ingredient checked, consumed, and the
|
|
3
15
|
* result added, all in one call - the same small-focused-function shape `skillCheck`
|
|
@@ -5,10 +17,15 @@
|
|
|
5
17
|
* adds/removes what a game already hands it; nothing there turns one stack of items into a
|
|
6
18
|
* different one, which is the entire gap this closes.
|
|
7
19
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
20
|
+
* An ingredient may name an exact `id` (or any of several), a `category` ("any herb", matched
|
|
21
|
+
* against the item definition's own `category`), or a `matches` predicate, and a quantity is
|
|
22
|
+
* taken from as many matching stacks as it spans.
|
|
23
|
+
*
|
|
24
|
+
* All or nothing: if any ingredient is missing or too few, nothing is touched. The allocation
|
|
25
|
+
* runs against a working copy of the stacks first, so two ingredients that could both take the
|
|
26
|
+
* same stack cannot each count it. If every ingredient is present but the result would not fit
|
|
27
|
+
* (`Inventory`'s own capacity, unrelated to crafting itself), the ingredients are put back
|
|
28
|
+
* exactly as they were rather than being spent for nothing.
|
|
12
29
|
*
|
|
13
30
|
* @returns whether the recipe resolved
|
|
14
31
|
*
|
|
@@ -17,38 +34,53 @@
|
|
|
17
34
|
* import { craft, Inventory, type Recipe } from '@datamoc/mw_games/actors';
|
|
18
35
|
*
|
|
19
36
|
* const bag = new Inventory();
|
|
20
|
-
* bag.add({ id: '
|
|
21
|
-
* bag.add({ id: '
|
|
37
|
+
* bag.add({ id: 'sage', quantity: 2, stackable: true, category: 'herb' });
|
|
38
|
+
* bag.add({ id: 'ember', quantity: 1, stackable: true, category: 'runestone' });
|
|
22
39
|
*
|
|
23
40
|
* const recipe: Recipe = {
|
|
24
|
-
* ingredients: [
|
|
25
|
-
*
|
|
41
|
+
* ingredients: [
|
|
42
|
+
* { category: 'herb', quantity: 2 },
|
|
43
|
+
* { category: 'runestone', quantity: 1 },
|
|
44
|
+
* ],
|
|
45
|
+
* result: { id: 'elixir', quantity: 1 },
|
|
26
46
|
* };
|
|
27
47
|
*
|
|
28
|
-
* const made = craft(bag, recipe); // true -
|
|
48
|
+
* const made = craft(bag, recipe); // true - any herb plus any runestone becomes an elixir
|
|
29
49
|
* ```
|
|
30
50
|
*/
|
|
31
51
|
export function craft(inventory, recipe) {
|
|
32
|
-
|
|
52
|
+
//a working copy of every stack's quantity, so an earlier ingredient consumes this allocation
|
|
53
|
+
//even when a later one matches the same category or predicate
|
|
54
|
+
const available = new Map();
|
|
55
|
+
for (const item of inventory.items)
|
|
56
|
+
available.set(item, item.quantity);
|
|
57
|
+
const taken = new Map();
|
|
33
58
|
for (const ingredient of recipe.ingredients) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
if (!ingredientHasMatcher(ingredient))
|
|
60
|
+
throw new Error('recipe ingredient must name an id, a category, or a matches predicate');
|
|
61
|
+
if (!Number.isFinite(ingredient.quantity) || ingredient.quantity <= 0)
|
|
62
|
+
throw new Error('recipe ingredient quantity must be a positive number');
|
|
63
|
+
let needed = ingredient.quantity;
|
|
64
|
+
for (const item of inventory.items) {
|
|
65
|
+
if (needed <= 0)
|
|
66
|
+
break;
|
|
67
|
+
const held = available.get(item) ?? 0;
|
|
68
|
+
if (held <= 0 || !matchesIngredient(item, ingredient))
|
|
69
|
+
continue;
|
|
70
|
+
const take = Math.min(held, needed);
|
|
71
|
+
available.set(item, held - take);
|
|
72
|
+
needed -= take;
|
|
73
|
+
taken.set(item, (taken.get(item) ?? 0) + take);
|
|
74
|
+
}
|
|
75
|
+
if (needed > 0)
|
|
39
76
|
return false;
|
|
40
77
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
...inventory.find(ingredient.id),
|
|
44
|
-
quantity: ingredient.quantity,
|
|
45
|
-
}));
|
|
46
|
-
for (const ingredient of recipe.ingredients)
|
|
47
|
-
inventory.remove(ingredient.id, ingredient.quantity);
|
|
78
|
+
for (const [item, quantity] of taken)
|
|
79
|
+
inventory.remove(item.id, quantity, item.instanceId);
|
|
48
80
|
if (inventory.add(recipe.result))
|
|
49
81
|
return true;
|
|
50
|
-
for (const item of
|
|
51
|
-
inventory.add(item);
|
|
82
|
+
for (const [item, quantity] of taken)
|
|
83
|
+
inventory.add({ ...item, quantity });
|
|
52
84
|
return false;
|
|
53
85
|
}
|
|
54
86
|
//# sourceMappingURL=craft.js.map
|
package/dist/actors/craft.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"craft.js","sourceRoot":"","sources":["../../src/actors/craft.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"craft.js","sourceRoot":"","sources":["../../src/actors/craft.ts"],"names":[],"mappings":"AA4BA,SAAS,iBAAiB,CAAC,IAAmB,EAAE,UAAsB;IACrE,IAAI,UAAU,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CAAC;IACpF,IAAI,OAAO,UAAU,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;IACxE,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,oBAAoB,CAAC,UAAsB;IACnD,OAAO,UAAU,CAAC,OAAO,KAAK,SAAS,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,IAAI,UAAU,CAAC,EAAE,KAAK,SAAS,CAAC;AAC7G,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,UAAU,KAAK,CAAC,SAAoB,EAAE,MAAc;IACzD,6FAA6F;IAC7F,8DAA8D;IAC9D,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IACnD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK;QAAE,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC/C,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC7C,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,QAAQ,IAAI,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAEzE,IAAI,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACpC,IAAI,MAAM,IAAI,CAAC;gBAAE,MAAM;YACvB,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC;gBAAE,SAAS;YAChE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACpC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;YACjC,MAAM,IAAI,IAAI,CAAC;YACf,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IAC9B,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK;QAAE,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3F,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,KAAK;QAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACd,CAAC"}
|
package/dist/actors/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type { EquippableItem, EquipmentOptions, SavedEquipment } from './Equipme
|
|
|
10
10
|
export { Inventory } from './Inventory.ts';
|
|
11
11
|
export type { InventoryItem, InventoryOptions, ItemDefinition, SavedInventory, SavedInventoryItem, } from './Inventory.ts';
|
|
12
12
|
export { craft } from './craft.ts';
|
|
13
|
-
export type { Recipe } from './craft.ts';
|
|
13
|
+
export type { Ingredient, Recipe } from './craft.ts';
|
|
14
14
|
export { applyStatusEffect } from './StatusEffect.ts';
|
|
15
15
|
export type { EffectClock, StatusEffectOptions, StatusEffectHandle } from './StatusEffect.ts';
|
|
16
16
|
export { identify, enchant, damageItem, repairItem } from './ItemState.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,kBAAkB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actors/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/** A single aspect's value: the shapes a game authors in content without inventing a type. */
|
|
2
|
+
export type AspectValue = number | string | boolean | readonly string[];
|
|
3
|
+
export interface AspectValues {
|
|
4
|
+
readonly [name: string]: AspectValue | undefined;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The named tuning knobs of a heuristic AI - Wesnoth's "aspects" - read by whatever stage is
|
|
8
|
+
* scoring candidates. `mwg` ships no values, because the numbers are game content: a side sets
|
|
9
|
+
* `aggression`, `caution`, `village_value`, `keep_away` and the rest to whatever its own balance
|
|
10
|
+
* wants, and a difficulty level overrides a few of them.
|
|
11
|
+
*
|
|
12
|
+
* Typed readers give a stage a usable number without every caller casting: a missing aspect reads
|
|
13
|
+
* as the fallback (`1` for a weight, so an unset aspect is neutral rather than zeroing a score).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { Aspects } from '@datamoc/mw_games/ai';
|
|
18
|
+
*
|
|
19
|
+
* const aspects = new Aspects({ aggression: 2, keep_away: 3 });
|
|
20
|
+
* console.log(aspects.number('aggression')); // 2
|
|
21
|
+
* console.log(aspects.number('caution')); // 0 - the fallback
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class Aspects {
|
|
25
|
+
private values;
|
|
26
|
+
constructor(defaults?: AspectValues);
|
|
27
|
+
has(name: string): boolean;
|
|
28
|
+
get(name: string): AspectValue | undefined;
|
|
29
|
+
set(name: string, value: AspectValue): void;
|
|
30
|
+
/** a numeric aspect, or `fallback` when it is missing or not a number */
|
|
31
|
+
number(name: string, fallback?: number): number;
|
|
32
|
+
flag(name: string, fallback?: boolean): boolean;
|
|
33
|
+
/** a list aspect; a bare string reads as a one-entry list, anything else as empty */
|
|
34
|
+
list(name: string): readonly string[];
|
|
35
|
+
names(): string[];
|
|
36
|
+
/** a new store with `overrides` laid over this one, leaving this one untouched */
|
|
37
|
+
with(overrides: AspectValues): Aspects;
|
|
38
|
+
toJSON(): Record<string, AspectValue>;
|
|
39
|
+
static fromJSON(values: Readonly<Record<string, AspectValue>>): Aspects;
|
|
40
|
+
}
|
|
41
|
+
export interface DifficultyLevel {
|
|
42
|
+
id: string;
|
|
43
|
+
name?: string;
|
|
44
|
+
/** the aspects this level changes from the game's base set */
|
|
45
|
+
aspects?: AspectValues;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Named difficulty levels, each a set of aspect overrides - Wesnoth's native difficulty ladder,
|
|
49
|
+
* which is really "the same AI with different numbers". A level is applied on top of a base aspect
|
|
50
|
+
* set, so a game writes its normal AI once and a level only lists what it changes.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { Aspects, Difficulty } from '@datamoc/mw_games/ai';
|
|
55
|
+
*
|
|
56
|
+
* const difficulty = new Difficulty(
|
|
57
|
+
* [{ id: 'hard', aspects: { aggression: 2, keep_away: 3 } }],
|
|
58
|
+
* { aggression: 1 },
|
|
59
|
+
* );
|
|
60
|
+
* console.log(difficulty.aspectsFor('hard').number('aggression')); // 2
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class Difficulty {
|
|
64
|
+
private readonly levels;
|
|
65
|
+
private readonly base;
|
|
66
|
+
constructor(levels?: readonly DifficultyLevel[], base?: AspectValues);
|
|
67
|
+
get ids(): string[];
|
|
68
|
+
get(id: string): DifficultyLevel | undefined;
|
|
69
|
+
/** the base aspects with a level's overrides applied; throws for an unknown level */
|
|
70
|
+
aspectsFor(id: string): Aspects;
|
|
71
|
+
}
|
|
72
|
+
export type GoalKind = 'attack' | 'defend' | 'retreat' | 'capture' | 'scout';
|
|
73
|
+
export interface Goal {
|
|
74
|
+
unit: string;
|
|
75
|
+
kind: GoalKind;
|
|
76
|
+
/** what the goal is about: the enemy to attack, the village to hold */
|
|
77
|
+
target?: string;
|
|
78
|
+
/** a tiebreaker between goals, read by a stage's own `weigh`; defaults to 1 */
|
|
79
|
+
priority?: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Per-unit goals - "hold this village", "attack that leader" - kept as a small registry for a
|
|
83
|
+
* stage's `weigh` to read. `mwg` does not decide what a goal is worth, the same way it ships no
|
|
84
|
+
* damage formula: the registry answers *what* a unit has been told to do, and a game's weigh
|
|
85
|
+
* decides how much that matters.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { Goals } from '@datamoc/mw_games/ai';
|
|
90
|
+
*
|
|
91
|
+
* const goals = new Goals();
|
|
92
|
+
* goals.set({ unit: 'hero', kind: 'attack', target: 'rat', priority: 3 });
|
|
93
|
+
* console.log(goals.get('hero')?.kind); // 'attack'
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare class Goals {
|
|
97
|
+
private readonly byUnit;
|
|
98
|
+
set(goal: Goal): void;
|
|
99
|
+
clear(unit: string): void;
|
|
100
|
+
get(unit: string): Goal | undefined;
|
|
101
|
+
all(): readonly Goal[];
|
|
102
|
+
get isEmpty(): boolean;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The order a side recruits in - Wesnoth's `recruitment_pattern`, e.g. `scout, fighter, archer` -
|
|
106
|
+
* cycled by turn. A side with nothing left to recruit falls back to its `fallback`, and a side
|
|
107
|
+
* with neither recruits nothing.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* import { RecruitmentPattern } from '@datamoc/mw_games/ai';
|
|
112
|
+
*
|
|
113
|
+
* const pattern = new RecruitmentPattern(['scout', 'fighter'], 'fighter');
|
|
114
|
+
* console.log(pattern.at(0), pattern.at(1), pattern.at(2)); // scout fighter scout
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare class RecruitmentPattern {
|
|
118
|
+
private readonly order;
|
|
119
|
+
private readonly fallback;
|
|
120
|
+
constructor(order: readonly string[], fallback?: string | null);
|
|
121
|
+
get length(): number;
|
|
122
|
+
/** the unit type at a position in the cycle, or the fallback when the pattern is empty */
|
|
123
|
+
at(index: number): string | null;
|
|
124
|
+
/** the entry after `after` in the cycle, or the first when `after` is not in it */
|
|
125
|
+
next(after: string | null): string | null;
|
|
126
|
+
}
|
|
127
|
+
export interface HeuristicCandidate<A = unknown> {
|
|
128
|
+
/** an id for tracing which candidate won */
|
|
129
|
+
id: string;
|
|
130
|
+
action: A;
|
|
131
|
+
/** the unit the action belongs to, matched against `Goals` by a stage's own `weigh` */
|
|
132
|
+
unit?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Aspect-named weights this candidate contributes, e.g. `{ aggression: 3, village_value: 2 }`.
|
|
135
|
+
* `distance` is special: with a `keep_away` aspect it is penalised by `keepAwayScore`.
|
|
136
|
+
*/
|
|
137
|
+
factors?: Readonly<Record<string, number>>;
|
|
138
|
+
/** the acting unit's type, when the candidate carries one */
|
|
139
|
+
type?: string;
|
|
140
|
+
/** the acting unit's role/function, e.g. `leader` or `courier` */
|
|
141
|
+
role?: string;
|
|
142
|
+
/** whether the acting unit can recruit */
|
|
143
|
+
can_recruit?: boolean;
|
|
144
|
+
/** the acting unit's own name */
|
|
145
|
+
name?: string;
|
|
146
|
+
}
|
|
147
|
+
export interface HeuristicContext {
|
|
148
|
+
aspects: Aspects;
|
|
149
|
+
goals?: Goals;
|
|
150
|
+
turn?: number;
|
|
151
|
+
}
|
|
152
|
+
export interface HeuristicStage<A = unknown> {
|
|
153
|
+
id: string;
|
|
154
|
+
/** whether this stage runs at all; it always does when omitted */
|
|
155
|
+
when?: (context: HeuristicContext) => boolean;
|
|
156
|
+
/** score one candidate; higher wins. Defaults to `defaultWeigh` */
|
|
157
|
+
weigh?: (candidate: HeuristicCandidate<A>, context: HeuristicContext) => number;
|
|
158
|
+
}
|
|
159
|
+
export interface HeuristicDecision<A = unknown> {
|
|
160
|
+
candidate: HeuristicCandidate<A>;
|
|
161
|
+
stage: string;
|
|
162
|
+
score: number;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The candidate-action pipeline at the heart of a Wesnoth-style AI: stages run in order, the first
|
|
166
|
+
* one whose `when` passes scores every candidate with its `weigh`, and the highest score wins (the
|
|
167
|
+
* earlier candidate on a tie, so a decision is stable across equal scores).
|
|
168
|
+
*
|
|
169
|
+
* The default `weigh` is the aspect-weighted sum of each candidate's `factors`, which is what makes
|
|
170
|
+
* the aspects worth having: a game sets `aggression: 2` once and every candidate naming
|
|
171
|
+
* `aggression` is worth twice as much. `keep_away` is honoured through a candidate's `distance`
|
|
172
|
+
* factor. A stage that needs more - goal priorities, terrain, this turn's state - brings its own
|
|
173
|
+
* `weigh`, and `mwg` stays out of the rules.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* import { Aspects, HeuristicAI } from '@datamoc/mw_games/ai';
|
|
178
|
+
*
|
|
179
|
+
* const ai = new HeuristicAI<{ kind: string }>({ stages: [{ id: 'best' }] });
|
|
180
|
+
* const decision = ai.decide(
|
|
181
|
+
* [
|
|
182
|
+
* { id: 'wait', action: { kind: 'wait' }, factors: { caution: 2 } },
|
|
183
|
+
* { id: 'charge', action: { kind: 'attack' }, factors: { aggression: 3 } },
|
|
184
|
+
* ],
|
|
185
|
+
* { aspects: new Aspects({ aggression: 1, caution: 1 }) },
|
|
186
|
+
* );
|
|
187
|
+
* console.log(decision?.candidate.id); // 'charge'
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare class HeuristicAI<A = unknown> {
|
|
191
|
+
private readonly stages;
|
|
192
|
+
constructor(options: {
|
|
193
|
+
stages: readonly HeuristicStage<A>[];
|
|
194
|
+
});
|
|
195
|
+
/** the first stage's best candidate, or `null` when nothing applies or no candidate is given */
|
|
196
|
+
decide(candidates: readonly HeuristicCandidate<A>[], context: HeuristicContext): HeuristicDecision<A> | null;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The default stage weight: each factor times the aspect of the same name (an unset aspect weighs
|
|
200
|
+
* 1, so a factor on its own is not erased), minus a `keepAwayScore` penalty for a candidate's
|
|
201
|
+
* `distance`.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* import { Aspects, defaultWeigh } from '@datamoc/mw_games/ai';
|
|
206
|
+
*
|
|
207
|
+
* const score = defaultWeigh(
|
|
208
|
+
* { id: 'charge', action: {}, factors: { aggression: 3 } },
|
|
209
|
+
* { aspects: new Aspects({ aggression: 2 }) },
|
|
210
|
+
* );
|
|
211
|
+
* console.log(score); // 6
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
export declare function defaultWeigh<A>(candidate: HeuristicCandidate<A>, context: HeuristicContext): number;
|
|
215
|
+
/**
|
|
216
|
+
* How much a candidate at `distance` loses for being inside a `keepAway` radius: 0 when there is no
|
|
217
|
+
* radius or the candidate is outside it, otherwise the shortfall as a negative score.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* import { keepAwayScore } from '@datamoc/mw_games/ai';
|
|
222
|
+
*
|
|
223
|
+
* console.log(keepAwayScore(1, 3)); // -2, two tiles inside the radius
|
|
224
|
+
* console.log(keepAwayScore(5, 3)); // 0, outside it
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
227
|
+
export declare function keepAwayScore(distance: number, keepAway: number): number;
|
|
228
|
+
/**
|
|
229
|
+
* What a stage's own weigh can add for a goal: its `priority`, or 1 when it has none.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```ts
|
|
233
|
+
* import { goalScore } from '@datamoc/mw_games/ai';
|
|
234
|
+
*
|
|
235
|
+
* console.log(goalScore({ unit: 'u1', kind: 'attack', priority: 3 })); // 3
|
|
236
|
+
* console.log(goalScore(undefined)); // 0, no goal at all
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
export declare function goalScore(goal: Goal | undefined): number;
|
|
240
|
+
//# sourceMappingURL=Heuristics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Heuristics.d.ts","sourceRoot":"","sources":["../../src/ai/Heuristics.ts"],"names":[],"mappings":"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"}
|