"""Configuration loading and validation""" import yaml from pydantic import BaseModel, Field from typing import List, Optional class MudConfig(BaseModel): """MUD server configuration""" host: str port: int mud_type: str = "dead_souls" username: str = "" password: str = "" keep_alive_interval: int = 60 keep_alive_command: str = "" class CharacterConfig(BaseModel): """Character preferences""" name: str = "AIPlayer" preferred_class: str = "warrior" preferred_race: str = "human" play_style: str = "balanced" class LLMProviderConfig(BaseModel): """LLM provider configuration (Ollama / OpenAI-compatible)""" enabled: bool = True base_url: str = "http://localhost:11434" model: str = "llama3.2" temperature: float = 0.3 max_tokens: int = 512 timeout_seconds: float = 30.0 max_retries: int = 2 system_prompt: str = ( "You are an AI playing a text-based MUD game. " "You must respond ONLY with the requested format. " "Be concise and precise. No explanations unless asked." ) memory_db_path: str = "data/llm_memory.db" """Path to SQLite database for LLM long-term memory.""" class AIConfig(BaseModel): """AI engine configuration""" engine: str = "hybrid" llm_model: str = "llama3.2" decision_delay_ms: List[int] = Field(default=[200, 2000]) exploration_strategy: str = "depth_first" llm: LLMProviderConfig = Field(default_factory=LLMProviderConfig) class MapperConfig(BaseModel): """Mapper configuration""" class ActiveStorageConfig(BaseModel): db_path: str = "data/maps/active/world.db" graph_cache_size: int = 10000 class HistoricalStorageConfig(BaseModel): archive_dir: str = "data/maps/archive" class SnapshotTriggers(BaseModel): room_count: int = 500 session_end: bool = True time_interval_hours: int = 24 snapshot_triggers: SnapshotTriggers = Field(default_factory=SnapshotTriggers) class SemanticSearchConfig(BaseModel): model: str = "sentence-transformers/all-MiniLM-L6-v2" top_k: int = 5 similarity_threshold: float = 0.7 active_storage: ActiveStorageConfig = Field(default_factory=ActiveStorageConfig) historical_storage: HistoricalStorageConfig = Field(default_factory=HistoricalStorageConfig) semantic_search: SemanticSearchConfig = Field(default_factory=SemanticSearchConfig) class BehaviorConfig(BaseModel): """Behavior simulation configuration""" reaction_time_min_ms: int = 200 reaction_time_max_ms: int = 2000 pause_probability: float = 0.05 typo_probability: float = 0.0 class LoggingConfig(BaseModel): """Logging configuration""" level: str = "INFO" file: str = "data/logs/game.log" console: bool = True max_file_size_mb: int = 10 backup_count: int = 5 class MonitoringConfig(BaseModel): """Web monitoring dashboard configuration""" enabled: bool = True host: str = "127.0.0.1" port: int = 8080 class Config(BaseModel): """Main configuration""" mud: MudConfig character: CharacterConfig = Field(default_factory=CharacterConfig) ai: AIConfig = Field(default_factory=AIConfig) mapper: MapperConfig = Field(default_factory=MapperConfig) behavior: BehaviorConfig = Field(default_factory=BehaviorConfig) logging: LoggingConfig = Field(default_factory=LoggingConfig) monitoring: MonitoringConfig = Field(default_factory=MonitoringConfig) def load_config(config_path: str = "config.yaml") -> Config: """ Load configuration from YAML file Args: config_path: Path to config file Returns: Validated Config object """ with open(config_path, 'r') as f: config_dict = yaml.safe_load(f) return Config(**config_dict)