- Bump version 0.1.0 to 0.2.0 (GMCP decoder, mapper BFS, EventLogger added since 0.1) - Update pyproject description to surface project identity - Expand PyPI keywords: viandante, wandering, ascii-mapper, gmcp
viandante
viandante ospita un client MUD CLI pensato per collegarsi a un MUD
LP‑MUD basato sul driver FluffOS (per esempio Dead Souls, libreria
3.8.6). Il client parla telnet con estensioni standard: ECHO, NAWS,
TTYPE, e rifiuta (WONT) tutte le altre (GMCP, MSDP, MCCP, MXP
per ora). Tiene traccia delle stanze visitate e le renderizza come mappa
ASCII on-demand.
Requisiti
- Python ≥ 3.10
- Una libreria Python:
prompt_toolkit≥ 3.0
Setup
cd viandante
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Verrà installato il comando mudclient.
Uso
# Default: si collega a localhost:6666 con un finestra iniziale 120×40
mudclient
# Espliciti
mudclient --host localhost --port 6666 --cols 120 --rows 40
# Auto-login: passa il nome; il client lo invia quando il server chiede
# "What name do you wish?". Se serve la password, il client chiede
# /password PWD oppure la puoi passare con --password (o env MUDCLIENT_PASSWORD).
mudclient --user zork --password hunter2
# Log di sessione: ogni evento (testo, GMCP, stanze, comandi locali, linee inviate)
# viene serializzato in append‑only, flushed dopo ogni write — adatto a `tail -f`.
mudclient --log-json ~/mud-session.jsonl --log-md ~/mud-session.md
I file
--log-json/--log-mdvengono truncati all'apertura: ogni nuova sessione ricomincia da zero. Per ruotare manualmente prima della sessione:mv ~/mud-session.jsonl{,.prev} && mudclient --log-json ~/mud-session.jsonl
Schema eventi (un oggetto JSON per riga):
kind |
Scopo | Note |
|---|---|---|
session_start |
apertura sessione | host, port, user |
session_end |
chiusura normale | reason |
disconnect |
chiusura socket | reason |
text |
chunk ANSI ricevuto dal server | raw preservato |
room_enter |
mapper ha registrato una stanza | id, name, exits |
gmcp |
frame GMCP accettato | module, payload |
vitals |
snapshot hp/sp/mv | solo i campi presenti |
line_sent |
riga inoltrata al MUD | password redatte (***) |
local_cmd |
comando /... intercettato |
password/segreti redatti |
login |
prompt/risposta auto-login | value redatto di default; passare redact=False per i nomi account |
Una volta connesso:
| Tasto | Effetto |
|---|---|
| Testo qualsiasi | inviato al MUD terminato da \r\n |
/map |
disegna la mappa ASCII delle stanze visitate (multi-source BFS) |
/where |
mostra la stanza corrente e le uscite |
/look |
invia look al MUD |
/vitals |
mostra hp/sp/mv (via GMCP Char.Vitals) |
/stats |
locali scoperti, GMCP stato, vitali |
/password PWD |
invia una password al MUD |
/clear |
pulisce lo schermo |
/help (/?) |
mostra l'aiuto |
/quit (/q, Ctrl‑D) |
esce |
Il prompt è sempre del tipo:
[NomeStanza]> _
con il nome della stanza corrente in cyan brillante. In basso c'è una status bar che mostra:
[stanza: Outer Courtyard] [GMCP: on] HP 100/100 SP 50/50 MV 80/80
Quando il server invia Char.Vitals via GMCP, hp/sp/mv compaiono automaticamente.
Layout dei sorgenti
viandante/
├── pyproject.toml # metadata + dipendenze + entry point `mudclient`
├── README.md # questo file
├── .gitignore
├── docs/ # documentazione completa (vedi sotto)
│ ├── README.md # indice della cartella docs
│ ├── architecture.md # analisi architetturale (data flow + boundary)
│ ├── modules.md # descrizione modulo‑per‑modulo
│ ├── protocol.md # telnet, GMCP, ANSI, euristiche Dead Souls
│ ├── usage.md # flag CLI, esempi, auto‑login, comandi slash
│ ├── events.md # schema eventi del logger
│ ├── development.md # setup dev, pytest, ruff, come estendere
│ └── gitea.md # flusso di pubblicazione sul Gitea + sicurezza token
├── src/viandante/ # package
│ ├── __init__.py
│ ├── __main__.py # supporta `python -m viandante`
│ ├── cli.py # entry point + UI a riga di comando
│ ├── telnet.py # state machine IAC + asyncio
│ ├── deadsouls.py # parser di stanze Dead Souls / LP‑MUD
│ ├── gmcp.py # parser GMCP (Char.Vitals / Room.Info)
│ ├── mapper.py # grafo delle stanze + render ASCII
│ ├── logger.py # EventLogger (JSONL + Markdown sinks)
│ └── ansi.py # stripper ANSI per il parser
└── tests/ # unit test (pytest)
├── test_telnet.py
├── test_ansi.py
├── test_deadsouls.py
├── test_mapper.py
└── test_logger.py
📚 Documentazione completa
La documentazione vive nella cartella docs/ e
copre:
docs/architecture.md— analisi architetturale completa: dipendenze tra moduli, data flow di un frame dal server, boundary concerns, refactor raccomandati.docs/modules.md— cosa fa ogni modulo, API pubblica, responsabilità, tolleranze.docs/protocol.md— IAC state machine, GMCP wire format, euristiche Dead Souls, ANSI handling.docs/usage.md— riferimento flag CLI, esempi pratici, flusso auto‑login, comandi slash, rotazione log.docs/events.md— schema completo degli eventi del logger (JSONL + Markdown), regole di redazione, esempijq.docs/development.md— workflow sviluppatore: setup, test, lint, come aggiungere moduli, debugging.docs/gitea.md— flusso di pubblicazione sul server Gitea192.168.0.183:8085(utentetruetype) + regole di sicurezza del token.
Note sul protocollo
Il client negozia:
ECHO: inviaWILL ECHOin risposta aDO ECHO. Il server non eseguirà più echo remoto, mentre l'eco locale è gestita daprompt_toolkit.NAWS: se attivo, invia la dimensione della finestra iniziale.TTYPE: risponde conXTERM-256COLORquando il server lo richiede.GMCP: viene offerto proattivamente (WILLal connect). Dead Souls lo accetta e invia pacchettiChar.Vitals,Room.Info,Char.Login, ecc. Quando una stanza arriva viaRoom.Info, si usa ilnum(vnum) del server come id stabile della stanza.
Le righe di stato del parser considerano IAC GA (249) e IAC EOR
(239) come delimitatori di "record/prompt", così da poter chiudere un
blocco di stanza anche quando il prompt testuale non è immediatamente
riconoscibile.
La rilevazione automatica della geometria del mondo si basa sul movimento
inviato dall'utente + descrizione della stanza osservata subito
dopo: quando digiti n, il client informa il mapper; quando la risposta
del MUD arriva, Mapper.visit() collega automaticamente
corrente → nuova lungo la direzione digitata.
Il render della mappa è un multi-source BFS dal current room, con
fallback di posizionamento orfano per le stanze visitate in sequenza
indietro (es. n→s) e stack nell'angolo in basso a destra per stanze
completamente isolate.
Limitazioni note (v0.2)
- MSDP / MCCP / MCP / MXP non sono ancora abilitati: una sessione che
li richiede ottiene
WONTdal nostro lato. Dead Souls usa GMCP, che è ben coperto; altri MUD basati su MSDP possono essere aggiunti seguendo lo schema digmcp.py. - La detection delle stanze senza GMCP resta euristica sul testo.
- Login automatico: il client riconosce il prompt
What name do you wish?/Password:e invia automaticamente solo la prima volta. Per la password senza--passwordviene mostrato un suggerimentousa /password <pwd>(niente prompt annidato, troppo fragile). - Gli
u/d(verticali) sono rappresentati nella mappa ma non influenzano le coordinate 2D (offset(0,0)). - La status bar si aggiorna ad ogni rilettura della riga del prompt;
per refresh continui in idle si può aggiungere
refresh_intervalalPromptSessioncome estensione futura.
Sviluppo
pip install -e ".[dev]"
pytest # gira tutta la suite
ruff check src tests # lint
Licenza
MIT per il codice del client. Il server Dead Souls non è GPL — assicurati di rispettarne la licenza prima di redistribuirlo.