# MMUD — Mesh Multi-User Dungeon Text-based multiplayer dungeon crawler for Meshtastic LoRa mesh networks. BBS door games (LORD, TradeWars) adapted for 150-char mesh radio constraints, async play, 30-day wipe cycles. ## Status **Phase:** Deployed and running — all 6 phases implemented, NPC conversation system live with Gemini 2.5 Flash. ## Deployment - **Game Daemon:** CT 109 (192.168.1.109) on utility node, Docker container, Flask dashboard on port 5000 - **Dashboard:** https://mmud.echo6.co (Last Ember — dark tavern aesthetic) - **SIM Nodes:** 6 meshtasticd LXC containers (CT 111-116) on utility - EMBR (CT 111) — game server - DCRG (CT 112) — broadcast - GRST (CT 113) — Grist barkeep NPC - MRN (CT 114) — Maren healer NPC - TRVL (CT 115) — Torval merchant NPC - WSPR (CT 116) — Whisper sage NPC - **LLM Backend:** Gemini 2.5 Flash via Google genai SDK (configured in DB `llm_config` table) - **Compose:** `/opt/mmud/docker-compose.yml` on CT 109 - **Admin:** https://mmud.echo6.co/admin (session auth, password in docker env) ## Repo `/home/zvx/projects/mmud` (GitHub: zvx-echo6/mmud) The repo contains a `CLAUDE.md` with full architecture, directory structure, and implementation guidance. **Read it first before any work.** ## Key Files - `CLAUDE.md` — Architecture, patterns, gotchas - `docs/planned.md` — Complete game design document (~950 lines). Source of truth for all mechanics. - `docs/npc-lore.md` — NPC deep lore bible (5-layer Hearth-Sworn backstories, 514 lines) - `docs/worldbuilding.md` — Surface-level worldbuilding (Legend of Oryn, floor identities) - `config.py` — All game constants with rationale - `src/db/schema.sql` — Full database schema (migrations in `src/db/migrations/`) ## Architecture - **Python 3.11+**, SQLite, Meshtastic Python API, Flask 3.x, Jinja2 - **Docker:** python:3.11-slim, /data volume for SQLite DB - **6-node mesh topology:** EMBR (game), DCRG (broadcast), 4 NPC nodes - **150 characters per message** — hard ceiling from Meshtastic LoRa - **12 dungeon actions/day**, 30-day epochs, async-first - **828+ tests** — `python3 -m pytest tests/ -x -v` ## NPC Conversation System NPCs use runtime LLM calls (the one exception to the "no runtime LLM" rule). Key features: - **TX Tag System:** LLM prefixes responses with `[TX:action:detail]` for game mechanics (heal, buy, sell, browse, gamble, hint, recap) - **Session Memory:** Per-player per-NPC conversation history with persistent memory summaries - **Deep Lore:** Five-layer backstory system (Surface → Observations → History → Truth → Unspeakable) - Trigger word detection pushes toward deeper layers - Interaction count tracks conversation depth per player per NPC - "Soren" is a Layer 5 nuclear trigger for all 4 NPCs - **Easter Eggs:** Death memory (Maren), daily gamble (Torval), countdown (Whisper), late-epoch vulnerability (Maren), inter-NPC secret (Torval/Whisper) - **DummyBackend:** Keyword-based offline mode for testing without LLM ## LLM Configuration - Model configured via `llm_config` table in SQLite DB (not env vars) - Currently: Gemini 2.5 Flash (`gemini-2.5-flash`) - API key stored in DB, manageable via admin panel at /admin/llm - **No `max_output_tokens` restrictions** — Gemini 2.5 Flash thinking tokens consume the budget, causing truncation. All backends have token limits removed. - Supports: Google (Gemini), Anthropic (Claude), OpenAI-compatible backends ## Development Phases (All Complete) 1. **Core Loop** — Message handling, parser, player creation, navigation, combat, death, action budget 2. **Economy & Progression** — XP, leveling, gold, shops, gear, bank, healer 3. **Social Systems** — Broadcasts, barkeep, bounty board, player messages, mail 4. **Epoch Generation** — World gen, LLM narrative pipeline, secrets, bounty pools 5. **Endgame Modes** — Hold the Line, Raid Boss, Retrieve & Escape, epoch vote 6. **The Breach** — Breach zone gen, 4 mini-events (Heist, Emergence, Incursion, Resonance) ## Gotchas - Gemini 2.5 Flash thinking tokens count against `max_output_tokens` — never set token limits - NPC greeting path uses `complete()`, conversation path uses `chat()` — different code paths - `npc_memory` table stores `turn_count` for interaction depth tracking - Death log table (`death_log`) tracks monster kills for Maren's memory feature - Town actions are always free — never charge dungeon actions in town - The design doc (`docs/planned.md`) is the source of truth — if code contradicts it, code is wrong ## Notes - All regen/HP/damage numbers are targets — will need playtesting - SQLite single file DB, no ORM, raw parameterized SQL - Every outbound message must fit 150 chars — the formatter is the final gate - Container on CT 109 connects to 6 SIM nodes via TCP (ports 4403)