idlerpg.sh 0.1.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/README.md +171 -0
- package/dist/affix/AffixRegistry.d.ts +68 -0
- package/dist/affix/AffixRegistry.d.ts.map +1 -0
- package/dist/affix/AffixRegistry.js +245 -0
- package/dist/affix/AffixRegistry.js.map +1 -0
- package/dist/affix/PluginLoader.d.ts +66 -0
- package/dist/affix/PluginLoader.d.ts.map +1 -0
- package/dist/affix/PluginLoader.js +321 -0
- package/dist/affix/PluginLoader.js.map +1 -0
- package/dist/affix/builtin.d.ts +6 -0
- package/dist/affix/builtin.d.ts.map +1 -0
- package/dist/affix/builtin.js +311 -0
- package/dist/affix/builtin.js.map +1 -0
- package/dist/affix/index.d.ts +8 -0
- package/dist/affix/index.d.ts.map +1 -0
- package/dist/affix/index.js +11 -0
- package/dist/affix/index.js.map +1 -0
- package/dist/affix/types.d.ts +152 -0
- package/dist/affix/types.d.ts.map +1 -0
- package/dist/affix/types.js +8 -0
- package/dist/affix/types.js.map +1 -0
- package/dist/ai/PlayKitClient.d.ts +208 -0
- package/dist/ai/PlayKitClient.d.ts.map +1 -0
- package/dist/ai/PlayKitClient.js +721 -0
- package/dist/ai/PlayKitClient.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/app/App.d.ts +85 -0
- package/dist/app/App.d.ts.map +1 -0
- package/dist/app/App.js +296 -0
- package/dist/app/App.js.map +1 -0
- package/dist/app/EventBus.d.ts +222 -0
- package/dist/app/EventBus.d.ts.map +1 -0
- package/dist/app/EventBus.js +88 -0
- package/dist/app/EventBus.js.map +1 -0
- package/dist/app/Keybind.d.ts +83 -0
- package/dist/app/Keybind.d.ts.map +1 -0
- package/dist/app/Keybind.js +184 -0
- package/dist/app/Keybind.js.map +1 -0
- package/dist/app/Router.d.ts +123 -0
- package/dist/app/Router.d.ts.map +1 -0
- package/dist/app/Router.js +142 -0
- package/dist/app/Router.js.map +1 -0
- package/dist/app/ScreenManager.d.ts +97 -0
- package/dist/app/ScreenManager.d.ts.map +1 -0
- package/dist/app/ScreenManager.js +216 -0
- package/dist/app/ScreenManager.js.map +1 -0
- package/dist/app/index.d.ts +14 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +19 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/screens/BaseScreen.d.ts +101 -0
- package/dist/app/screens/BaseScreen.d.ts.map +1 -0
- package/dist/app/screens/BaseScreen.js +132 -0
- package/dist/app/screens/BaseScreen.js.map +1 -0
- package/dist/app/screens/CharacterCreationScreen.d.ts +42 -0
- package/dist/app/screens/CharacterCreationScreen.d.ts.map +1 -0
- package/dist/app/screens/CharacterCreationScreen.js +467 -0
- package/dist/app/screens/CharacterCreationScreen.js.map +1 -0
- package/dist/app/screens/CombatScreen.d.ts +30 -0
- package/dist/app/screens/CombatScreen.d.ts.map +1 -0
- package/dist/app/screens/CombatScreen.js +309 -0
- package/dist/app/screens/CombatScreen.js.map +1 -0
- package/dist/app/screens/DialogScreen.d.ts +29 -0
- package/dist/app/screens/DialogScreen.d.ts.map +1 -0
- package/dist/app/screens/DialogScreen.js +295 -0
- package/dist/app/screens/DialogScreen.js.map +1 -0
- package/dist/app/screens/ExploreScreen.d.ts +50 -0
- package/dist/app/screens/ExploreScreen.d.ts.map +1 -0
- package/dist/app/screens/ExploreScreen.js +308 -0
- package/dist/app/screens/ExploreScreen.js.map +1 -0
- package/dist/app/screens/HelpScreen.d.ts +12 -0
- package/dist/app/screens/HelpScreen.d.ts.map +1 -0
- package/dist/app/screens/HelpScreen.js +155 -0
- package/dist/app/screens/HelpScreen.js.map +1 -0
- package/dist/app/screens/InventoryScreen.d.ts +27 -0
- package/dist/app/screens/InventoryScreen.d.ts.map +1 -0
- package/dist/app/screens/InventoryScreen.js +326 -0
- package/dist/app/screens/InventoryScreen.js.map +1 -0
- package/dist/app/screens/PrologueScreen.d.ts +24 -0
- package/dist/app/screens/PrologueScreen.d.ts.map +1 -0
- package/dist/app/screens/PrologueScreen.js +176 -0
- package/dist/app/screens/PrologueScreen.js.map +1 -0
- package/dist/app/screens/TitleScreen.d.ts +42 -0
- package/dist/app/screens/TitleScreen.d.ts.map +1 -0
- package/dist/app/screens/TitleScreen.js +380 -0
- package/dist/app/screens/TitleScreen.js.map +1 -0
- package/dist/app/screens/TravelScreen.d.ts +22 -0
- package/dist/app/screens/TravelScreen.d.ts.map +1 -0
- package/dist/app/screens/TravelScreen.js +122 -0
- package/dist/app/screens/TravelScreen.js.map +1 -0
- package/dist/app/screens/index.d.ts +14 -0
- package/dist/app/screens/index.d.ts.map +1 -0
- package/dist/app/screens/index.js +17 -0
- package/dist/app/screens/index.js.map +1 -0
- package/dist/commands/CommandRegistry.d.ts +91 -0
- package/dist/commands/CommandRegistry.d.ts.map +1 -0
- package/dist/commands/CommandRegistry.js +159 -0
- package/dist/commands/CommandRegistry.js.map +1 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +10 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/core/Actor.d.ts +103 -0
- package/dist/core/Actor.d.ts.map +1 -0
- package/dist/core/Actor.js +409 -0
- package/dist/core/Actor.js.map +1 -0
- package/dist/core/Combat.d.ts +37 -0
- package/dist/core/Combat.d.ts.map +1 -0
- package/dist/core/Combat.js +294 -0
- package/dist/core/Combat.js.map +1 -0
- package/dist/core/DungeonRunner.d.ts +169 -0
- package/dist/core/DungeonRunner.d.ts.map +1 -0
- package/dist/core/DungeonRunner.js +627 -0
- package/dist/core/DungeonRunner.js.map +1 -0
- package/dist/core/Game.d.ts +133 -0
- package/dist/core/Game.d.ts.map +1 -0
- package/dist/core/Game.js +644 -0
- package/dist/core/Game.js.map +1 -0
- package/dist/core/IdleCombat.d.ts +61 -0
- package/dist/core/IdleCombat.d.ts.map +1 -0
- package/dist/core/IdleCombat.js +461 -0
- package/dist/core/IdleCombat.js.map +1 -0
- package/dist/core/IdleGameManager.d.ts +198 -0
- package/dist/core/IdleGameManager.d.ts.map +1 -0
- package/dist/core/IdleGameManager.js +688 -0
- package/dist/core/IdleGameManager.js.map +1 -0
- package/dist/core/IdleSaveManager.d.ts +109 -0
- package/dist/core/IdleSaveManager.d.ts.map +1 -0
- package/dist/core/IdleSaveManager.js +296 -0
- package/dist/core/IdleSaveManager.js.map +1 -0
- package/dist/core/NewGameFlowManager.d.ts +64 -0
- package/dist/core/NewGameFlowManager.d.ts.map +1 -0
- package/dist/core/NewGameFlowManager.js +153 -0
- package/dist/core/NewGameFlowManager.js.map +1 -0
- package/dist/core/Player.d.ts +65 -0
- package/dist/core/Player.d.ts.map +1 -0
- package/dist/core/Player.js +261 -0
- package/dist/core/Player.js.map +1 -0
- package/dist/core/RoomHandlers.d.ts +75 -0
- package/dist/core/RoomHandlers.d.ts.map +1 -0
- package/dist/core/RoomHandlers.js +383 -0
- package/dist/core/RoomHandlers.js.map +1 -0
- package/dist/core/SaveManager.d.ts +84 -0
- package/dist/core/SaveManager.d.ts.map +1 -0
- package/dist/core/SaveManager.js +281 -0
- package/dist/core/SaveManager.js.map +1 -0
- package/dist/core/SaveMigration.d.ts +69 -0
- package/dist/core/SaveMigration.d.ts.map +1 -0
- package/dist/core/SaveMigration.js +408 -0
- package/dist/core/SaveMigration.js.map +1 -0
- package/dist/core/StateAdapter.d.ts +79 -0
- package/dist/core/StateAdapter.d.ts.map +1 -0
- package/dist/core/StateAdapter.js +397 -0
- package/dist/core/StateAdapter.js.map +1 -0
- package/dist/core/Team.d.ts +145 -0
- package/dist/core/Team.d.ts.map +1 -0
- package/dist/core/Team.js +371 -0
- package/dist/core/Team.js.map +1 -0
- package/dist/core/TeamCombat.d.ts +88 -0
- package/dist/core/TeamCombat.d.ts.map +1 -0
- package/dist/core/TeamCombat.js +405 -0
- package/dist/core/TeamCombat.js.map +1 -0
- package/dist/core/TeamDungeonRunner.d.ts +186 -0
- package/dist/core/TeamDungeonRunner.d.ts.map +1 -0
- package/dist/core/TeamDungeonRunner.js +758 -0
- package/dist/core/TeamDungeonRunner.js.map +1 -0
- package/dist/core/TimeManager.d.ts +114 -0
- package/dist/core/TimeManager.d.ts.map +1 -0
- package/dist/core/TimeManager.js +318 -0
- package/dist/core/TimeManager.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/timeConstants.d.ts +135 -0
- package/dist/core/timeConstants.d.ts.map +1 -0
- package/dist/core/timeConstants.js +157 -0
- package/dist/core/timeConstants.js.map +1 -0
- package/dist/core/types.d.ts +780 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +16 -0
- package/dist/core/types.js.map +1 -0
- package/dist/data/continents/index.d.ts +163 -0
- package/dist/data/continents/index.d.ts.map +1 -0
- package/dist/data/continents/index.js +31 -0
- package/dist/data/continents/index.js.map +1 -0
- package/dist/data/continents/verdantia.d.ts +294 -0
- package/dist/data/continents/verdantia.d.ts.map +1 -0
- package/dist/data/continents/verdantia.js +327 -0
- package/dist/data/continents/verdantia.js.map +1 -0
- package/dist/handlers/DialogHandler.d.ts +95 -0
- package/dist/handlers/DialogHandler.d.ts.map +1 -0
- package/dist/handlers/DialogHandler.js +450 -0
- package/dist/handlers/DialogHandler.js.map +1 -0
- package/dist/handlers/SaveLoadHandler.d.ts +60 -0
- package/dist/handlers/SaveLoadHandler.d.ts.map +1 -0
- package/dist/handlers/SaveLoadHandler.js +187 -0
- package/dist/handlers/SaveLoadHandler.js.map +1 -0
- package/dist/handlers/TitleScreenHandler.d.ts +43 -0
- package/dist/handlers/TitleScreenHandler.d.ts.map +1 -0
- package/dist/handlers/TitleScreenHandler.js +508 -0
- package/dist/handlers/TitleScreenHandler.js.map +1 -0
- package/dist/handlers/WorkshopHandler.d.ts +75 -0
- package/dist/handlers/WorkshopHandler.d.ts.map +1 -0
- package/dist/handlers/WorkshopHandler.js +401 -0
- package/dist/handlers/WorkshopHandler.js.map +1 -0
- package/dist/handlers/index.d.ts +12 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +14 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/types.d.ts +34 -0
- package/dist/handlers/types.d.ts.map +1 -0
- package/dist/handlers/types.js +8 -0
- package/dist/handlers/types.js.map +1 -0
- package/dist/i18n/en.d.ts +3 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +130 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/index.d.ts +40 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +105 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/types.d.ts +133 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +8 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/i18n/zh.d.ts +3 -0
- package/dist/i18n/zh.d.ts.map +1 -0
- package/dist/i18n/zh.js +130 -0
- package/dist/i18n/zh.js.map +1 -0
- package/dist/instrument.d.ts +8 -0
- package/dist/instrument.d.ts.map +1 -0
- package/dist/instrument.js +33 -0
- package/dist/instrument.js.map +1 -0
- package/dist/main-new.d.ts +12 -0
- package/dist/main-new.d.ts.map +1 -0
- package/dist/main-new.js +32 -0
- package/dist/main-new.js.map +1 -0
- package/dist/main.d.ts +7 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +2816 -0
- package/dist/main.js.map +1 -0
- package/dist/map/ContinentManager.d.ts +88 -0
- package/dist/map/ContinentManager.d.ts.map +1 -0
- package/dist/map/ContinentManager.js +241 -0
- package/dist/map/ContinentManager.js.map +1 -0
- package/dist/map/DungeonGenerator.d.ts +32 -0
- package/dist/map/DungeonGenerator.d.ts.map +1 -0
- package/dist/map/DungeonGenerator.js +615 -0
- package/dist/map/DungeonGenerator.js.map +1 -0
- package/dist/map/MapGenerator.d.ts +27 -0
- package/dist/map/MapGenerator.d.ts.map +1 -0
- package/dist/map/MapGenerator.js +485 -0
- package/dist/map/MapGenerator.js.map +1 -0
- package/dist/map/index.d.ts +5 -0
- package/dist/map/index.d.ts.map +1 -0
- package/dist/map/index.js +8 -0
- package/dist/map/index.js.map +1 -0
- package/dist/npc/NPCGenerator.d.ts +68 -0
- package/dist/npc/NPCGenerator.d.ts.map +1 -0
- package/dist/npc/NPCGenerator.js +468 -0
- package/dist/npc/NPCGenerator.js.map +1 -0
- package/dist/npc/NPCManager.d.ts +86 -0
- package/dist/npc/NPCManager.d.ts.map +1 -0
- package/dist/npc/NPCManager.js +217 -0
- package/dist/npc/NPCManager.js.map +1 -0
- package/dist/npc/fixedNPCs.d.ts +7 -0
- package/dist/npc/fixedNPCs.d.ts.map +1 -0
- package/dist/npc/fixedNPCs.js +196 -0
- package/dist/npc/fixedNPCs.js.map +1 -0
- package/dist/npc/index.d.ts +9 -0
- package/dist/npc/index.d.ts.map +1 -0
- package/dist/npc/index.js +12 -0
- package/dist/npc/index.js.map +1 -0
- package/dist/npc/traits.d.ts +33 -0
- package/dist/npc/traits.d.ts.map +1 -0
- package/dist/npc/traits.js +795 -0
- package/dist/npc/traits.js.map +1 -0
- package/dist/npc/types.d.ts +193 -0
- package/dist/npc/types.d.ts.map +1 -0
- package/dist/npc/types.js +9 -0
- package/dist/npc/types.js.map +1 -0
- package/dist/quest/QuestManager.d.ts +79 -0
- package/dist/quest/QuestManager.d.ts.map +1 -0
- package/dist/quest/QuestManager.js +273 -0
- package/dist/quest/QuestManager.js.map +1 -0
- package/dist/quest/index.d.ts +6 -0
- package/dist/quest/index.d.ts.map +1 -0
- package/dist/quest/index.js +9 -0
- package/dist/quest/index.js.map +1 -0
- package/dist/quest/types.d.ts +81 -0
- package/dist/quest/types.d.ts.map +1 -0
- package/dist/quest/types.js +8 -0
- package/dist/quest/types.js.map +1 -0
- package/dist/strategy/StrategyExecutor.d.ts +159 -0
- package/dist/strategy/StrategyExecutor.d.ts.map +1 -0
- package/dist/strategy/StrategyExecutor.js +479 -0
- package/dist/strategy/StrategyExecutor.js.map +1 -0
- package/dist/strategy/StrategyParser.d.ts +48 -0
- package/dist/strategy/StrategyParser.d.ts.map +1 -0
- package/dist/strategy/StrategyParser.js +321 -0
- package/dist/strategy/StrategyParser.js.map +1 -0
- package/dist/strategy/defaultStrategy.d.ts +40 -0
- package/dist/strategy/defaultStrategy.d.ts.map +1 -0
- package/dist/strategy/defaultStrategy.js +254 -0
- package/dist/strategy/defaultStrategy.js.map +1 -0
- package/dist/strategy/index.d.ts +8 -0
- package/dist/strategy/index.d.ts.map +1 -0
- package/dist/strategy/index.js +14 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/tui/ExploreMenu.d.ts +106 -0
- package/dist/tui/ExploreMenu.d.ts.map +1 -0
- package/dist/tui/ExploreMenu.js +282 -0
- package/dist/tui/ExploreMenu.js.map +1 -0
- package/dist/tui/GameUI.d.ts +313 -0
- package/dist/tui/GameUI.d.ts.map +1 -0
- package/dist/tui/GameUI.js +2116 -0
- package/dist/tui/GameUI.js.map +1 -0
- package/dist/tui/GameUIAdapter.d.ts +207 -0
- package/dist/tui/GameUIAdapter.d.ts.map +1 -0
- package/dist/tui/GameUIAdapter.js +1342 -0
- package/dist/tui/GameUIAdapter.js.map +1 -0
- package/dist/tui/Input.d.ts +139 -0
- package/dist/tui/Input.d.ts.map +1 -0
- package/dist/tui/Input.js +278 -0
- package/dist/tui/Input.js.map +1 -0
- package/dist/tui/Menu.d.ts +110 -0
- package/dist/tui/Menu.d.ts.map +1 -0
- package/dist/tui/Menu.js +365 -0
- package/dist/tui/Menu.js.map +1 -0
- package/dist/tui/Screen.d.ts +228 -0
- package/dist/tui/Screen.d.ts.map +1 -0
- package/dist/tui/Screen.js +502 -0
- package/dist/tui/Screen.js.map +1 -0
- package/dist/tui/components/Box.d.ts +36 -0
- package/dist/tui/components/Box.d.ts.map +1 -0
- package/dist/tui/components/Box.js +43 -0
- package/dist/tui/components/Box.js.map +1 -0
- package/dist/tui/components/List.d.ts +69 -0
- package/dist/tui/components/List.d.ts.map +1 -0
- package/dist/tui/components/List.js +136 -0
- package/dist/tui/components/List.js.map +1 -0
- package/dist/tui/components/ProgressBar.d.ts +42 -0
- package/dist/tui/components/ProgressBar.d.ts.map +1 -0
- package/dist/tui/components/ProgressBar.js +75 -0
- package/dist/tui/components/ProgressBar.js.map +1 -0
- package/dist/tui/components/index.d.ts +8 -0
- package/dist/tui/components/index.d.ts.map +1 -0
- package/dist/tui/components/index.js +11 -0
- package/dist/tui/components/index.js.map +1 -0
- package/dist/tui/core/BaseSection.d.ts +98 -0
- package/dist/tui/core/BaseSection.d.ts.map +1 -0
- package/dist/tui/core/BaseSection.js +174 -0
- package/dist/tui/core/BaseSection.js.map +1 -0
- package/dist/tui/core/Component.d.ts +61 -0
- package/dist/tui/core/Component.d.ts.map +1 -0
- package/dist/tui/core/Component.js +32 -0
- package/dist/tui/core/Component.js.map +1 -0
- package/dist/tui/core/Section.d.ts +101 -0
- package/dist/tui/core/Section.d.ts.map +1 -0
- package/dist/tui/core/Section.js +24 -0
- package/dist/tui/core/Section.js.map +1 -0
- package/dist/tui/core/SectionManager.d.ts +108 -0
- package/dist/tui/core/SectionManager.d.ts.map +1 -0
- package/dist/tui/core/SectionManager.js +258 -0
- package/dist/tui/core/SectionManager.js.map +1 -0
- package/dist/tui/core/index.d.ts +9 -0
- package/dist/tui/core/index.d.ts.map +1 -0
- package/dist/tui/core/index.js +12 -0
- package/dist/tui/core/index.js.map +1 -0
- package/dist/tui/index.d.ts +15 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +23 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/screens/BaseScreen.d.ts +62 -0
- package/dist/tui/screens/BaseScreen.d.ts.map +1 -0
- package/dist/tui/screens/BaseScreen.js +55 -0
- package/dist/tui/screens/BaseScreen.js.map +1 -0
- package/dist/tui/screens/CombatScreen.d.ts +43 -0
- package/dist/tui/screens/CombatScreen.d.ts.map +1 -0
- package/dist/tui/screens/CombatScreen.js +125 -0
- package/dist/tui/screens/CombatScreen.js.map +1 -0
- package/dist/tui/screens/DialogScreen.d.ts +53 -0
- package/dist/tui/screens/DialogScreen.d.ts.map +1 -0
- package/dist/tui/screens/DialogScreen.js +90 -0
- package/dist/tui/screens/DialogScreen.js.map +1 -0
- package/dist/tui/screens/DungeonScreen.d.ts +80 -0
- package/dist/tui/screens/DungeonScreen.d.ts.map +1 -0
- package/dist/tui/screens/DungeonScreen.js +317 -0
- package/dist/tui/screens/DungeonScreen.js.map +1 -0
- package/dist/tui/screens/ExploreScreen.d.ts +69 -0
- package/dist/tui/screens/ExploreScreen.d.ts.map +1 -0
- package/dist/tui/screens/ExploreScreen.js +224 -0
- package/dist/tui/screens/ExploreScreen.js.map +1 -0
- package/dist/tui/screens/SectionScreen.d.ts +84 -0
- package/dist/tui/screens/SectionScreen.d.ts.map +1 -0
- package/dist/tui/screens/SectionScreen.js +156 -0
- package/dist/tui/screens/SectionScreen.js.map +1 -0
- package/dist/tui/screens/TitleScreen.d.ts +40 -0
- package/dist/tui/screens/TitleScreen.d.ts.map +1 -0
- package/dist/tui/screens/TitleScreen.js +253 -0
- package/dist/tui/screens/TitleScreen.js.map +1 -0
- package/dist/tui/screens/TownScreen.d.ts +98 -0
- package/dist/tui/screens/TownScreen.d.ts.map +1 -0
- package/dist/tui/screens/TownScreen.js +370 -0
- package/dist/tui/screens/TownScreen.js.map +1 -0
- package/dist/tui/screens/TravelScreen.d.ts +67 -0
- package/dist/tui/screens/TravelScreen.d.ts.map +1 -0
- package/dist/tui/screens/TravelScreen.js +286 -0
- package/dist/tui/screens/TravelScreen.js.map +1 -0
- package/dist/tui/screens/index.d.ts +8 -0
- package/dist/tui/screens/index.d.ts.map +1 -0
- package/dist/tui/screens/index.js +17 -0
- package/dist/tui/screens/index.js.map +1 -0
- package/dist/tui/sections/ActionsSection.d.ts +71 -0
- package/dist/tui/sections/ActionsSection.d.ts.map +1 -0
- package/dist/tui/sections/ActionsSection.js +184 -0
- package/dist/tui/sections/ActionsSection.js.map +1 -0
- package/dist/tui/sections/DungeonSection.d.ts +65 -0
- package/dist/tui/sections/DungeonSection.d.ts.map +1 -0
- package/dist/tui/sections/DungeonSection.js +144 -0
- package/dist/tui/sections/DungeonSection.js.map +1 -0
- package/dist/tui/sections/EventsSection.d.ts +50 -0
- package/dist/tui/sections/EventsSection.d.ts.map +1 -0
- package/dist/tui/sections/EventsSection.js +134 -0
- package/dist/tui/sections/EventsSection.js.map +1 -0
- package/dist/tui/sections/MapSection.d.ts +66 -0
- package/dist/tui/sections/MapSection.d.ts.map +1 -0
- package/dist/tui/sections/MapSection.js +669 -0
- package/dist/tui/sections/MapSection.js.map +1 -0
- package/dist/tui/sections/StatusSection.d.ts +47 -0
- package/dist/tui/sections/StatusSection.d.ts.map +1 -0
- package/dist/tui/sections/StatusSection.js +133 -0
- package/dist/tui/sections/StatusSection.js.map +1 -0
- package/dist/tui/sections/TeamSection.d.ts +71 -0
- package/dist/tui/sections/TeamSection.d.ts.map +1 -0
- package/dist/tui/sections/TeamSection.js +224 -0
- package/dist/tui/sections/TeamSection.js.map +1 -0
- package/dist/tui/sections/TravelingSection.d.ts +51 -0
- package/dist/tui/sections/TravelingSection.d.ts.map +1 -0
- package/dist/tui/sections/TravelingSection.js +106 -0
- package/dist/tui/sections/TravelingSection.js.map +1 -0
- package/dist/tui/sections/index.d.ts +9 -0
- package/dist/tui/sections/index.d.ts.map +1 -0
- package/dist/tui/sections/index.js +12 -0
- package/dist/tui/sections/index.js.map +1 -0
- package/dist/ui/Terminal.d.ts +68 -0
- package/dist/ui/Terminal.d.ts.map +1 -0
- package/dist/ui/Terminal.js +297 -0
- package/dist/ui/Terminal.js.map +1 -0
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +8 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/utils/configMigration.d.ts +14 -0
- package/dist/utils/configMigration.d.ts.map +1 -0
- package/dist/utils/configMigration.js +92 -0
- package/dist/utils/configMigration.js.map +1 -0
- package/dist/utils/errorHandler.d.ts +86 -0
- package/dist/utils/errorHandler.d.ts.map +1 -0
- package/dist/utils/errorHandler.js +224 -0
- package/dist/utils/errorHandler.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +43 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/weapon/WeaponFactory.d.ts +32 -0
- package/dist/weapon/WeaponFactory.d.ts.map +1 -0
- package/dist/weapon/WeaponFactory.js +216 -0
- package/dist/weapon/WeaponFactory.js.map +1 -0
- package/dist/weapon/index.d.ts +5 -0
- package/dist/weapon/index.d.ts.map +1 -0
- package/dist/weapon/index.js +8 -0
- package/dist/weapon/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Executor
|
|
3
|
+
* Executes strategy decisions during gameplay based on the StrategyStateMachine
|
|
4
|
+
*
|
|
5
|
+
* This module makes deterministic decisions based on the parsed strategy.
|
|
6
|
+
* No AI calls are made during execution - all decisions are rule-based.
|
|
7
|
+
*/
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Strategy Executor Class
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8ed6e56f-0034-5738-834a-4c2faf22ce66")}catch(e){}}();
|
|
13
|
+
export class StrategyExecutor {
|
|
14
|
+
strategy;
|
|
15
|
+
constructor(strategy) {
|
|
16
|
+
this.strategy = strategy;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Update the current strategy
|
|
20
|
+
*/
|
|
21
|
+
setStrategy(strategy) {
|
|
22
|
+
this.strategy = strategy;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the current strategy
|
|
26
|
+
*/
|
|
27
|
+
getStrategy() {
|
|
28
|
+
return this.strategy;
|
|
29
|
+
}
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Combat Decisions
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Decide combat action based on current context
|
|
35
|
+
*/
|
|
36
|
+
decideCombatAction(context) {
|
|
37
|
+
const { player, enemies, turn, isBossFight, inventory } = context;
|
|
38
|
+
const combat = this.strategy.combat;
|
|
39
|
+
// Check retreat condition first
|
|
40
|
+
if (this.shouldRetreat(player, isBossFight)) {
|
|
41
|
+
return {
|
|
42
|
+
action: 'retreat',
|
|
43
|
+
reason: `HP (${Math.round(player.hp / player.maxHp * 100)}%) below retreat threshold`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Check if we should use an item
|
|
47
|
+
const itemDecision = this.shouldUseItemInCombat(player, enemies, turn, inventory);
|
|
48
|
+
if (itemDecision.shouldUse && itemDecision.itemId) {
|
|
49
|
+
return {
|
|
50
|
+
action: 'item',
|
|
51
|
+
itemId: itemDecision.itemId,
|
|
52
|
+
reason: itemDecision.reason,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Select target based on priority
|
|
56
|
+
const target = this.selectTarget(enemies, combat);
|
|
57
|
+
return {
|
|
58
|
+
action: 'attack',
|
|
59
|
+
targetId: target?.id,
|
|
60
|
+
reason: `Targeting ${target?.name || 'enemy'} based on priority: ${combat.targetPriority[0]}`,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if should retreat from combat
|
|
65
|
+
*/
|
|
66
|
+
shouldRetreat(player, isBossFight) {
|
|
67
|
+
const retreat = this.strategy.combat.retreatCondition;
|
|
68
|
+
if (!retreat.enabled)
|
|
69
|
+
return false;
|
|
70
|
+
if (isBossFight && retreat.bossExempt)
|
|
71
|
+
return false;
|
|
72
|
+
const hpPercent = player.hp / player.maxHp;
|
|
73
|
+
return hpPercent < retreat.hpThreshold;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if should use an item in combat
|
|
77
|
+
*/
|
|
78
|
+
shouldUseItemInCombat(player, enemies, turn, inventory) {
|
|
79
|
+
const rules = this.strategy.combat.itemUsage
|
|
80
|
+
.slice()
|
|
81
|
+
.sort((a, b) => b.priority - a.priority);
|
|
82
|
+
for (const rule of rules) {
|
|
83
|
+
let shouldUse = false;
|
|
84
|
+
let reason = '';
|
|
85
|
+
switch (rule.condition) {
|
|
86
|
+
case 'hp_below':
|
|
87
|
+
shouldUse = player.hp / player.maxHp < rule.threshold;
|
|
88
|
+
reason = `HP below ${rule.threshold * 100}%`;
|
|
89
|
+
break;
|
|
90
|
+
case 'mp_below':
|
|
91
|
+
shouldUse = player.mp / player.maxMp < rule.threshold;
|
|
92
|
+
reason = `MP below ${rule.threshold * 100}%`;
|
|
93
|
+
break;
|
|
94
|
+
case 'enemy_count':
|
|
95
|
+
shouldUse = enemies.length >= rule.threshold;
|
|
96
|
+
reason = `${enemies.length} enemies present`;
|
|
97
|
+
break;
|
|
98
|
+
case 'turn_count':
|
|
99
|
+
shouldUse = turn === rule.threshold;
|
|
100
|
+
reason = `Turn ${turn}`;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
if (shouldUse) {
|
|
104
|
+
// Find matching item in inventory
|
|
105
|
+
const item = this.findItemByType(inventory, rule.itemType);
|
|
106
|
+
if (item) {
|
|
107
|
+
return {
|
|
108
|
+
shouldUse: true,
|
|
109
|
+
itemId: item.id,
|
|
110
|
+
itemType: rule.itemType,
|
|
111
|
+
reason: `Using ${rule.itemType}: ${reason}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { shouldUse: false, reason: 'No item use conditions met' };
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Select target based on priority
|
|
120
|
+
*/
|
|
121
|
+
selectTarget(enemies, combat) {
|
|
122
|
+
if (enemies.length === 0)
|
|
123
|
+
return null;
|
|
124
|
+
// Filter alive enemies
|
|
125
|
+
const alive = enemies.filter(e => e.hp > 0);
|
|
126
|
+
if (alive.length === 0)
|
|
127
|
+
return null;
|
|
128
|
+
// Try each priority in order
|
|
129
|
+
for (const priority of combat.targetPriority) {
|
|
130
|
+
const target = this.findTargetByPriority(alive, priority);
|
|
131
|
+
if (target)
|
|
132
|
+
return target;
|
|
133
|
+
}
|
|
134
|
+
// Fallback to focus target strategy
|
|
135
|
+
return this.selectByFocusTarget(alive, combat.focusTarget);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Find target matching priority type
|
|
139
|
+
*/
|
|
140
|
+
findTargetByPriority(enemies, priority) {
|
|
141
|
+
switch (priority) {
|
|
142
|
+
case 'healer':
|
|
143
|
+
return enemies.find(e => this.isEnemyType(e, 'healer')) || null;
|
|
144
|
+
case 'caster':
|
|
145
|
+
return enemies.find(e => this.isEnemyType(e, 'caster')) || null;
|
|
146
|
+
case 'ranged':
|
|
147
|
+
return enemies.find(e => this.isEnemyType(e, 'ranged')) || null;
|
|
148
|
+
case 'tank':
|
|
149
|
+
return enemies.find(e => this.isEnemyType(e, 'tank')) || null;
|
|
150
|
+
case 'boss':
|
|
151
|
+
return enemies.find(e => e.isBoss) || null;
|
|
152
|
+
case 'minion':
|
|
153
|
+
return enemies.find(e => !e.isBoss) || null;
|
|
154
|
+
case 'lowest_hp':
|
|
155
|
+
return enemies.reduce((min, e) => e.hp < min.hp ? e : min);
|
|
156
|
+
case 'highest_damage':
|
|
157
|
+
return enemies.reduce((max, e) => e.attack > max.attack ? e : max);
|
|
158
|
+
default:
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Select target by focus strategy
|
|
164
|
+
*/
|
|
165
|
+
selectByFocusTarget(enemies, focus) {
|
|
166
|
+
switch (focus) {
|
|
167
|
+
case 'lowest_hp':
|
|
168
|
+
return enemies.reduce((min, e) => e.hp < min.hp ? e : min);
|
|
169
|
+
case 'highest_damage':
|
|
170
|
+
return enemies.reduce((max, e) => e.attack > max.attack ? e : max);
|
|
171
|
+
case 'highest_threat':
|
|
172
|
+
// Threat = attack * (hp / maxHp)
|
|
173
|
+
return enemies.reduce((max, e) => {
|
|
174
|
+
const threat = e.attack * (e.hp / e.maxHp);
|
|
175
|
+
const maxThreat = max.attack * (max.hp / max.maxHp);
|
|
176
|
+
return threat > maxThreat ? e : max;
|
|
177
|
+
});
|
|
178
|
+
case 'random':
|
|
179
|
+
default:
|
|
180
|
+
return enemies[Math.floor(Math.random() * enemies.length)];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check enemy type based on name/abilities
|
|
185
|
+
*/
|
|
186
|
+
isEnemyType(enemy, type) {
|
|
187
|
+
const name = enemy.name.toLowerCase();
|
|
188
|
+
const abilities = enemy.abilities?.map(a => a.name.toLowerCase()) || [];
|
|
189
|
+
switch (type) {
|
|
190
|
+
case 'healer':
|
|
191
|
+
return name.includes('healer') || name.includes('priest') ||
|
|
192
|
+
abilities.some(a => a.includes('heal'));
|
|
193
|
+
case 'caster':
|
|
194
|
+
return name.includes('mage') || name.includes('wizard') ||
|
|
195
|
+
name.includes('sorcerer');
|
|
196
|
+
case 'ranged':
|
|
197
|
+
return name.includes('archer') || name.includes('ranger') ||
|
|
198
|
+
name.includes('shooter');
|
|
199
|
+
case 'tank':
|
|
200
|
+
return name.includes('knight') || name.includes('guardian') ||
|
|
201
|
+
name.includes('tank');
|
|
202
|
+
default:
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// Exploration Decisions
|
|
208
|
+
// ============================================================================
|
|
209
|
+
/**
|
|
210
|
+
* Decide exploration action
|
|
211
|
+
*/
|
|
212
|
+
decideExplorationAction(context) {
|
|
213
|
+
const { currentRoom, availableRooms, exploredRooms, player } = context;
|
|
214
|
+
const exploration = this.strategy.exploration;
|
|
215
|
+
// Check if should rest
|
|
216
|
+
const hpPercent = player.hp / player.maxHp;
|
|
217
|
+
if (hpPercent < exploration.restThreshold && this.canRestInRoom(currentRoom)) {
|
|
218
|
+
return {
|
|
219
|
+
action: 'rest',
|
|
220
|
+
reason: `HP (${Math.round(hpPercent * 100)}%) below rest threshold`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Handle dead end
|
|
224
|
+
if (availableRooms.length === 0 || this.isDeadEnd(currentRoom, availableRooms, exploredRooms)) {
|
|
225
|
+
return this.handleDeadEnd(currentRoom, player);
|
|
226
|
+
}
|
|
227
|
+
// Filter rooms based on strategy
|
|
228
|
+
let candidates = availableRooms.filter(room => !exploredRooms.includes(room.id));
|
|
229
|
+
// Apply avoidance rules
|
|
230
|
+
if (exploration.avoidTraps) {
|
|
231
|
+
candidates = candidates.filter(r => r.type !== 'trap');
|
|
232
|
+
}
|
|
233
|
+
if (exploration.avoidElites) {
|
|
234
|
+
candidates = candidates.filter(r => r.type !== 'elite');
|
|
235
|
+
}
|
|
236
|
+
// If no unexplored rooms, consider explored ones
|
|
237
|
+
if (candidates.length === 0) {
|
|
238
|
+
candidates = availableRooms;
|
|
239
|
+
}
|
|
240
|
+
// Select room based on priority
|
|
241
|
+
const targetRoom = this.selectRoomByPriority(candidates, exploration);
|
|
242
|
+
if (targetRoom) {
|
|
243
|
+
return {
|
|
244
|
+
action: 'move',
|
|
245
|
+
targetRoomId: targetRoom.id,
|
|
246
|
+
reason: `Moving to ${targetRoom.type} room (priority: ${exploration.roomPriority[0]})`,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
// No valid room found, search current room
|
|
250
|
+
return {
|
|
251
|
+
action: 'search',
|
|
252
|
+
reason: 'No valid rooms to explore, searching current room',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Check if current position is a dead end
|
|
257
|
+
*/
|
|
258
|
+
isDeadEnd(currentRoom, availableRooms, exploredRooms) {
|
|
259
|
+
const unexplored = availableRooms.filter(r => !exploredRooms.includes(r.id));
|
|
260
|
+
return unexplored.length === 0 && currentRoom.type !== 'exit';
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Handle dead end based on strategy
|
|
264
|
+
*/
|
|
265
|
+
handleDeadEnd(currentRoom, player) {
|
|
266
|
+
const behavior = this.strategy.exploration.deadEndBehavior;
|
|
267
|
+
switch (behavior) {
|
|
268
|
+
case 'retreat_immediately':
|
|
269
|
+
return {
|
|
270
|
+
action: 'retreat',
|
|
271
|
+
reason: 'Dead end - retreating immediately',
|
|
272
|
+
};
|
|
273
|
+
case 'search_thoroughly':
|
|
274
|
+
return {
|
|
275
|
+
action: 'search',
|
|
276
|
+
reason: 'Dead end - searching for hidden passages',
|
|
277
|
+
};
|
|
278
|
+
case 'rest_if_needed':
|
|
279
|
+
const hpPercent = player.hp / player.maxHp;
|
|
280
|
+
if (hpPercent < 0.8 && this.canRestInRoom(currentRoom)) {
|
|
281
|
+
return {
|
|
282
|
+
action: 'rest',
|
|
283
|
+
reason: 'Dead end - resting before retreat',
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
action: 'retreat',
|
|
288
|
+
reason: 'Dead end - retreating after rest check',
|
|
289
|
+
};
|
|
290
|
+
default:
|
|
291
|
+
return {
|
|
292
|
+
action: 'retreat',
|
|
293
|
+
reason: 'Dead end - retreating',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if can rest in current room
|
|
299
|
+
*/
|
|
300
|
+
canRestInRoom(room) {
|
|
301
|
+
const restableTypes = ['rest', 'safe_room', 'fountain', 'entrance'];
|
|
302
|
+
return restableTypes.includes(room.type);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Select room based on priority
|
|
306
|
+
*/
|
|
307
|
+
selectRoomByPriority(rooms, exploration) {
|
|
308
|
+
if (rooms.length === 0)
|
|
309
|
+
return null;
|
|
310
|
+
// Map room types to priorities
|
|
311
|
+
const typeToRoomPriority = {
|
|
312
|
+
combat: 'combat',
|
|
313
|
+
elite: 'combat',
|
|
314
|
+
boss: 'combat',
|
|
315
|
+
ambush: 'combat',
|
|
316
|
+
treasure: 'treasure',
|
|
317
|
+
event: 'event',
|
|
318
|
+
encounter: 'event',
|
|
319
|
+
shop: 'shop',
|
|
320
|
+
rest: 'rest',
|
|
321
|
+
safe_room: 'rest',
|
|
322
|
+
fountain: 'rest',
|
|
323
|
+
altar: 'event',
|
|
324
|
+
exit: 'exit',
|
|
325
|
+
entrance: null,
|
|
326
|
+
dead_end: null,
|
|
327
|
+
trap: 'event',
|
|
328
|
+
puzzle: 'event',
|
|
329
|
+
empty: null,
|
|
330
|
+
};
|
|
331
|
+
// Score each room
|
|
332
|
+
const scored = rooms.map(room => {
|
|
333
|
+
const roomPriority = typeToRoomPriority[room.type];
|
|
334
|
+
const priorityIndex = roomPriority
|
|
335
|
+
? exploration.roomPriority.indexOf(roomPriority)
|
|
336
|
+
: -1;
|
|
337
|
+
return {
|
|
338
|
+
room,
|
|
339
|
+
score: priorityIndex === -1 ? 999 : priorityIndex,
|
|
340
|
+
};
|
|
341
|
+
});
|
|
342
|
+
// Sort by score (lower is better)
|
|
343
|
+
scored.sort((a, b) => a.score - b.score);
|
|
344
|
+
return scored[0]?.room || null;
|
|
345
|
+
}
|
|
346
|
+
// ============================================================================
|
|
347
|
+
// Encounter Decisions
|
|
348
|
+
// ============================================================================
|
|
349
|
+
/**
|
|
350
|
+
* Decide encounter action
|
|
351
|
+
*/
|
|
352
|
+
decideEncounterAction(context) {
|
|
353
|
+
const encounter = this.strategy.encounter;
|
|
354
|
+
switch (context.type) {
|
|
355
|
+
case 'npc':
|
|
356
|
+
return this.decideNPCAction(context.npc, encounter);
|
|
357
|
+
case 'event':
|
|
358
|
+
return this.decideEventAction(context.event, context.riskLevel, encounter);
|
|
359
|
+
case 'shop':
|
|
360
|
+
return this.decideShopAction(encounter);
|
|
361
|
+
case 'trap':
|
|
362
|
+
case 'puzzle':
|
|
363
|
+
return {
|
|
364
|
+
action: this.strategy.exploration.avoidTraps ? 'skip' : 'engage',
|
|
365
|
+
reason: this.strategy.exploration.avoidTraps
|
|
366
|
+
? 'Avoiding traps per strategy'
|
|
367
|
+
: 'Engaging trap/puzzle',
|
|
368
|
+
};
|
|
369
|
+
default:
|
|
370
|
+
return { action: 'skip', reason: 'Unknown encounter type' };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Decide NPC interaction
|
|
375
|
+
*/
|
|
376
|
+
decideNPCAction(npc, encounter) {
|
|
377
|
+
switch (encounter.npcBehavior) {
|
|
378
|
+
case 'always_talk':
|
|
379
|
+
return { action: 'engage', reason: 'Always talking to NPCs' };
|
|
380
|
+
case 'quest_givers_only':
|
|
381
|
+
if (npc?.type === 'quest_giver' || (npc?.quests && npc.quests.length > 0)) {
|
|
382
|
+
return { action: 'engage', reason: 'NPC is a quest giver' };
|
|
383
|
+
}
|
|
384
|
+
return { action: 'skip', reason: 'NPC is not a quest giver' };
|
|
385
|
+
case 'skip':
|
|
386
|
+
return { action: 'skip', reason: 'Skipping NPC interactions' };
|
|
387
|
+
default:
|
|
388
|
+
return { action: 'engage', reason: 'Default NPC behavior' };
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Decide event action
|
|
393
|
+
*/
|
|
394
|
+
decideEventAction(event, riskLevel = 0.5, encounter) {
|
|
395
|
+
if (riskLevel <= encounter.eventRiskTolerance) {
|
|
396
|
+
return {
|
|
397
|
+
action: 'engage',
|
|
398
|
+
reason: `Event risk (${riskLevel}) within tolerance (${encounter.eventRiskTolerance})`,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
action: 'skip',
|
|
403
|
+
reason: `Event risk (${riskLevel}) exceeds tolerance (${encounter.eventRiskTolerance})`,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Decide shop action
|
|
408
|
+
*/
|
|
409
|
+
decideShopAction(encounter) {
|
|
410
|
+
switch (encounter.shopBehavior) {
|
|
411
|
+
case 'buy_upgrades':
|
|
412
|
+
return { action: 'buy', reason: 'Looking for equipment upgrades' };
|
|
413
|
+
case 'buy_consumables':
|
|
414
|
+
return { action: 'buy', reason: 'Buying consumables' };
|
|
415
|
+
case 'sell_only':
|
|
416
|
+
return { action: 'sell', reason: 'Only selling items' };
|
|
417
|
+
case 'skip':
|
|
418
|
+
return { action: 'skip', reason: 'Skipping shop' };
|
|
419
|
+
default:
|
|
420
|
+
return { action: 'engage', reason: 'Default shop behavior' };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// ============================================================================
|
|
424
|
+
// Resource Decisions
|
|
425
|
+
// ============================================================================
|
|
426
|
+
/**
|
|
427
|
+
* Check if should take resource action (outside combat)
|
|
428
|
+
*/
|
|
429
|
+
checkResourceAction(player) {
|
|
430
|
+
const resource = this.strategy.resource;
|
|
431
|
+
// Check HP
|
|
432
|
+
const hpPercent = player.hp / player.maxHp;
|
|
433
|
+
if (hpPercent < resource.hpThreshold) {
|
|
434
|
+
return {
|
|
435
|
+
action: resource.hpAction,
|
|
436
|
+
reason: `HP (${Math.round(hpPercent * 100)}%) below threshold (${resource.hpThreshold * 100}%)`,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
// Check MP
|
|
440
|
+
const mpPercent = player.mp / player.maxMp;
|
|
441
|
+
if (mpPercent < resource.mpThreshold) {
|
|
442
|
+
return {
|
|
443
|
+
action: resource.mpAction,
|
|
444
|
+
reason: `MP (${Math.round(mpPercent * 100)}%) below threshold (${resource.mpThreshold * 100}%)`,
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
return { action: null, reason: 'No resource action needed' };
|
|
448
|
+
}
|
|
449
|
+
// ============================================================================
|
|
450
|
+
// Utility
|
|
451
|
+
// ============================================================================
|
|
452
|
+
/**
|
|
453
|
+
* Find item by type in inventory
|
|
454
|
+
*/
|
|
455
|
+
findItemByType(inventory, itemType) {
|
|
456
|
+
const typeMap = {
|
|
457
|
+
health_potion: ['health', 'healing', 'hp', 'potion'],
|
|
458
|
+
mana_potion: ['mana', 'mp', 'magic'],
|
|
459
|
+
buff: ['buff', 'boost', 'enhance'],
|
|
460
|
+
debuff: ['debuff', 'weaken', 'curse'],
|
|
461
|
+
revive: ['revive', 'phoenix', 'resurrection'],
|
|
462
|
+
};
|
|
463
|
+
const keywords = typeMap[itemType] || [itemType];
|
|
464
|
+
return inventory.find(item => item.type === 'consumable' &&
|
|
465
|
+
item.quantity > 0 &&
|
|
466
|
+
keywords.some(k => item.name.toLowerCase().includes(k))) || null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// ============================================================================
|
|
470
|
+
// Factory
|
|
471
|
+
// ============================================================================
|
|
472
|
+
/**
|
|
473
|
+
* Create a strategy executor with the given strategy
|
|
474
|
+
*/
|
|
475
|
+
export function createStrategyExecutor(strategy) {
|
|
476
|
+
return new StrategyExecutor(strategy);
|
|
477
|
+
}
|
|
478
|
+
//# sourceMappingURL=StrategyExecutor.js.map
|
|
479
|
+
//# debugId=8ed6e56f-0034-5738-834a-4c2faf22ce66
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrategyExecutor.js","sources":["strategy/StrategyExecutor.ts"],"sourceRoot":"/","sourcesContent":["/**\r\n * Strategy Executor\r\n * Executes strategy decisions during gameplay based on the StrategyStateMachine\r\n *\r\n * This module makes deterministic decisions based on the parsed strategy.\r\n * No AI calls are made during execution - all decisions are rule-based.\r\n */\r\n\r\nimport type {\r\n StrategyStateMachine,\r\n CombatStrategyConfig,\r\n ExplorationStrategy,\r\n ResourceStrategy,\r\n EncounterStrategy,\r\n Enemy,\r\n DungeonRoom,\r\n DungeonRoomType,\r\n InventoryItem,\r\n TargetPriority,\r\n RoomPriority,\r\n Player,\r\n NPC,\r\n GameEvent,\r\n} from '../core/types.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface CombatContext {\r\n player: {\r\n hp: number;\r\n maxHp: number;\r\n mp: number;\r\n maxMp: number;\r\n };\r\n enemies: Enemy[];\r\n turn: number;\r\n isBossFight: boolean;\r\n inventory: InventoryItem[];\r\n}\r\n\r\nexport interface ExplorationContext {\r\n currentRoom: DungeonRoom;\r\n availableRooms: DungeonRoom[];\r\n exploredRooms: string[];\r\n player: {\r\n hp: number;\r\n maxHp: number;\r\n mp: number;\r\n maxMp: number;\r\n };\r\n}\r\n\r\nexport interface EncounterContext {\r\n type: 'npc' | 'event' | 'shop' | 'trap' | 'puzzle';\r\n npc?: NPC;\r\n event?: GameEvent;\r\n riskLevel?: number;\r\n}\r\n\r\nexport interface CombatDecision {\r\n action: 'attack' | 'skill' | 'item' | 'retreat' | 'defend';\r\n targetId?: string;\r\n itemId?: string;\r\n skillId?: string;\r\n reason: string;\r\n}\r\n\r\nexport interface ExplorationDecision {\r\n action: 'move' | 'rest' | 'search' | 'retreat';\r\n targetRoomId?: string;\r\n reason: string;\r\n}\r\n\r\nexport interface EncounterDecision {\r\n action: 'engage' | 'skip' | 'buy' | 'sell' | 'accept' | 'decline';\r\n itemId?: string;\r\n questId?: string;\r\n reason: string;\r\n}\r\n\r\nexport interface ItemUseDecision {\r\n shouldUse: boolean;\r\n itemId?: string;\r\n itemType?: string;\r\n reason: string;\r\n}\r\n\r\n// ============================================================================\r\n// Strategy Executor Class\r\n// ============================================================================\r\n\r\nexport class StrategyExecutor {\r\n private strategy: StrategyStateMachine;\r\n\r\n constructor(strategy: StrategyStateMachine) {\r\n this.strategy = strategy;\r\n }\r\n\r\n /**\r\n * Update the current strategy\r\n */\r\n setStrategy(strategy: StrategyStateMachine): void {\r\n this.strategy = strategy;\r\n }\r\n\r\n /**\r\n * Get the current strategy\r\n */\r\n getStrategy(): StrategyStateMachine {\r\n return this.strategy;\r\n }\r\n\r\n // ============================================================================\r\n // Combat Decisions\r\n // ============================================================================\r\n\r\n /**\r\n * Decide combat action based on current context\r\n */\r\n decideCombatAction(context: CombatContext): CombatDecision {\r\n const { player, enemies, turn, isBossFight, inventory } = context;\r\n const combat = this.strategy.combat;\r\n\r\n // Check retreat condition first\r\n if (this.shouldRetreat(player, isBossFight)) {\r\n return {\r\n action: 'retreat',\r\n reason: `HP (${Math.round(player.hp / player.maxHp * 100)}%) below retreat threshold`,\r\n };\r\n }\r\n\r\n // Check if we should use an item\r\n const itemDecision = this.shouldUseItemInCombat(player, enemies, turn, inventory);\r\n if (itemDecision.shouldUse && itemDecision.itemId) {\r\n return {\r\n action: 'item',\r\n itemId: itemDecision.itemId,\r\n reason: itemDecision.reason,\r\n };\r\n }\r\n\r\n // Select target based on priority\r\n const target = this.selectTarget(enemies, combat);\r\n\r\n return {\r\n action: 'attack',\r\n targetId: target?.id,\r\n reason: `Targeting ${target?.name || 'enemy'} based on priority: ${combat.targetPriority[0]}`,\r\n };\r\n }\r\n\r\n /**\r\n * Check if should retreat from combat\r\n */\r\n private shouldRetreat(player: { hp: number; maxHp: number }, isBossFight: boolean): boolean {\r\n const retreat = this.strategy.combat.retreatCondition;\r\n\r\n if (!retreat.enabled) return false;\r\n if (isBossFight && retreat.bossExempt) return false;\r\n\r\n const hpPercent = player.hp / player.maxHp;\r\n return hpPercent < retreat.hpThreshold;\r\n }\r\n\r\n /**\r\n * Check if should use an item in combat\r\n */\r\n private shouldUseItemInCombat(\r\n player: { hp: number; maxHp: number; mp: number; maxMp: number },\r\n enemies: Enemy[],\r\n turn: number,\r\n inventory: InventoryItem[]\r\n ): ItemUseDecision {\r\n const rules = this.strategy.combat.itemUsage\r\n .slice()\r\n .sort((a, b) => b.priority - a.priority);\r\n\r\n for (const rule of rules) {\r\n let shouldUse = false;\r\n let reason = '';\r\n\r\n switch (rule.condition) {\r\n case 'hp_below':\r\n shouldUse = player.hp / player.maxHp < rule.threshold;\r\n reason = `HP below ${rule.threshold * 100}%`;\r\n break;\r\n case 'mp_below':\r\n shouldUse = player.mp / player.maxMp < rule.threshold;\r\n reason = `MP below ${rule.threshold * 100}%`;\r\n break;\r\n case 'enemy_count':\r\n shouldUse = enemies.length >= rule.threshold;\r\n reason = `${enemies.length} enemies present`;\r\n break;\r\n case 'turn_count':\r\n shouldUse = turn === rule.threshold;\r\n reason = `Turn ${turn}`;\r\n break;\r\n }\r\n\r\n if (shouldUse) {\r\n // Find matching item in inventory\r\n const item = this.findItemByType(inventory, rule.itemType);\r\n if (item) {\r\n return {\r\n shouldUse: true,\r\n itemId: item.id,\r\n itemType: rule.itemType,\r\n reason: `Using ${rule.itemType}: ${reason}`,\r\n };\r\n }\r\n }\r\n }\r\n\r\n return { shouldUse: false, reason: 'No item use conditions met' };\r\n }\r\n\r\n /**\r\n * Select target based on priority\r\n */\r\n private selectTarget(enemies: Enemy[], combat: CombatStrategyConfig): Enemy | null {\r\n if (enemies.length === 0) return null;\r\n\r\n // Filter alive enemies\r\n const alive = enemies.filter(e => e.hp > 0);\r\n if (alive.length === 0) return null;\r\n\r\n // Try each priority in order\r\n for (const priority of combat.targetPriority) {\r\n const target = this.findTargetByPriority(alive, priority);\r\n if (target) return target;\r\n }\r\n\r\n // Fallback to focus target strategy\r\n return this.selectByFocusTarget(alive, combat.focusTarget);\r\n }\r\n\r\n /**\r\n * Find target matching priority type\r\n */\r\n private findTargetByPriority(enemies: Enemy[], priority: TargetPriority): Enemy | null {\r\n switch (priority) {\r\n case 'healer':\r\n return enemies.find(e => this.isEnemyType(e, 'healer')) || null;\r\n case 'caster':\r\n return enemies.find(e => this.isEnemyType(e, 'caster')) || null;\r\n case 'ranged':\r\n return enemies.find(e => this.isEnemyType(e, 'ranged')) || null;\r\n case 'tank':\r\n return enemies.find(e => this.isEnemyType(e, 'tank')) || null;\r\n case 'boss':\r\n return enemies.find(e => e.isBoss) || null;\r\n case 'minion':\r\n return enemies.find(e => !e.isBoss) || null;\r\n case 'lowest_hp':\r\n return enemies.reduce((min, e) => e.hp < min.hp ? e : min);\r\n case 'highest_damage':\r\n return enemies.reduce((max, e) => e.attack > max.attack ? e : max);\r\n default:\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Select target by focus strategy\r\n */\r\n private selectByFocusTarget(\r\n enemies: Enemy[],\r\n focus: CombatStrategyConfig['focusTarget']\r\n ): Enemy {\r\n switch (focus) {\r\n case 'lowest_hp':\r\n return enemies.reduce((min, e) => e.hp < min.hp ? e : min);\r\n case 'highest_damage':\r\n return enemies.reduce((max, e) => e.attack > max.attack ? e : max);\r\n case 'highest_threat':\r\n // Threat = attack * (hp / maxHp)\r\n return enemies.reduce((max, e) => {\r\n const threat = e.attack * (e.hp / e.maxHp);\r\n const maxThreat = max.attack * (max.hp / max.maxHp);\r\n return threat > maxThreat ? e : max;\r\n });\r\n case 'random':\r\n default:\r\n return enemies[Math.floor(Math.random() * enemies.length)];\r\n }\r\n }\r\n\r\n /**\r\n * Check enemy type based on name/abilities\r\n */\r\n private isEnemyType(enemy: Enemy, type: string): boolean {\r\n const name = enemy.name.toLowerCase();\r\n const abilities = enemy.abilities?.map(a => a.name.toLowerCase()) || [];\r\n\r\n switch (type) {\r\n case 'healer':\r\n return name.includes('healer') || name.includes('priest') ||\r\n abilities.some(a => a.includes('heal'));\r\n case 'caster':\r\n return name.includes('mage') || name.includes('wizard') ||\r\n name.includes('sorcerer');\r\n case 'ranged':\r\n return name.includes('archer') || name.includes('ranger') ||\r\n name.includes('shooter');\r\n case 'tank':\r\n return name.includes('knight') || name.includes('guardian') ||\r\n name.includes('tank');\r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // Exploration Decisions\r\n // ============================================================================\r\n\r\n /**\r\n * Decide exploration action\r\n */\r\n decideExplorationAction(context: ExplorationContext): ExplorationDecision {\r\n const { currentRoom, availableRooms, exploredRooms, player } = context;\r\n const exploration = this.strategy.exploration;\r\n\r\n // Check if should rest\r\n const hpPercent = player.hp / player.maxHp;\r\n if (hpPercent < exploration.restThreshold && this.canRestInRoom(currentRoom)) {\r\n return {\r\n action: 'rest',\r\n reason: `HP (${Math.round(hpPercent * 100)}%) below rest threshold`,\r\n };\r\n }\r\n\r\n // Handle dead end\r\n if (availableRooms.length === 0 || this.isDeadEnd(currentRoom, availableRooms, exploredRooms)) {\r\n return this.handleDeadEnd(currentRoom, player);\r\n }\r\n\r\n // Filter rooms based on strategy\r\n let candidates = availableRooms.filter(room => !exploredRooms.includes(room.id));\r\n\r\n // Apply avoidance rules\r\n if (exploration.avoidTraps) {\r\n candidates = candidates.filter(r => r.type !== 'trap');\r\n }\r\n if (exploration.avoidElites) {\r\n candidates = candidates.filter(r => r.type !== 'elite');\r\n }\r\n\r\n // If no unexplored rooms, consider explored ones\r\n if (candidates.length === 0) {\r\n candidates = availableRooms;\r\n }\r\n\r\n // Select room based on priority\r\n const targetRoom = this.selectRoomByPriority(candidates, exploration);\r\n\r\n if (targetRoom) {\r\n return {\r\n action: 'move',\r\n targetRoomId: targetRoom.id,\r\n reason: `Moving to ${targetRoom.type} room (priority: ${exploration.roomPriority[0]})`,\r\n };\r\n }\r\n\r\n // No valid room found, search current room\r\n return {\r\n action: 'search',\r\n reason: 'No valid rooms to explore, searching current room',\r\n };\r\n }\r\n\r\n /**\r\n * Check if current position is a dead end\r\n */\r\n private isDeadEnd(\r\n currentRoom: DungeonRoom,\r\n availableRooms: DungeonRoom[],\r\n exploredRooms: string[]\r\n ): boolean {\r\n const unexplored = availableRooms.filter(r => !exploredRooms.includes(r.id));\r\n return unexplored.length === 0 && currentRoom.type !== 'exit';\r\n }\r\n\r\n /**\r\n * Handle dead end based on strategy\r\n */\r\n private handleDeadEnd(\r\n currentRoom: DungeonRoom,\r\n player: { hp: number; maxHp: number; mp: number; maxMp: number }\r\n ): ExplorationDecision {\r\n const behavior = this.strategy.exploration.deadEndBehavior;\r\n\r\n switch (behavior) {\r\n case 'retreat_immediately':\r\n return {\r\n action: 'retreat',\r\n reason: 'Dead end - retreating immediately',\r\n };\r\n\r\n case 'search_thoroughly':\r\n return {\r\n action: 'search',\r\n reason: 'Dead end - searching for hidden passages',\r\n };\r\n\r\n case 'rest_if_needed':\r\n const hpPercent = player.hp / player.maxHp;\r\n if (hpPercent < 0.8 && this.canRestInRoom(currentRoom)) {\r\n return {\r\n action: 'rest',\r\n reason: 'Dead end - resting before retreat',\r\n };\r\n }\r\n return {\r\n action: 'retreat',\r\n reason: 'Dead end - retreating after rest check',\r\n };\r\n\r\n default:\r\n return {\r\n action: 'retreat',\r\n reason: 'Dead end - retreating',\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Check if can rest in current room\r\n */\r\n private canRestInRoom(room: DungeonRoom): boolean {\r\n const restableTypes: DungeonRoomType[] = ['rest', 'safe_room', 'fountain', 'entrance'];\r\n return restableTypes.includes(room.type);\r\n }\r\n\r\n /**\r\n * Select room based on priority\r\n */\r\n private selectRoomByPriority(rooms: DungeonRoom[], exploration: ExplorationStrategy): DungeonRoom | null {\r\n if (rooms.length === 0) return null;\r\n\r\n // Map room types to priorities\r\n const typeToRoomPriority: Record<DungeonRoomType, RoomPriority | null> = {\r\n combat: 'combat',\r\n elite: 'combat',\r\n boss: 'combat',\r\n ambush: 'combat',\r\n treasure: 'treasure',\r\n event: 'event',\r\n encounter: 'event',\r\n shop: 'shop',\r\n rest: 'rest',\r\n safe_room: 'rest',\r\n fountain: 'rest',\r\n altar: 'event',\r\n exit: 'exit',\r\n entrance: null,\r\n dead_end: null,\r\n trap: 'event',\r\n puzzle: 'event',\r\n empty: null,\r\n };\r\n\r\n // Score each room\r\n const scored = rooms.map(room => {\r\n const roomPriority = typeToRoomPriority[room.type];\r\n const priorityIndex = roomPriority\r\n ? exploration.roomPriority.indexOf(roomPriority)\r\n : -1;\r\n\r\n return {\r\n room,\r\n score: priorityIndex === -1 ? 999 : priorityIndex,\r\n };\r\n });\r\n\r\n // Sort by score (lower is better)\r\n scored.sort((a, b) => a.score - b.score);\r\n\r\n return scored[0]?.room || null;\r\n }\r\n\r\n // ============================================================================\r\n // Encounter Decisions\r\n // ============================================================================\r\n\r\n /**\r\n * Decide encounter action\r\n */\r\n decideEncounterAction(context: EncounterContext): EncounterDecision {\r\n const encounter = this.strategy.encounter;\r\n\r\n switch (context.type) {\r\n case 'npc':\r\n return this.decideNPCAction(context.npc, encounter);\r\n\r\n case 'event':\r\n return this.decideEventAction(context.event, context.riskLevel, encounter);\r\n\r\n case 'shop':\r\n return this.decideShopAction(encounter);\r\n\r\n case 'trap':\r\n case 'puzzle':\r\n return {\r\n action: this.strategy.exploration.avoidTraps ? 'skip' : 'engage',\r\n reason: this.strategy.exploration.avoidTraps\r\n ? 'Avoiding traps per strategy'\r\n : 'Engaging trap/puzzle',\r\n };\r\n\r\n default:\r\n return { action: 'skip', reason: 'Unknown encounter type' };\r\n }\r\n }\r\n\r\n /**\r\n * Decide NPC interaction\r\n */\r\n private decideNPCAction(npc: NPC | undefined, encounter: EncounterStrategy): EncounterDecision {\r\n switch (encounter.npcBehavior) {\r\n case 'always_talk':\r\n return { action: 'engage', reason: 'Always talking to NPCs' };\r\n\r\n case 'quest_givers_only':\r\n if (npc?.type === 'quest_giver' || (npc?.quests && npc.quests.length > 0)) {\r\n return { action: 'engage', reason: 'NPC is a quest giver' };\r\n }\r\n return { action: 'skip', reason: 'NPC is not a quest giver' };\r\n\r\n case 'skip':\r\n return { action: 'skip', reason: 'Skipping NPC interactions' };\r\n\r\n default:\r\n return { action: 'engage', reason: 'Default NPC behavior' };\r\n }\r\n }\r\n\r\n /**\r\n * Decide event action\r\n */\r\n private decideEventAction(\r\n event: GameEvent | undefined,\r\n riskLevel: number = 0.5,\r\n encounter: EncounterStrategy\r\n ): EncounterDecision {\r\n if (riskLevel <= encounter.eventRiskTolerance) {\r\n return {\r\n action: 'engage',\r\n reason: `Event risk (${riskLevel}) within tolerance (${encounter.eventRiskTolerance})`,\r\n };\r\n }\r\n\r\n return {\r\n action: 'skip',\r\n reason: `Event risk (${riskLevel}) exceeds tolerance (${encounter.eventRiskTolerance})`,\r\n };\r\n }\r\n\r\n /**\r\n * Decide shop action\r\n */\r\n private decideShopAction(encounter: EncounterStrategy): EncounterDecision {\r\n switch (encounter.shopBehavior) {\r\n case 'buy_upgrades':\r\n return { action: 'buy', reason: 'Looking for equipment upgrades' };\r\n\r\n case 'buy_consumables':\r\n return { action: 'buy', reason: 'Buying consumables' };\r\n\r\n case 'sell_only':\r\n return { action: 'sell', reason: 'Only selling items' };\r\n\r\n case 'skip':\r\n return { action: 'skip', reason: 'Skipping shop' };\r\n\r\n default:\r\n return { action: 'engage', reason: 'Default shop behavior' };\r\n }\r\n }\r\n\r\n // ============================================================================\r\n // Resource Decisions\r\n // ============================================================================\r\n\r\n /**\r\n * Check if should take resource action (outside combat)\r\n */\r\n checkResourceAction(player: {\r\n hp: number;\r\n maxHp: number;\r\n mp: number;\r\n maxMp: number;\r\n gold: number;\r\n }): { action: ResourceStrategy['hpAction'] | null; reason: string } {\r\n const resource = this.strategy.resource;\r\n\r\n // Check HP\r\n const hpPercent = player.hp / player.maxHp;\r\n if (hpPercent < resource.hpThreshold) {\r\n return {\r\n action: resource.hpAction,\r\n reason: `HP (${Math.round(hpPercent * 100)}%) below threshold (${resource.hpThreshold * 100}%)`,\r\n };\r\n }\r\n\r\n // Check MP\r\n const mpPercent = player.mp / player.maxMp;\r\n if (mpPercent < resource.mpThreshold) {\r\n return {\r\n action: resource.mpAction,\r\n reason: `MP (${Math.round(mpPercent * 100)}%) below threshold (${resource.mpThreshold * 100}%)`,\r\n };\r\n }\r\n\r\n return { action: null, reason: 'No resource action needed' };\r\n }\r\n\r\n // ============================================================================\r\n // Utility\r\n // ============================================================================\r\n\r\n /**\r\n * Find item by type in inventory\r\n */\r\n private findItemByType(inventory: InventoryItem[], itemType: string): InventoryItem | null {\r\n const typeMap: Record<string, string[]> = {\r\n health_potion: ['health', 'healing', 'hp', 'potion'],\r\n mana_potion: ['mana', 'mp', 'magic'],\r\n buff: ['buff', 'boost', 'enhance'],\r\n debuff: ['debuff', 'weaken', 'curse'],\r\n revive: ['revive', 'phoenix', 'resurrection'],\r\n };\r\n\r\n const keywords = typeMap[itemType] || [itemType];\r\n\r\n return inventory.find(item =>\r\n item.type === 'consumable' &&\r\n item.quantity > 0 &&\r\n keywords.some(k => item.name.toLowerCase().includes(k))\r\n ) || null;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory\r\n// ============================================================================\r\n\r\n/**\r\n * Create a strategy executor with the given strategy\r\n */\r\nexport function createStrategyExecutor(strategy: StrategyStateMachine): StrategyExecutor {\r\n return new StrategyExecutor(strategy);\r\n}\r\n"],"names":[],"mappings":"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","debug_id":"8ed6e56f-0034-5738-834a-4c2faf22ce66"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy Parser
|
|
3
|
+
* Uses AI to parse natural language strategy descriptions into StrategyStateMachine
|
|
4
|
+
*
|
|
5
|
+
* NO FALLBACKS - All AI errors prompt for retry
|
|
6
|
+
*/
|
|
7
|
+
import type { StrategyStateMachine } from '../core/types.js';
|
|
8
|
+
import { type OperationResult } from '../utils/errorHandler.js';
|
|
9
|
+
export interface StrategyParseResult extends OperationResult<StrategyStateMachine> {
|
|
10
|
+
rawResponse?: string;
|
|
11
|
+
parseWarnings?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface StrategyValidationResult {
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
errors: string[];
|
|
16
|
+
warnings: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare class StrategyParser {
|
|
19
|
+
private aiClient;
|
|
20
|
+
private errorHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Parse natural language strategy into StrategyStateMachine
|
|
23
|
+
* Returns error if AI fails - NO FALLBACK
|
|
24
|
+
*/
|
|
25
|
+
parseStrategy(description: string): Promise<StrategyParseResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Parse JSON response from AI
|
|
28
|
+
*/
|
|
29
|
+
private parseJSONResponse;
|
|
30
|
+
/**
|
|
31
|
+
* Validate parsed strategy structure
|
|
32
|
+
*/
|
|
33
|
+
private validateStrategy;
|
|
34
|
+
/**
|
|
35
|
+
* Merge partial strategy with defaults
|
|
36
|
+
*/
|
|
37
|
+
mergeWithDefaults(partial: Partial<StrategyStateMachine>): StrategyStateMachine;
|
|
38
|
+
/**
|
|
39
|
+
* Update a specific part of the strategy via natural language
|
|
40
|
+
*/
|
|
41
|
+
updateStrategyPart(currentStrategy: StrategyStateMachine, updateDescription: string, part: 'combat' | 'exploration' | 'resource' | 'encounter'): Promise<StrategyParseResult>;
|
|
42
|
+
}
|
|
43
|
+
export declare function getStrategyParser(): StrategyParser;
|
|
44
|
+
/**
|
|
45
|
+
* Convert strategy to human-readable description
|
|
46
|
+
*/
|
|
47
|
+
export declare function strategyToDescription(strategy: StrategyStateMachine): string;
|
|
48
|
+
//# sourceMappingURL=StrategyParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StrategyParser.d.ts","sourceRoot":"/","sources":["strategy/StrategyParser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,oBAAoB,EAYrB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,KAAK,eAAe,EAKrB,MAAM,0BAA0B,CAAC;AAOlC,MAAM,WAAW,mBAAoB,SAAQ,eAAe,CAAC,oBAAoB,CAAC;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAyED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,YAAY,CAAqB;IAEzC;;;OAGG;IACG,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAgEtE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqCzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA8CxB;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,oBAAoB;IAS/E;;OAEG;IACG,kBAAkB,CACtB,eAAe,EAAE,oBAAoB,EACrC,iBAAiB,EAAE,MAAM,EACzB,IAAI,EAAE,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,GACxD,OAAO,CAAC,mBAAmB,CAAC;CA2DhC;AAQD,wBAAgB,iBAAiB,IAAI,cAAc,CAKlD;AAMD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,CA4B5E"}
|