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

8.6 KiB

puoi produrre un PR.MD per chiedere ad un agente tipo ralph di produrre un automapper con queste caratteristiche ?

# 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)

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:

-- 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:

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

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

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

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

# 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

# Dopo 10 stanze esplorate
assert db.count_rooms() == 10
assert db.get_room("square_123").visit_count >= 1

Test 4: Memvid Snapshot

# 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)

# 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