Files
truetype f85c27a742 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)
2026-02-08 19:08:59 +01:00

307 lines
8.6 KiB
Markdown

<img src="https://r2cdn.perplexity.ai/pplx-full-logo-primary-dark%402x.png" style="height:64px;margin-right:32px"/>
# puoi produrre un PR.MD per chiedere ad un agente tipo ralph di produrre un automapper con queste caratteristiche ?
```markdown
# PR: Implementazione Automapper MUD con Archivio Ibrido SQLite/Memvid
## Descrizione
Implementare un modulo automapper per un client MUD che costruisca automaticamente una mappa del mondo di gioco durante l'esplorazione, con persistenza ibrida: SQLite per la memoria attiva real-time e Memvid per l'archivio storico compresso.
## Obiettivi
- [ ] Parsing delle descrizioni stanze dal protocollo Telnet MUD
- [ ] Costruzione incrementale del grafo di navigazione (stanze = nodi, direzioni = archi)
- [ ] Identificazione univoca delle stanze (room fingerprinting)
- [ ] Auto-mapping durante l'esplorazione senza intervento umano
- [ ] Pathfinding A* tra stanze note
- [ ] Storage layer ibrido: SQLite (attivo) + Memvid (storico)
- [ ] Sistema di ricerca semantica sulle descrizioni stanze
## Architettura Proposta
### 1. Telnet Parser & Room Extractor
```python
class RoomExtractor:
"""Estrae informazioni stanza dal testo MUD grezzo"""
def parse(self, raw_output: str) -> RoomData:
# Estrae: nome stanza, descrizione, exits disponibili,
# oggetti presenti, mob/NPC visibili
pass
```
**Input**: Testo raw dal server MUD (con ANSI color codes)
**Output**: `RoomData` strutturato con:
- `room_id`: hash univoco (descrizione + exits + nome)
- `name`: nome breve stanza
- `description`: descrizione lunga
- `exits`: dict {direzione: room_id_target} o None se non esplorato
- `entities`: lista mob/NPC/oggetti presenti
- `metadata`: timestamp, coordinate approssimative (se disponibili)
### 2. Graph Manager (NetworkX)
```python
class MUDGraph:
"""Grafo delle stanze con metodi di navigazione"""
def add_room(self, room: RoomData) -> bool:
# Aggiunge nodo, aggiorna archi bidirezionali
pass
def find_path(self, from_id: str, to_id: str) -> List[str]:
# A* pathfinding, ritorna lista di direzioni [n, n, e, u, ...]
pass
def get_unexplored_exits(self, room_id: str) -> List[str]:
# Ritorna direzioni da esplorare (exit con target=None)
pass
```
### 3. Storage Layer Ibrido
#### Layer A - SQLite (Memoria Attiva)
Per operazioni real-time durante l'esplorazione:
```sql
-- rooms: cache attiva delle stanze esplorate
CREATE TABLE rooms (
room_id TEXT PRIMARY KEY,
name TEXT,
description TEXT,
embedding BLOB, -- vettore per ricerca semantica
discovered_at TIMESTAMP,
visit_count INTEGER DEFAULT 1,
last_visit TIMESTAMP
);
-- exits: grafo di navigazione
CREATE TABLE exits (
from_room TEXT,
direction TEXT,
to_room TEXT, -- NULL se non esplorato
FOREIGN KEY (from_room) REFERENCES rooms(room_id)
);
-- exploration_queue: stanze con exit non esplorati
CREATE TABLE exploration_queue (
room_id TEXT,
direction TEXT,
priority INTEGER,
added_at TIMESTAMP
);
```
#### Layer B - Memvid (Archivio Storico)
Per storage compresso e ricerca semantica a lungo termine:
```python
class MemvidArchive:
"""Archivio storico in MP4 con QR code frames"""
def snapshot(self, db_path: str) -> str:
# 1. Estrae tutte le stanze da SQLite
# 2. Chunking descrizioni + metadati
# 3. Embedding con sentence-transformers
# 4. Encoding in QR code frames
# 5. Genera MP4 H.264 + indice FAISS
pass
def semantic_search(self, query: str, top_k: int = 5) -> List[RoomData]:
# Ricerca vettoriale sul MP4 storico
pass
```
### 4. Auto-Explorer Controller
```python
class AutoExplorer:
"""Orchestra l'esplorazione automatica"""
def decide_next_move(self, current_room: RoomData) -> str:
# Logica:
# 1. Se ci sono exit non esplorati, scegli quella più vicina
# 2. Altrimenti, BFS verso la stanza con exit non esplorati
# 3. Evita loop (no back-and-forth)
pass
def update_graph(self, move: str, result: str) -> None:
# Aggiorna grafo dopo ogni movimento
# Se result è "You can't go that way", marca exit come blocked
pass
```
### 5. Sync Manager
```python
class SyncManager:
"""Gestisce la sincronizzazione tra SQLite e Memvid"""
def __init__(self, sync_interval: int = 100):
# Ogni N stanze nuove, triggera snapshot Memvid
pass
def should_sync(self) -> bool:
# Controlla se ci sono abbastanza nuove stanze
pass
def perform_sync(self):
# 1. Crea backup SQLite
# 2. Genera snapshot Memvid
# 3. Verifica integrità (sample random decode)
# 4. Opzionale: pulisce SQLite delle stanze meno recenti
pass
```
## Criteri di Accettazione
### Test 1: Parsing Base
```python
raw_mud_output = """
[Exits: n e w]
The Village Square
You are standing in the village square. A fountain bubbles here.
A guard is standing here.
A signpost points north to the Forest, east to the Shop.
"""
room = extractor.parse(raw_mud_output)
assert room.name == "The Village Square"
assert room.exits == {"n": None, "e": None, "w": None}
assert "guard" in room.entities
```
### Test 2: Costruzione Grafo
```python
# Simula esplorazione: Square → North → Forest
graph = MUDGraph()
# ... aggiungi stanze ...
path = graph.find_path("square_123", "forest_456")
assert path == ["n"] # diretta, una sola mossa
```
### Test 3: Persistenza SQLite
```python
# Dopo 10 stanze esplorate
assert db.count_rooms() == 10
assert db.get_room("square_123").visit_count >= 1
```
### Test 4: Memvid Snapshot
```python
# Dopo sync, verifica che MP4 sia leggibile
archive = MemvidArchive("world_map.mp4")
results = archive.semantic_search("forest with dark trees")
assert len(results) > 0
assert "forest" in results.description.lower()
```
### Test 5: Auto-Explorer (Integration)
```python
# Simula 20 movimenti in un mondo di test
explorer = AutoExplorer(graph)
for _ in range(20):
move = explorer.decide_next_move(current_room)
# Simula risposta server
new_room = simulate_mud_response(move)
explorer.update_graph(move, new_room)
# Dovrebbe aver esplorato almeno 5 stanze uniche
assert len(graph.rooms) >= 5
```
## Considerazioni Tecniche
### Room ID Generation
Usare hash consistente (SHA256 truncato) di:
- Nome stanza normalizzato (lowercase, no color codes)
- Descrizione normalizzata (prime 100 char)
- Lista di exits disponibili (ordinata)
### Gestione Stanze Dinamiche
Alcuni MUD hanno stanze che cambiano (portali random, maze). Implementare:
- `is_dynamic`: flag se la stanza cambia tra visite
- `confidence`: score 0-1 sulla stabilità dell'ID
### Performance Targets
- Parsing stanza: < 50ms
- Query pathfinding: < 100ms per 1000 stanze
- Sync SQLite→Memvid: background, non bloccare < 500ms UI
### Dipendenze
```
# requirements.txt
networkx
sqlite3
numpy
sentence-transformers
pillow # QR generation
opencv-python # QR decoding
faiss-cpu # o faiss-gpu
```
## Checklist Implementazione
- [ ] Implementare `RoomExtractor` con regex MUD
- [ ] Implementare `MUDGraph` con NetworkX
- [ ] Setup schema SQLite
- [ ] Implementare `AutoExplorer` con BFS per exit non esplorati
- [ ] Implementare `MemvidArchive` encoding/decoding
- [ ] Implementare `SyncManager` con trigger automatico
- [ ] Scrivere test unitari per ogni modulo
- [ ] Scrivere test di integrazione con server MUD mock
- [ ] Documentazione API (docstring)
- [ ] Esempio di usage in `examples/basic_explorer.py`
## Note per l'Agente
1. **Inizia dal SQLite**: implementa prima il grafo in-memory + SQLite, il Memvid è un "nice to have" iniziale
2. **Mock del server**: crea un `MockMUDServer` che risponde con testo predefinito per i test
3. **Logging**: usa `logging` per tracciare ogni decisione dell'explorer (utile per debug)
4. **Configurazione**: usa `pydantic.BaseSettings` per parametri (sync_interval, embedding model, ecc.)
## Definizione di Completato
L'automapper è considerato completato quando:
1. ✅ Può esplorare autonomamente un mondo MUD di test con 50+ stanze
2. ✅ Costruisce un grafo navigabile con pathfinding funzionante
3. ✅ Persiste i dati in SQLite senza perdita di informazioni
4. ✅ Genera correttamente un archivio Memvid ricercabile
5. ✅ Tutti i test passano (`pytest tests/ -v`)
---
**Priorità**: Alta