mudlib landscape - research into the MUD engine ecosystem

this document synthesizes research into existing MUD engines, their architectures,
and their design decisions. useful reference when designing our own mudlib.


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 1: the mud family tree
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

dikumud (1990)
--------------
the combat MUD ancestor. C, room-based, zone files, tick-based.

spawned the entire diku family: merc, rom, circle/tbamud, smaug.

binary/text zone files define the world. NPCs are templates that get instantiated
via "resets". main loop is tick-based (1/4 second typical). zones have 6 sections:
zone declaration, mobiles, objects, rooms, resets, DIL scripts.

major descendants:
  - merc 2.0 was a total rewrite improving code quality, dropping binary formats
  - circlemud stayed closer to original diku, cleaner but fewer features
  - smaug was the biggest architectural divergence - reintroduced complexity merc
    stripped out
  - tbamud is the modern circle continuation


lpc/lpmud (1989)
----------------
the big innovation: driver + mudlib separation.

driver is a VM for the LPC language. mudlib is the game framework written in LPC.
this means game logic is hot-reloadable interpreted code while the engine is
compiled C/C++.

drivers:
  - fluffos (active, mudos fork, C++)
  - ldmud (C, long history)
  - dgd (independent implementation)

mudlibs:
  - dead souls (beginner-friendly, batteries-included)
  - lima (clean modern)
  - discworld (the famous one)
  - morgengrauen (oldest german lpmud, since 1992)
  - realms-mud (rich combat/crafting)
  - cdlib/genesis (historically influential)

LPC is C-like, OOP. blueprint objects serve as templates, clones are instances.
objects inherit from parents forming hierarchies. code lives in .c files compiled
by the driver at runtime.

in-world programming: builders write LPC code that gets compiled by the driver
without restart. this is the core appeal of lpc muds.


moo/lambdamoo
-------------
everything-is-an-object. the entire world is a persistent object database.

objects have properties (data) and verbs (methods/commands). verbs are the core
interaction - "put ball in box" parses into a verb call with direct object,
preposition, indirect object.

in-world programming via @program command - attach MOO code to object verbs.

persistence: entire DB in RAM, periodic checkpoints to disk.

fork statement creates background tasks for async work.

modern forks:
  - toaststunt: multiple inheritance, HTTP, JSON, threading for sqlite/sort/etc
  - stunt: adds map datatype, RESTful interface


mush/mux (tinymud family)
-------------------------
objects with attributes (key-value), flags (booleans), locks (permission
expressions).

two kinds of code:
  - hardcoded (C, needs restart)
  - softcoded (mushcode, stored in attributes, hot-reloadable)

three parsers: command parser, function parser, locks parser.

building with @dig, @create, @link.


modern engines
--------------

evennia (python/twisted/django)
  see section 2 for deep dive. most framework-like of modern engines.

ranvier (node.js)
  bundle system where nearly everything is modular. bundles package commands,
  areas, items, NPCs, channels, behaviors. network layer is swappable.
  unopinionated core.

exventure (elixir)
  uses erlang/otp process model. kalevala framework underneath. web client,
  telnet, clustering, prometheus metrics, cross-game gossip chat.

coffeemud (java)
  most feature-complete MUD codebase. supports everything: MSP, MXP, GMCP, OLC,
  built-in web+mail server. d20-style combat with extensive modifier system.

compiled engine + scripted logic pattern:
  - gomud (go)
  - dragon-mud (go+lua)
  - ataxia (rust+lua)

graphicmud (java)
  tile-based graphics over telnet via sixel encoding. ECS architecture instead of
  inheritance. behavior trees for NPC AI. 4-tier action system with automatic
  dependency chaining. multi-connector: telnet, discord, telegram, websocket, MCP.
  30+ plugins. symbol system maps each tile to multiple representations (ascii,
  cp437, unicode, ansi colors, pixel bitmaps) — client capability detection picks
  the best one.

taleweave-ai (python)
  AI NPCs via LLMs, discord integration, stable diffusion visuals.


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 2: evennia deep dive
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

most relevant reference since we're also python.


architecture
------------
dual-process: portal (networking) + server (game logic), communicate via AMP
protocol.

portal handles all protocols: telnet, SSH, SSL, websocket, IRC, discord, grapevine.

server runs game logic, django ORM for persistence.

twisted-based async, event-driven (not tick-based by default).

