New MUD Book
© Christopher R. Jones, 2003. All rights reserved.
While the software will be developed using C++ and in an object
oriented way, actual MUD objects will be represented as a limited number
of "templatized" objects. This cuts down on overall memory usage in
large MUDs (you can point to the stereotype object instead of having to
create a new reference for each item in the game), as well as the total
number of objects and hierarchies that need to be created.
There are a number of goals the developer should keep in mind when
designing and programming the MUD. In rough order, these are:
- MUD concept,
- bandwidth utilization,
- processing time,
- memory footprint,
- and persistence.
What kind of multi-user game is being developed? In addition to
deciding on a setting, technical design decisions need to be made;
depending on what the game is like, and how it is implemented, some
design decisions are going to be easier to make (even if not easier to
implement). The following are game architecture concepts, in rough order
of difficulty to implement.
Moving toward using multimedia, tile, or 3D elements requires more
media assets to be created. The greatest development expense in a
commerical game relates to the creation of those elements, rather than
the actual game code.
- Non-Real Time Games
- Turn-based game
- Specialized client (including, say, voice or phone enabled
- Real Time Games
- Text (traditional MUDs)
- Mixed text/multimedia (text game, with multimedia elements
loaded by the client)
- ASCII graphics (Angband)
- Graphical (requires a specialized client)
- 3D environment
This document will examine the creation of a simple multi-user on-line
tile-based MUD. A minimal tile-set will be developed as part of the MUD.
The less bandwidth used, the more users can be connected to the game at
one time. While all communication will occur over the Internet, several
approaches present themselves as possible solutions:
This game will communicate in near-real time between clients and the
server. To minimize bandwidth utilization, the following restrictions
will be placed on the protocol:
- HTTP or other stateless transmissions (appropriate for web-based
or non-real-time games only);
- Text-based messages over TCP (appropriate for traditional text
- UDP messages (less TCP overhead, but lossy);
- TCP messages (more bandwidth used, but less need to provde for
- Mixed TCP/UDP messages (balance messages that can't get lost vs
those that can be lost or arrive out of order).
Messages types will be enumerated later in development and tokenized
where possible. All objects in the game will have unique IDs, so a
typical message may (syntactically) look like:
- Only objects which are visible to the client will be transmitted
to the client. If an object outside of view is updated, it will not be
updated on the client.
- When objects come into view, their appearance, location, and
vector will be transmitted to the client.
- When objects change their vector, that information will be
transmitted to all clients within visual range.
- When objects change their appearance, that information will be
transmitted to all clients within visual range.
- If objects change location (independent of the vector of
movement), that will be transmitted to all clients within visual range.
- When objects take certain actions, those will be transmitted to
- Clients will send messages indicating:
- movement (vector) requests
- appearance change requests
- inventory manipulation requests
- trade command requests (initiate, add object, accept trade,
- speaking or emoting messages
- action requests (attack, use skill, open/close door or
- Clients will receive messages including:
- character updates
- object updates.
<message type> <actor> <target>
Messages may be stacked or concatenated to reduce the total number of
transmissions sent. Connections between the client and server will be
performed with TCP (to limit out of sequence packets) and will use a
single established connection for the duration of the session. Finally,
clients will be throttled so that they may send no more than two
individual transmissions per second to the server, and no stacked
message should exceed 1000 bytes (to accomodate a 1500 MTU).
Massively multi-player games need to process transactions from hundreds
or thousands of players at a time. To accomplish this, the systems are
designed with a few key features:
Server software should be designed to minimize processing time and push
as much appearance processing on the client as possible.
- Templatized objects: each object in the game is designed or
programmed in advance as a template, with instance data provided at
runtime and only instance data persisted.
When something about the monster needs to be determined that is not
limited to run-time data, it is looked up on the monster's template type
by ID (for instance, the goblin's basic stats, appearance, and AI
|The unique instance ID
|Indicates if this is a
unique, single instance (determined by template)
|Points to a template for
this instance (5 is a basic goblin)
|The instance name
|The instance location in the
|The current state of this
instance for the action table
|The natural maximum health
of this monster
|The current health of this
|The natural maximum mana of
|The current mana of this
|The ID of the weapon
instance wielded (if any)
|An array or list of effects
in place on this monster (buffs, DOTs, etc.)
|The inventory available on
this monster upon death.
|The amount of money on this
monster, avaiable upon death.
|Other monsters that will be
alerted when this monster's State changes
|A sorted list of who the
monster hates, first being hated the most
- Low-level languages: high level, interpreted languages are used
in a few places, if at all. The server software needs to run "close to
the metal" in order to support many players and handle all the actions.
- Few processes with minimal threading: breaking the application
across process boundaries is one way of isolating code, but it comes at
a cost in context switching. Likewise, threads cost some processing time
to move between each. Minimizing threading and different running
processes reduces that overhead, at the cost of flexibility in design
and apparent server speed. To overcome this perception, modern clients
make the world look busy, even when little is happening (idle
animations, predictive pathing, etc.). To be avoided at all costs are
systems designed to use one thread per client--many systems can't handle
hundreds or thousands of active threads. MUDs have traditionally acted
in the intervals between
developers should use
poll(), but the principle remains.
- Minimal database access with occasional checkpoints: until
recently, relational databases weren't even used that often. It was more
mmap() a structure onto disk and load it back
in when the system was started. The downside to this, of course, is that
every object in the system will be present at all times. Using ISAM or
flat random data file access techniques are another option. Using a
relational database requires more overhead, in addition to (generally) a
separate database server, but provides access to the data outside of
the application and doesn't require any special application to access,
manipulate, and update the game data when the MUD is not running.
Checkpoints are generally only made to player character objects: most
MUDs will respawn all mobs when the system is restarted, and their
status is inconsequential. On the other hand, players want their
progress and status to be frequently stored in case of a server crash.
- Simple AI. Complex neural networks, systems that learn, and the
like, require a lot more processing power. Short of dedicating servers
to this task, most MUDs will instead use simple scripts to define NPC
reactions and activity:
To further simplify the AI, many mobs can inherit the same behaviors by
pointing to common scripts.
|PC within 100 units, PC
Faction < Neutral
|Change state to aggro,
add PC to hate list
|PC on hate list, PC farther
than 10 units, PC within 500 units
|Move to PC location
|| PC on hate list, PC within
10 units, PC health under 20%
|| Attack PC
|PC on top of hate list, PC
within 10 units
|PC on hate list, PC within
|Move away from PC
|No PC on hate list
|Change state to idle
|No PC within 100 units,
health < max
|Friend changed to Aggro
|Change state to aggro,
add PC to hate list
- Partitioning the application across multiple servers is a good
strategy for improving performance on a per-machine basis, but requires
much additional work, especially is regions are to be split across
servers (many event messages may be lost unless sent between servers so
all clients can receive them). Paritioning applications between servers
will not be covered explicitly in this documentation.
Memory isn't as expensive as it once was, but as long as the
application is being deployed to a 32-bit PC platform, there is an upper
limit of 4 GB. Using a UNIX-like operating system can reduce the total
space needed by the operating system, but there are still limits,
especially if the database and MUD server must be hosted on the same
Minimizing memory utilization by intelligent creation of object
instances (ie, only when a PC is nearby, or when a scripted activity is
taking place) is a useful strategy at the cost of additional complexity.
In short, the developer shouldn't waste memory and should clean up
after himself. Minimizing instance data is key, as is using templates.
This was partially discussed in Processing Time. Strategies for
persisting world data include:
The strategy used will be to persist only player characters. Initial
world state (locations and numbers of mobs, items, etc.) will be loaded
from static data (data that is not modified by in-game activities).
- complete persistence of all instance objects,
- persisting only player characters,
- and persisting nothing.
Data may be stored in:
It's imperative that MUD data be able to be manipulated outside the
system. Some requirements include:
- flat text files
- comma delimited and column ordered
- property files (key-value pair)
- XML data files,
- indexed data files (ISAM),
- memory-mapped data files,
- DBM (key-value pair) files,
- relational databases,
- and object or XML databases.
Flat text files, ISAM, and DBM files can only be manipulated with
custom programs. Memory-mapped data files likewise require a custom
program, and may not function properly outside the MUD itself (depending
on how it was designed). Relational databases allow scripts to be
written in SQL and SQL clients to directly view and manipulate the
system data, as well as making it very easy to add and remove columns
(fields) as code changes. Object and XML databases require a lot more
overhead, are generally more expensive, but also can preserve a natural
object structure without a lot of additional development time to map
the objects to tables.
- changing and updating existing data,
- adding new types of data (to correspond with code changes),
- removing types of data (likewise, to correspond with code
- auditing and searching existing data,
- and adding new objects (characters, for instance).
This system will use a relational database to persist data, as the
template structure described above closely matches the table/row/column
The MUD must provide implementations for a large number of
requirements, in detail, as well as a few broader requirements. From the
broad, high level requirements, the detailed requirements will be
derived and enumerated.
The high level requirements include:
- support for multiple users,
- communication between those users,
- providing multiple, interesting locations,
- providing for conflict
- between users and MUD opponents,
- the user against himself,
- and possibly the user against other users,
- providing for individual achievement and progress,
- and to remain compelling over time.
Support for multiple users
Communication between users
- Each user is distinguished from another while entering commands
and receiving responses
- Each user is tied to an account
- Each user interacts with the MUD world with an avatar or
character (Player Character, or PC)
- Each user connects to the MUD through the Internet with a
specialized client program
Providing multple, interesting locations
- User messages may be tagged as public
- User messages may be tagged as private
- User messages may be tagged as broadcast
- User messages may appear as actions or emotes
- User messages are distributed to the appropriate receivers
- Users may selectively block a class of message
- Users may selectively block messages from a particular user
- Areas may be designed or painted with different textures
- Areas may be designed or architected with
- Areas may have details only visible or available if the PC has
progressed far enough in the game
- Areas may only be accessible if the PC has achieved certain
- Areas may only be accessible if the PC has performed certain
- Areas may be populated with other PCs and MUD NPCs