Add pluggable parser system, perception loop, and project infrastructure
Phase 0 (housekeeping): - Add .gitignore to protect credentials and runtime files - Track all project source code, docs, and config Phase 1 (perception loop): - Implement pluggable parser architecture (BaseMudParser ABC + ParserFactory) - Add DeadSoulsParser with regex for HP/MP/SP prompt, room descriptions, exits (multiple formats), NPC/item detection, and combat events - Add OutputBuffer for accumulating text between prompts - Update GameState with SP support and update_from_prompt/room/combat methods - Rewire main loop to use parser + buffer for real-time game state updates - Add reconnection logic to TelnetClient (retry with backoff) - Remove old TextParser (replaced by pluggable system) - Add mud_type config field for selecting parser at runtime - Add comprehensive test suite (50 tests, all passing)
This commit is contained in:
1 parent
0f370ec089
commit
f85c27a742
42 files changed
+3490
-134
No files matched your search
@@ -0,0 +1,95 @@
|
||||
"""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 AIConfig(BaseModel):
|
||||
"""AI engine configuration"""
|
||||
engine: str = "rule_based"
|
||||
llm_model: str = "llama3.2"
|
||||
decision_delay_ms: List[int] = Field(default=[200, 2000])
|
||||
exploration_strategy: str = "depth_first"
|
||||
|
||||
|
||||
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)
|
||||
|
||||
active_storage: ActiveStorageConfig = Field(default_factory=ActiveStorageConfig)
|
||||
historical_storage: HistoricalStorageConfig = Field(default_factory=HistoricalStorageConfig)
|
||||
|
||||
|
||||
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 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)
|
||||
|
||||
|
||||
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)
|
||||
Reference in new issue
Block a user