scripts use ExtendedLoopingCall for timed tasks (tickers).


object model
------------
TypedObject base -> ObjectDB (django model) -> typeclasses (DefaultObject,
DefaultRoom, DefaultCharacter, DefaultExit)

rooms are objects with location=None.

exits are objects with db_destination. they dynamically create CmdExit commands.
typing "north" runs the exit's command which checks locks and traverses.

contents cached via ContentsHandler.

attributes: arbitrary pickled data via obj.db.attrname, stored in DB.

tags: lightweight string labels with categories, fast for filtering.

locks: function-based access control strings like "cmd:perm(Builder) AND
attr(canEdit)".


command system
--------------
commands define: key, aliases, locks, arg_regex, parse(), func().

processing pipeline:
  gather cmdsets from session/account/character/room/exits
  -> merge
  -> match
  -> execute: at_pre_cmd -> parse -> func -> at_post_cmd

cmdset merging uses set theory operations with priorities:
  - union (default)
  - intersect
  - replace
  - remove

priorities: exits=10, account=0, room objects=lower.

this is how game states work: push a "fishing" cmdset that overrides "throw",
pop it when done fishing. push "dark room" cmdset that replaces default commands.
stack them.

this is genuinely novel - set-theoretic operations on command availability.


session handling
----------------
portal creates PortalSession per connection.

server creates ServerSession, links to Account and Character.

MULTISESSION_MODE:
  0 = exclusive
  1 = multiple chars
  2 = multiple sessions per char
  3 = full multi


building
--------
@create, @dig, @link, @open, @desc, @set, @tag, @lock, @typeclass, @spawn

no in-game python execution in base evennia.

prototypes: dict-based object templates with inheritance via prototype_parent.

spawn system creates objects from prototypes.


persistence
-----------
django ORM with any supported DB (sqlite default, postgres for production).


what's unique about evennia
----------------------------
- cmdset merging system is genuinely novel
- typeclass system lets you change object behavior by swapping its class at
  runtime
- multi-protocol portal means same game is playable via telnet, web, ssh
  simultaneously
- django integration means you get admin panel, REST API, web views for free
- most "framework-like" of all MUD engines - it's a toolkit, not a game


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 3: how they all solve the same problems
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


world representation
--------------------

room graph (most common)
  rooms as nodes, exits as edges, directed graph. diku, lpc, evennia, ranvier
  all use this.

  advantage: clear sight lines (same room = visible)
  disadvantage: no consistent coordinate system

grid-based
  n*m orthogonal grid, each cell ~8 neighbors. used for wilderness areas in some
  lpc muds. consistent scale but less flexible.

continuous/coordinate
  entities at exact 2D/3D coordinates, descriptions generated from proximity.
  modern trend.

  advantages: seamless movement, true spatial relationships
  challenge: rendering continuous space as text

tile graphics (graphicmud)
  3D tile grid (x, y, z) with toroidal wrap. the unique part: tiles render as
  actual bitmap graphics via sixel encoding over telnet, not just colored text
  characters. symbol system gives each tile multiple representations — ascii
  fallback, cp437 glyph, unicode, ansi colors (16/256/24-bit), and pixel-grid
  bitmaps. client capability detection picks the richest format supported.
  standalone symbol editor for creating tile sets.

OUR APPROACH (from dreambook)
  2D toroidal tile grid with terrain types. viewport centered on player. hybrid -
  overworld is grid, interiors can be rooms. this is relatively uncommon in the
  MUD world.


command parsing
---------------
all MUDs: text in -> parse command name -> extract arguments -> dispatch to
handler -> execute -> text out

simple
  split on first space, command + args string

complex (moo)
  parse verb + direct object + preposition + indirect object

mush
  three separate parsers for commands, functions, and locks

evennia
  fuzzy matching against merged cmdset, disambiguation for ambiguous matches

ranvier
  modular command definitions in bundles


persistence
-----------

flat files
  diku zone files, moo database dumps. human-readable, version-controllable.

ORM/SQL
  evennia (django), some modern engines. structured, queryable, scalable.

in-memory + checkpoint
  moo model. fast but needs enough RAM.

sqlite
  good for embedded single-server muds. ACID compliant, single file.

OUR APPROACH
  world definitions in yaml/toml files (version controlled), runtime state in
  memory, player data in sqlite.


