671 lines
21 KiB
Text
671 lines
21 KiB
Text
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.
|