# Storyteller - Technical Architecture ## 1. System Overview The game follows a **Client-Server** model where the Godot game client acts as the frontend and state manager, while the LLM (via OpenRouter) acts as the narrative engine and intent parser. ```mermaid graph TD User[User Input] -->|Text| UI[UI Layer] UI -->|Signal| GM[GameManager] GM -->|Context + Input| LLM[LLM Service] LLM -->|OpenRouter API| Cloud[AI Model] Cloud -->|JSON Response| LLM LLM -->|Parsed Action| GM GM -->|Update| State[GameState] State -->|Signal| UI State -->|Signal| Visuals[Visual/Audio System] ``` ## 2. Core Components ### 2.1 LLM Service (`LLMService.gd`) * **Responsibility:** Handles HTTP requests to OpenRouter. * **Pattern:** Adapter pattern to allow future swapping to local LLM (Ollama). * **Key Functions:** * `send_prompt(system_prompt: String, user_input: String) -> Dictionary` * `_parse_json(response: String) -> Dictionary` * **Configuration:** API Key stored in `user://secrets.cfg` (not in version control). ### 2.2 Game Manager (`GameManager.gd`) * **Responsibility:** Central coordinator. * **Logic:** 1. Receives user text. 2. Constructs a prompt including: * Current Room Description. * Visible Items/Enemies. * Player Inventory. * Valid Actions (Rules). 3. Sends to `LLMService`. 4. Executes the returned Action (e.g., `move_player`, `pickup_item`, `start_combat`). ### 2.3 State Manager * **Responsibility:** Single source of truth. * **Implementation:** Godot `Resource` based system for easy saving/loading. ## 3. Data Architecture ### 3.1 Game State (`GameState.gd` - Resource) ```gdscript class_name GameState extends Resource @export var current_room_id: String @export var player_hp: int @export var player_max_hp: int @export var inventory: Array[ItemData] # List of Item Resources @export var world_flags: Dictionary # For tracking puzzle states ``` ### 3.2 Room Data (`RoomData.gd` - Resource) ```gdscript class_name RoomData extends Resource @export var id: String @export var name: String @export var description: String # Base description for LLM context @export var image_path: String # Path to static background @export var exits: Dictionary # { "north": "room_id_2", ... } @export var items: Array[ItemData] @export var enemies: Array[EnemyData] ``` ### 3.3 LLM Protocol (JSON Structure) The LLM will be instructed to return JSON in this format: ```json { "narrative": "You step into the dark cave. The air is damp...", "action": { "type": "MOVE", "target": "north" }, "state_changes": { "player_hp": -5 } } ``` ## 4. Core Systems ### 4.1 Navigation (The 4x4 Grid) * **Map:** A 4x4 grid of `RoomData` resources. * **Minimap:** A UI GridContainer that highlights the `current_room_id`. * **Movement:** Validated against `RoomData.exits`. ### 4.2 Combat System (Dragon Quest Style) * **Trigger:** When `action.type == "COMBAT"` or player encounters an enemy. * **View:** Switches Main Display to "Combat Mode" (Enemy sprite front & center). * **Flow:** 1. **Player Turn:** Choose Attack/Item/Flee. 2. **Resolution:** Calculate damage (Simple: `Atk - Def`). 3. **Enemy Turn:** Enemy attacks player. 4. **Loop:** Until HP <= 0. * **LLM Role:** Describes the combat moves ("You swing your sword...", "The slime wobbles aggressively..."), but the *math* is handled by Godot. ### 4.3 Inventory * **Data:** Array of `ItemData` resources. * **UI:** List of items. Clicking an item adds "Use [Item Name]" to the input field or triggers a context menu. ## 5. Tech Stack * **Engine:** Godot 4.2+ * **Language:** GDScript * **AI Provider:** OpenRouter (Model: `google/gemini-2.0-flash-exp` or `meta-llama/llama-3-8b-instruct` for speed/cost). * **Version Control:** Git