game loop
---------

tick-based (diku)
  fixed interval (1/4 sec), process all queues each tick. synchronous progression.
  simple, deterministic.

event-driven (evennia, ranvier, exventure)
  no central loop, react to events. tickers optional for periodic tasks. better
  for async, scales with concurrency.

turn-based
  advance only on player input. good for single-player IF, awkward for multiplayer.

OUR APPROACH (from dreambook)
  tick-based (10 ticks/sec), drain input queues each tick. timing-based combat
  needs a real clock.


combat
------

diku-style
  automatic attacks on timer ("pulse_violence" ~3 sec), player can enter special
  moves. hit/miss/damage calculated from stats, armor, weapon, random rolls.

no built-in combat
  most frameworks (evennia, ranvier) provide none - you build it.

coffeemud
  most complete combat system. d20-style with extensive modifier system.

OUR APPROACH (from dreambook)
  timing-based with telegraph/response windows. PL as health AND damage multiplier.
  stamina as action economy. diminishing returns on grinding.


communication
-------------
universal pattern: channels with audience types.

  say (room)
  tell (private)
  yell (area)
  chat (global)
  emote (room action)

ranvier's architecture: channel = name + audience type + formatter functions.

inter-mud: gossip protocol, IMC2, I3.


in-world creation/coding
------------------------

lpc
  write LPC code, driver compiles it live. most powerful but requires learning
  a language.

moo
  @program attaches code to object verbs. everything modifiable from inside.

mush
  softcode in attributes. simpler language than lpc/moo but capable.

evennia
  no in-game coding. prototypes and building commands only. spawn system for
  templates.

ranvier
  bundles written externally, loaded on startup.

OUR APPROACH (from dreambook)
  world-building DSL for puzzles/triggers/state machines, writable in in-MUD
  editor. NOT a full programming language but powerful enough for IF-style
  content.


npc behavior
-----------
most muds: simple scripts or state machines. mobs patrol, aggro, flee at low hp.

diku
  mobprog/mudprog triggers (on_greet, on_fight, on_death). procedural scripts.

lpc
  NPC code in LPC, full programming language. powerful but requires coding skill.

evennia
  no built-in NPC system. roll your own with scripts and tickers.

graphicmud
  behavior trees. hierarchical node structure (sequence, best-effort, action
  nodes). NPCs make decisions via tree traversal each tick. supports conditional
  logic, parallel execution, error handling. combat AI: survive, eliminate threat,
  patrol, assist.

OUR APPROACH (from dreambook)
  not yet designed. behavior trees worth considering.


action architecture
-------------------
how commands turn into world changes.

simple (most muds)
  command handler directly modifies state. "kill goblin" -> find goblin, check
  conditions, deal damage, all in one function.

graphicmud (4-tier)
  rawactions (atomic ops) -> cookedactions (single pulse) -> mudactions (multi-pulse
  with conditions) -> commands (user input). actions automatically chain to resolve
  dependencies — "attack goblin with sword" generates: walk to sword, pick up,
  equip, walk to goblin, attack. planning system handles the sequencing.

evennia
  at_pre_cmd -> parse -> func -> at_post_cmd. hooks at each stage but no
  automatic chaining.


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 4: protocols
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

telnet is the base. extensions negotiate via telnet option subnegotiation.


essential
---------

NAWS (RFC 1073)
  terminal window size. critical for viewport sizing.

GMCP
  generic mud communication protocol. JSON over telnet. the modern standard for
  structured data (hp bars, inventory, room info).

MSDP
  mud server data protocol. typeless variables, arrays, tables. alternative to
  gmcp.

MCCP2/3
  compression. zlib over telnet.


useful
------

MTTS
  terminal type standard. client capabilities negotiation.

MNES
  new environment standard. supplements mtts.

MSSP
  server status protocol. for MUD crawlers/listings.

MSLP
  clickable links in terminal.


content
-------

MXP
  markup for enhanced text (zuggsoft).

MSP
  sound protocol (zuggsoft).

MCMP
  modernized sound via gmcp (mudlet).

MCP
  moo client protocol.


our telnetlib3 already handles
-------------------------------
GMCP, MSDP, NAWS, CHARSET, MTTS


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 5: clients and what they support
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


top clients by protocol support
--------------------------------

