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)
8.6 KiB
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 stanzadescription: descrizione lungaexits: dict {direzione: room_id_target} o None se non esploratoentities: lista mob/NPC/oggetti presentimetadata: 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 visiteconfidence: 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
RoomExtractorcon regex MUD - Implementare
MUDGraphcon NetworkX - Setup schema SQLite
- Implementare
AutoExplorercon BFS per exit non esplorati - Implementare
MemvidArchiveencoding/decoding - Implementare
SyncManagercon 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
- Inizia dal SQLite: implementa prima il grafo in-memory + SQLite, il Memvid è un "nice to have" iniziale
- Mock del server: crea un
MockMUDServerche risponde con testo predefinito per i test - Logging: usa
loggingper tracciare ogni decisione dell'explorer (utile per debug) - Configurazione: usa
pydantic.BaseSettingsper parametri (sync_interval, embedding model, ecc.)
Definizione di Completato
L'automapper è considerato completato quando:
- ✅ Può esplorare autonomamente un mondo MUD di test con 50+ stanze
- ✅ Costruisce un grafo navigabile con pathfinding funzionante
- ✅ Persiste i dati in SQLite senza perdita di informazioni
- ✅ Genera correttamente un archivio Memvid ricercabile
- ✅ Tutti i test passano (
pytest tests/ -v)
Priorità: Alta