# 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