mudlet
  gmcp, mssp, mcmp, msp, atcp, msdp, mxp, mmp. lua scripting. the dominant
  modern client.

tintin++
  gmcp, mccp, mccp3, msdp, mslp, mssp, mtts, mmcp, naws, mnes. terminal-based.

blightmud
  tls, gmcp, msdp, mccp2. terminal-based, rust.

mushclient
  mxp, mccp, mmcp, mtts. windows only.

cmud
  mxp, msp, mcp, mccp, atcp. commercial, windows.

axmud
  mxp, gmcp, msdp, mnes, mtts. perl/gtk3.


web clients
-----------

mudportal
  mccp, mxp, msdp, gmcp, atcp, mtts. proxy + web client.

grapevine
  mud listing with web client.

xterm.js approach
  terminal emulator in browser pointing at telnet (our dreambook mentions this).


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 6: what's missing from our INDEX.txt
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

repos worth adding for study:

  https://github.com/dworkin/dgd
    DGD driver - independent LPC driver, not derived from lpmud

  https://github.com/EmpireMUD/EmpireMUD-2.0-Beta
    EmpireMUD - persistent world map, circlemud derivative

  https://github.com/wowpin/dumserver
    DUM/dumserver - modern python MU* engine

  https://github.com/irmen/Tale
    Tale - python MUD/IF framework by irmen

  https://github.com/fuzzball-muck/fuzzball
    Fuzzball MUCK - tinymuck server

  https://github.com/necanthrope/HellCore
    HellCore - lambdamoo fork

  https://github.com/luciensadi/AwakeMUD
    AwakeMUD - community fork, C++

  https://github.com/mainframecity/fluxspace
    fluxspace - elixir MUD engine

  https://github.com/maldorne/mudos
    MudOS - historical fork

  https://github.com/cotillion/cd-gamedriver
    CD MUD driver - alternative LPC driver

  https://github.com/DikuMUDOmnibus
    DikuMUD Omnibus - 100+ diku-related projects

  https://github.com/mudhistoricalsociety
    MUD Historical Society - preservation


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION 7: key takeaways for our design
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

observations relevant to our mudlib:


1. driver/mudlib separation
----------------------------
the driver/mudlib split (lpc model) is the most influential architectural
decision in MUD history.

we get a version of this with python: the engine is the "driver", game
content/logic is the "mudlib". keeping this separation clean matters.


2. composable command sets
--------------------------
command sets that compose (evennia's cmdset merging) are a genuinely good idea
for session modes.

our mode stack (normal/combat/editor/IF) maps directly to pushing/popping
cmdsets.


3. room graphs vs grids
-----------------------
everyone uses room graphs. our tile grid is unusual.

the dreambook's hybrid (grid overworld + room interiors) is the right call - it
gives us the spatial consistency of a grid with the narrative flexibility of
rooms.


4. in-world creation
--------------------
in-world creation is the MOO dream.

we don't need a full programming language, but the DSL for IF/puzzles needs to
be powerful enough that people can create real content from a telnet client.


5. persistence strategy
-----------------------
world in files + player state in sqlite is actually the cleanest approach.

most modern engines do something similar. don't fight the pattern.


6. protocol investment
----------------------
gmcp is the protocol to invest in.

it's what mudlet and tintin++ both support well, and it's how we'll send
structured data (maps, gauges, inventory) to smart clients.


7. tick-based for combat
------------------------
tick-based is right for timing-based combat. event-driven is cleaner for
everything else.

hybrid is fine - main loop ticks, but non-combat systems can be event-driven.


8. prototype/spawn pattern
--------------------------
the prototype/spawn pattern (evennia, diku zone resets) is how everyone handles
mob/item templates.

define once, instantiate many.


9. entity component system
---------------------------
graphicmud uses ECS (composition over inheritance). entities are bags of
components, archetypes define which components they get.

most MUDs use deep inheritance hierarchies (Object -> Item -> Weapon -> Sword).
ECS avoids the diamond problem and makes it easier to add cross-cutting features.

worth considering if our entity model gets complex.


10. capability-based rendering
------------------------------
graphicmud's symbol system — same tile has ascii, ansi, and sixel representations,
client detection picks the richest — is elegant.

we already adapt to NAWS for viewport size. extending this pattern to rendering
quality (plain text -> colored text -> graphics) would let us support everything
from raw telnet to sixel-capable terminals.
