# Development Guide ## Come Aggiungere un Nuovo Tool 1. Apri `src/engine/tools.py` 2. Scrivi una funzione con `@tool` decorator: ```python @tool def perception_check(character_id: int, dc: int, modifier: int = 0) -> ToolResult: char = storage.get_character(character_id) if not char: return {"success": False, "tool": "perception-check", "message": "PG non trovato."} atk = dice.roll("d20", modifier=modifier) passed = atk["total"] >= dc return { "success": True, "tool": "perception-check", "character_id": character_id, "roll": atk["total"], "dc": dc, "passed": passed, "message": f"Percezione: d20+{modifier} → {atk['total']} vs CD {dc} → {'Successo!' if passed else 'Fallimento.'}", } ``` 3. Aggiungi il tool a `_KNOWN_TOOLS` in `src/engine/prompts.py`: ```python "perception_check": {"character_id": "id pg", "dc": "CD percezione", "modifier": "bonus/penalità"}, ``` 4. Aggiungi un esempio a `TOOL_EXAMPLES` in `prompts.py`: ```python - Tiro percezione CD 12 → {"tool": "perception_check", "params": {"character_id": 1, "dc": 12}, "narration": "Tendi l'orecchio..."} ``` 5. **Fatto.** Il tool viene automaticamente registrato in `TOOL_REGISTRY`. ## Come Aggiungere un Provider LLM 1. Apri `src/engine/providers.py` 2. Crea una nuova classe che estende `LLMProvider`: ```python class AnthropicProvider(LLMProvider): def __init__(self, api_key: str, model: str, timeout: int = 60): self.api_key = api_key self.model = model self.timeout = timeout def ask(self, prompt: str, system: str = "") -> str: # Implementa chiamata API Anthropic qui ... ``` 3. Registra in `_registry`: ```python _registry = { "ollama": OllamaProvider, "openrouter": OpenRouterProvider, "local": LocalProvider, "anthropic": AnthropicProvider, # <-- aggiungi } ``` 4. Aggiungi il case in `create_provider()`: ```python if cfg.kind == "anthropic": return cls(cfg.anthropic_api_key, cfg.anthropic_model, cfg.timeout) ``` 5. Aggiungi configurazione in `config.py`: ```python anthropic_api_key: str = "" anthropic_model: str = "claude-sonnet-4-20250514" ``` ## Come Aggiungere una Nuova Area all'Avventura 1. Apri `data/adventure/avventura.json` 2. Aggiungi area all'array `areas`: ```json { "id": "1.10", "name": "Biblioteca Arcana", "order": 10, "description": "...", "atmosphere": "...", "connections": ["1.9"], "features": ["Scaffali polverosi", "Globo luminoso fluttuante"], "puzzles": [...], "traps": [], "monsters": [{"ref_id": "ancient_spirit", "count": 1, "tactics": "...", "ambush": false}], "items": [ {"id": "scroll_of_truth", "name": "Pergamena della Verità", "description": "...", "type": "consumable", "magical": true} ], "treasure": [] } ``` 3. Aggiungi stat block del mostro in `monsters`: ```json { "id": "ancient_spirit", "name": "Spirito Antico", "level": 3, "stats": {"ac": 14, "hp": 18, "attack": "d20+3", "damage": "1d6+1", "saves": {"Tempra": 2, "Riflessi": 4, "Volontà": 6}, "move": "9m (volando)"}, "special": "Intangibile, colpito solo da magia o argento", "xp": 100, "loot": [] } ``` 4. Riavvia il server. La nuova area viene caricata automaticamente. ## Come Aggiungere una Tabella Crit/Fumble 1. Aggiungi entry a `data/crit_fumble_tables.json` 2. Riavvia il server (ricarica da JSON se DB vuoto) 3. Se il DB è già popolato, cancella `data/dcc_rpg.db` (verrà ricreato) ## Test ```bash # Test dadi python src/engine/dice.py # Test tools (con setup DB) python src/engine/tools.py # Test LLM parsing python src/engine/llm.py # Test DB completo python src/engine/db.py # Avvia CLI interattiva python -c " from src.engine import dm, db db.init_db() camp_id = db.create_campaign('Test', 'Avventura') char_id = db.create_character(camp_id, 'Eroe', 'guerriero', 'soldato') db.update_character(char_id, level=1, str=15, agi=11, sta=14, per=9, int=8, lck=10, hp_current=12, hp_max=12, ac=15) dm.interactive(camp_id) " ``` ### Test esistenti (`tests/`) - `test_dice.py` — test modulo dadi (pytest) - `test_tools.py` — test tool execution - `test_integration.py` — test flusso dm_cycle - `test_websocket.py` — test WebSocket lifecycle Per eseguire: ```bash python -m pytest tests/ -v ``` ## Known LSP Issues (non bloccanti) Il LSP segnala questi errori, ma non impediscono l'esecuzione: | File | Errore | Causa | |---|---|---| | `db.py:762` | `Object of type "None" is not subscriptable` | `cursor.fetchone()` in `get_current_area` può restituire None | | `test_dice.py:47` | `output_die not in ValidationError` | `DiceChainResult` e `ValidationError` condividono TypedDict — meglio `@dataclass` | | `tests/test_websocket.py:8` | `Import pytest could not be resolved` | pytest non installato nell'ambiente LSP | | `game_context.py:29` | `get_current_area not in db` | LSP non riconosce funzioni dinamicamente caricate | ## Estendere il Frontend Il frontend è un singolo file HTML (`src/web/static/index.html`) con: - CSS: tema scuro sword & sorcery con variabili CSS - JS: ~300 righe di vanilla JS (nessun framework) - WebSocket: connessione persistente, auto-reconnect Per modificare: - **Stile**: modifica le variabili CSS in `:root` e classi dei componenti - **Nuova sezione sidebar**: aggiungi div in HTML + funzione render in JS - **Nuovo tipo di messaggio**: aggiungi case a `handleMessage()` ## Guida alla Conoscenza Base (knowledge/) I 15 file in `knowledge/` contengono le regole DCC in formato markdown italiano. Non sono usati direttamente dal runtime (i dati sono in DB/JSON/code), ma sono la fonte di verità per lo sviluppo. Per rigenerare prompt alla luce delle regole: 1. Consulta i file `knowledge/01_meccanica_base.md` → `knowledge/15_dadi.md` 2. Adatta `prompts.py` e `tools.py` di conseguenza ## Checklist Prossimi Miglioramenti **Priorità alta:** - [ ] Aggiungere requirements.txt o pyproject.toml - [ ] Aggiungere Dockerfile + docker-compose.yml - [ ] Script start.sh per avvio con un comando - [ ] Supporto per più PG contemporaneamente - [ ] Persistenza PF multipli mostri per area **Priorità media:** - [ ] Test completi per ogni tool - [ ] Tavola incantesimi dal Reference Booklet - [ ] Abilità ladro complete (dado dedicato per livello) - [ ] Scacciare non-morti (Chierico) - [ ] Equipaggiamento e armi dal knowledge base **Priorità bassa:** - [ ] OCR Core Rulebook (498 pagine immagini, ~8h stimate) - [ ] RAG + embedding per knowledge base DCC - [ ] Multi-giocatore (più PG in contemporanea) - [ ] Inventory drag & drop nel frontend - [ ] Mappa interattiva delle aree