Mapping & Navigation
A comprehensive reference on how MUDs represent space, help players navigate it, and how client-side mappers render it. Covers everything from room graph fundamentals to pathfinding algorithms to Aardwolf’s continent coordinate system.
1. Room-Based vs Coordinate-Based Geography
1.1 Traditional Room Graph
The classic MUD spatial model treats the world as a directed graph where each node is a “room” and edges are exits. Rooms have no inherent position in space – they exist only by virtue of their connections.
Structure:
- Each room has a unique ID (vnum), a name, a description, and a set of exits
- Exits map a direction keyword (n/s/e/w/u/d, plus custom exits) to a destination room ID
- No coordinates required; rooms are connected purely by logical links
- The world is essentially a web of interconnected nodes, analogous to hyperlinked web pages
Characteristics:
- No consistent scale: One room might represent a closet, another an entire forest. Two “plains” areas might abut geographically but have no connecting exits between their interiors
- Flexible topology: Rooms can connect in non-Euclidean ways (a hallway that loops back on itself, a door that leads somewhere “impossible”)
- Simple to build: Builders create rooms and link exits without worrying about coordinate collisions
- Hard to map visually: Without coordinates, client-side mappers must infer positions from movement directions, leading to overlapping rooms
Pros:
- Extremely flexible – any topology is possible
- Easy for builders to create and modify areas
- Low memory overhead per room
- Natural for indoor/dungeon environments where strict geometry doesn’t matter
Cons:
- No inherent sense of distance or direction between non-adjacent rooms
- Client automappers struggle with overlap and non-Euclidean connections
- Wilderness/overworld areas feel artificial as discrete rooms
- Pathfinding must operate on the raw graph (no heuristic shortcuts like A*)
1.2 Coordinate/Grid Systems
Some MUDs assign every room an (x, y) or (x, y, z) coordinate, placing the world on an explicit spatial grid.
Structure:
- Each room has coordinates local to its area or global to the world
- Movement in a cardinal direction changes coordinates predictably (north = y+1, east = x+1, etc.)
- Rooms can be generated procedurally from a heightmap or terrain function
- Exits are often implicit: if a room exists at the adjacent coordinate, you can move there
Characteristics:
- Consistent scale: Each grid cell represents the same spatial unit
- Natural for wilderness: Open terrain, oceans, and overworld maps work well on grids
- Enables spatial queries: “What’s within 5 tiles of me?” is trivial with coordinates
- Supports line-of-sight, range, and area-of-effect calculations
Approaches:
- Pure function terrain: A function takes coordinates as input and returns terrain type (using Perlin noise, fractals, etc.). No need to store every room explicitly
- Height-mapped 3D: A z-level variable per tile allows vertical structures. Tiles above the base level default to empty/air unless specified. One byte per tile for height data keeps memory minimal
- Tile iteration: Rather than calculating movement/LOS from coordinates alone, iterate over tiles between source and destination, allowing complex vertical geometry (cliffs, towers)
Pros:
- Realistic spatial relationships; great for ranged combat, archery, area effects
- Client mappers can render accurately with no guesswork
- Supports procedural generation of large wilderness areas
- Enables A* pathfinding with coordinate-based heuristics
Cons:
- Less flexible topology – non-Euclidean spaces require special handling
- Grid artifacts: diagonal movement is longer than cardinal (unless hex grid)
- Large open worlds consume more memory if every cell is stored
- Builders must respect coordinate constraints
1.3 Wilderness / Overworld Systems
A common hybrid where the main world map uses coordinates but interior areas (dungeons, cities) use room graphs.
Evennia’s Wilderness Contrib:
- Provides a wilderness map without creating actual room objects in the database
- As you move, you re-enter the same room object but its description changes based on your coordinates
- Enables huge areas with minimal database footprint
- Works well when rooms are relatively similar (terrain variations, not unique locations)
Typical Implementation:
- Overworld stored as a 2D array or generated from a terrain function
- Each cell has a terrain type determining description, movement cost, encounters
- Entrances to instanced areas (dungeons, towns) are placed at specific coordinates
- Players see a minimap of surrounding terrain when on the overworld
1.4 Hybrid Approaches
Most modern MUDs use some combination:
- Aardwolf: Room-based graph with continent coordinates overlaid. Each room has a vnum (graph node) plus (x, y, continent_id) coordinates for mapper positioning. Interior areas may lack coordinates (returning -1 values)
- Ranvier: Rooms support optional 3D coordinates
[x, y, z]local to their area. ThegetExits()method returns both explicitly defined exits and exits inferred from adjacent coordinates - Evennia XYZGrid: Maps drawn as ASCII art are parsed into room graphs with coordinates. Pathfinding uses Dijkstra within each map. Transitions between maps (z-levels) handled via special teleport nodes
Design considerations for hybrid systems:
- Coordinate rooms should have consistent scale; graph rooms can vary
- Need clear transitions between coordinate space and graph space
- Client mappers need to handle both modes (GMCP coordinate data vs. inferred positions)
- Pathfinding may need different algorithms for each space type
2. Automapping Systems
2.1 Mudlet Mapper
The most widely-used modern MUD mapper. Renders a 2D graphical map in a panel alongside the text output.
GMCP Integration (IRE Mapping Script):
The mapper consumes GMCP Room.Info data to build maps automatically. Required fields:
| Field | Purpose |
|---|---|
Room.Info.num | Unique room ID; used as the mapper’s internal room identifier |
Room.Info.name | Room name displayed on hover |
Room.Info.area | Area name; rooms auto-assigned to mapper areas |
Room.Info.environment | Environment/terrain type; determines room color on the map |
Room.Info.exits | Table of {direction: destination_room_id}; builds exit links |
Key Lua API Functions:
Room management:
addRoom(roomID)– Create a roomsetRoomName(roomID, name)– Set display namesetRoomCoordinates(roomID, x, y, z)– Position on the map canvassetRoomArea(roomID, areaID)– Assign to an areasetRoomEnv(roomID, envID)– Set environment (determines color)setRoomWeight(roomID, weight)– Pathfinding cost (higher = avoided)lockRoom(roomID, locked)– Exclude from pathfinding entirelysetRoomUserData(roomID, key, value)– Store arbitrary metadata
Exit management:
setExit(fromID, toID, direction)– Create a standard exitaddSpecialExit(fromID, toID, command)– Create a custom/special exitgetRoomExits(roomID)– Returns{direction: destination_id}tablegetSpecialExits(roomID)– Returns custom exits separately
Navigation:
getPath(fromID, toID)– Calculate shortest path; populatesspeedWalkDir(directions) andspeedWalkPath(room IDs)speedwalk(fromID, toID, delay, reverse)– Execute the walk
Map storage:
- Maps stored as binary files (
.dat) in the Mudlet profile directory - One map file per profile; contains all rooms, areas, and metadata
- Can be shared between users for pre-built maps
The IRE Mapping Script was developed for Iron Realms Entertainment games but can be adapted to any GMCP-capable MUD by implementing the required Room.Info fields.
2.2 MUSHclient Mapper
Nick Gammon’s generic graphical mapper module for MUSHclient.
Architecture:
- Callback-based design: the mapper module is MUD-neutral
- A calling plugin provides room data through a
get_room()callback function - The callback returns: room UID, name, area, exit mappings, visual properties (border color, fill color, pen styles), hover messages
Rendering:
- Uses breadth-first traversal from the current room outward
- Draws rooms at fixed screen distances per direction
- Arrows indicate one-way exits
- When multiple rooms map to the same screen position, the closest (first-discovered) room wins
- Performance: ~400 rooms rendered in ~0.07 seconds; ~100 rooms in ~0.01 seconds
Features:
- Left-click speedwalking to any visible room via shortest route
- Room search with configurable conditions
- Individual room coloring for terrain types, shops, trainers, etc.
- Hover tooltips with room info
GMCP Mapper Plugin:
- Processes
room.infoGMCP data: num, name, zone, terrain, exits, coordinates - Maps rooms as you explore; pre-loaded maps available for some MUDs (Aardwolf ships with continent maps)
2.3 TinTin++ Mapping
Terminal-based mapper with extensive command-line controls. No GUI – renders ASCII maps directly in the terminal.
Map Creation:
#map create <size>– Initialize map (default 50,000 rooms)#map dig <exit> [new|<vnum>]– Create exits and rooms#map link <direction> <room> [both]– Connect existing rooms#map insert <direction> [roomflag]– Insert room between two connected rooms
Room Properties:
- Room flags:
avoid,block,hide,invis,leave,noglobal,void,static avoid– Pathfinder routes around this roomblock– Automapper won’t move through this roomhide– Map display stops at this roomvoid– Spacing room for visual layout (not a real room)static– Disables automatic exit creation when moving- Exit flags via
#map exitflag: AVOID, BLOCK, HIDE, INVIS
Navigation:
#map find <name> [filters]– Calculate shortest path (stored in#path)#map run <room> [delay]– Pathfind and auto-walk#map goto <vnum|name>– Teleport to a room on the map#map explore <exit>– Follow a direction until intersection or dead end#map travel <direction> <delay>– Walk in one direction with delay between steps
Display Modes:
#map map <rows> <cols>– Render ASCII map to outputasciigraphicsflag – Detailed display with diagonal exitssymbolgraphicsflag – Compact 1x1 symbol displayvtgraphicsflag – Uses terminal line-drawing charactersvtmapflag – Persistent map in top split-screen panelpancakeflag – Shows stacked vertical layers
Terrain System:
#map terrain <name> <symbol> [flags]– Define terrain types with density/spread options- Custom terrain rendering affects map display symbols and colors
File Operations:
#map read/write <filename>– Load/save maps#map sync <filename>– Merge maps without overwriting
2.4 Required Server Data for Automapping
For any automapper to work, the server must provide:
Minimum viable:
- Room identifier (unique ID or hash of name+exits)
- Exit directions and destinations
- Reliable movement confirmation (so the mapper knows when you’ve actually moved)
Ideal (GMCP):
- Unique room ID number
- Room name
- Area/zone name
- Terrain/environment type
- Exit table with destination IDs
- Coordinates (x, y, z or equivalent)
- Room flags (no-magic, no-mob, death trap, etc.)
Without GMCP, mappers must parse room names and exits from text output using triggers, which is fragile and error-prone.
3. In-Game Map Commands
3.1 ASCII Minimap Generation
Many MUDs provide a server-side map command that generates an ASCII representation of nearby rooms.
Evennia’s Algorithm (Recursive DFS):
- Start at the player’s current room
- A “worm” walks outward in each cardinal direction, drawing rooms as it goes
- Track position with (curX, curY) coordinates on a 2D character grid
worm_has_mappeddictionary prevents revisiting rooms- Stop after reaching max distance (calculated as
(min(width, height) - 1) / 2) - Grid dimensions must be odd numbers to ensure a center point exists
Symbol conventions:
| Symbol | Meaning |
|---|---|
[@] | Player’s current position |
[ ] or [.] | Standard room |
- | East-west connection |
| | North-south connection |
/ \ | Diagonal connection |
[#] | Blocked/wall |
[$] | Shop |
[!] | Quest NPC |
@ | Player location (Discworld style) |
* | Room (Discworld) |
+ | Door (Discworld) |
$ | Room with living things (Discworld) |
3.2 Discworld MUD Map Command
One of the most polished in-game map implementations:
Syntax variants:
map– Default display (configurable between ASCII and text)map ascii– Force ASCII art mapmap text– Text-based directionsmap door text– Shows objects in line of sight
Map contexts:
- City maps: Show immediate surroundings with rooms, exits, and doors
- Terrain maps: Display wilderness areas where
walkandjourneycommands apply
Display options:
options output map plain=on– Disable coloroptions output map mxp=on– Enable clickable MXP room linksoptions output map look/lookcity– Auto-show map on entering roomsoptions output map reversecolour=on– Swap foreground/background colors
3.3 Aardwolf Map Command
Displays an overhead minimap of current room and surroundings:
- Shows nearby mobs, doors, and shops
- Indicates exit directions
- Integrates with the GMCP mapper for client-side rendering
3.4 Implementation Considerations
Generating ASCII maps server-side:
- BFS or DFS from the player’s room, limited by depth
- Map each discovered room to a position on a character grid
- Handle overlapping rooms (first-discovered wins, or skip conflicting positions)
- Only cardinal directions produce clean maps; diagonals and custom exits complicate layout
- Custom fonts with embedded symbols (trees, water) can enhance display but require client-side font installation
Map integration with room display:
- Can be shown automatically above room descriptions on
look - Or invoked explicitly with a
mapcommand - Configurable size (3x3, 5x5, 9x9 tiles, etc.)
4. Navigation Aids
4.1 Speedwalking
Automated movement through a sequence of rooms.
Syntax formats:
- Shorthand:
3n2e4s= north 3 times, east 2 times, south 4 times - Verbose:
IN N 3W 2U W= in, north, west 3 times, up 2 times, west - Client-specific: Mudlet’s
speedwalk()function, TinTin++’s#map run
Key features:
- Configurable delay between moves (to avoid server-side spam protection)
- Route recording: record a path manually, replay it by name later
- Mudlet stores routes in
speedWalkDir(directions) andspeedWalkPath(room IDs) tables - Room weights influence pathfinding: higher weight = less preferred route
- Locked rooms excluded from pathfinding entirely
Risks:
- If interrupted mid-walk (by a mob, closed door, or lag), the player ends up lost
- Some MUDs penalize rapid movement or have anti-speedwalk timers
- One-way exits can strand a player if the path is reversed naively
4.2 Recall and Teleport
Recall:
- Classic Diku/Merc mechanic: instantly return to a designated “hometown” room
- Typically available as a spell, scroll, or potion
- Common restrictions: can’t recall from combat, can’t recall from no-recall rooms, lag/delay before teleport (e.g., 5-second cast time with re-check for combat)
- Some MUDs confuse the player for 2 rounds before teleporting to allow PvP counterplay
Teleport:
- Higher-level spell to teleport to a random or targeted room
- Portal spells create temporary two-way links between rooms
- Summon spells pull another player to your location
Hometown/Bind points:
- Players set their recall destination (hometown, guild hall, etc.)
- Some MUDs allow multiple bind points
4.3 Portals
- Permanent portals: fixed links between distant rooms (connecting continents, linking hub cities)
- Temporary portals: player-created, time-limited passages
- Quest portals: appear only under certain conditions
- Portal rooms: dedicated rooms that serve as transit hubs with multiple portal destinations
4.4 Hunt and Track
Hunt:
- Locates a specific mob or player within the area
- Returns the direction to move toward the target
- Aardwolf’s hunt trick:
hunt 1.<target>,hunt 2.<target>, etc. to enumerate instances, then use the count withwhereto find the specific room
Track:
- Skill that shows a trail of footprints leading toward a target
- May have a chance of failure based on skill level
- Some rooms flagged NOTRACK prevent tracking through them
Scan:
- Shows creatures/players in adjacent rooms (typically 2-3 rooms in each direction)
scan <direction>to scan a specific direction- Doors flagged
noscanblock scanning
4.5 Where and Area Finding
where– Lists visible players/mobs in the current area with their room nameswhere <target>– Locates a specific target within the areaareas/area list– Shows all areas with level ranges and continent locations- Mapper-based:
mapper areas(Aardwolf) finds area exits within search depth mapper find <name>– Searches for rooms by name within configurable depthmapper quest/mapper shops– Locates quest NPCs and shops
5. Aardwolf’s Mapping System
5.1 GMCP Mapper
Aardwolf’s GMCP mapper was authored by Nick Gammon and modified for GMCP compatibility by Lasher. Originally a MUSHclient plugin, now also implemented for Mudlet.
GMCP room.info Data:
{
"num": 32418,
"name": "The Grand City of Aylor",
"zone": "aylor",
"terrain": "city",
"details": "",
"exits": { "n": 32419, "e": 32420, "s": 32415, "w": 32611 },
"coord": { "id": 0, "x": 37, "y": 19, "cont": 0 }
}
Key fields:
num: Unique room vnumexits: Only standard directions (n/e/s/w/u/d); custom exits omitted for mapping purposescoord.id: Continent ID (0-6)coord.x,coord.y: Position on the continent mapcoord.cont: Binary flag – 1 if the room is on a continent, 0 if inside an area- Inside mazes, room IDs are hidden – only direction names appear in exits
Non-mappable rooms (clan halls, etc.) return -1 for num, coord.id, x, and y with empty exits.
5.2 The Seven Continents
The world of Andolor:
| ID | Continent | Description |
|---|---|---|
| 0 | Mesolar | Central civilization hub. Great cities, trade routes, alliances. Safest and most populated. |
| 1 | Southern Ocean (Iridian Sea) | Island societies, rumored underwater civilizations |
| 2 | Gelidus | Frozen north. Permanently away from the sun, covered in ice and ancient glaciers |
| 3 | Abend | The Dark Continent. West of Mesolar across the Banalog Ocean. Perpetual twilight, dangerous |
| 4 | Alagh | The Blood Continent. East of Mesolar across the Aphasian Ocean. Deserts, jungles, centuries of warfare |
| 5 | Uncharted Oceans | Vast unexplored waters with occasional islands |
| 6 | Vidblain | Rumored fifth continent (“ever dark”), unverified |
World properties:
- Andolor orbits a single sun but does not rotate; three moons create rapid day-night cycles
- The world is mostly circular: traveling far enough in any direction returns you near your starting point
- Over 30,000 unique rooms across all continents
5.3 Mapper Features
- Pre-loaded with continent maps and lower-level area maps
- Each square on the mapper represents a single room
- Current location highlighted in pink
- Unvisited rooms shown with dotted lines
- Diagonal lines indicate up/down exits
- Half-lines indicate one-way passages
- Recently traveled paths display as bolder lines
- Hover tooltips show room names and exit destinations
Mapper commands:
mapper find <name>– Search rooms (default 50-room depth, adjustable)mapper goto <room_num>– Navigate to a room by vnummapper where <room>– Display directions to a roommapper areas– List area exits within search depthmapper quest/mapper shops– Locate quest NPCs and shops- Bookmarking system via right-click on rooms
5.4 Gaardian Map Archives
Community resource at maps.gaardian.com:
- 264 publicly available area maps, automatically generated from dynamic content
- Maps update within seconds of area changes
- Show room names, connections, portals (marked with link icons), locked doors (hover details)
- Searchable by room name
- Screen-reader-friendly VI index for accessibility
- Copyleft licensing; community sharing with attribution
5.5 Navigation Commands
exits– Shows all exits; parenthesized exits are doors that must be opened; “other” exits are custom exits entered by keywordscan– Shows creatures/players in adjacent rooms (3-room range per direction)hunt <target>– Direction toward a mob/playerwhere <target>– In-area room location of a mob/playermap– Overhead minimap of surroundings
6. Spatial Design Patterns
6.1 Hub-and-Spoke
A central hub room (city square, guild hall, crossroads) connects to multiple destination areas radiating outward.
Applications:
- Hub cities: A central city with exits leading to surrounding wilderness areas, dungeons, and other zones. Midgaard in CircleMUD, Aylor in Aardwolf
- Portal hubs: A room with multiple portals to different continents or planes
- Guild halls: Central location with exits to training rooms, shops, quest boards
Design principles:
- Hub should be memorable and easy to find (recall target, portal destination)
- Spoke areas should have clear thematic identity
- Consider multiple hubs at different scales (world hubs, continent hubs, area hubs)
6.2 Maze Design
Intentionally confusing areas that challenge navigation.
Techniques:
- Identical room descriptions: Every room looks the same, forcing players to map carefully
- One-way exits: Entering a room from the north doesn’t mean going south returns you
- Randomized exits: Exits shuffle periodically or on each visit
- Loops: Paths that circle back on themselves
- Dead ends: Force backtracking
- Hidden exits: Critical paths concealed behind search/examine commands
Aardwolf approach: Inside mazes, GMCP room IDs are hidden in exit data (only directions shown), deliberately complicating automapping.
Best practices:
- Mazes should reward exploration, not just punish it (treasure, shortcuts, secrets)
- Provide hints in room descriptions for observant players
- Limit maze size; enormous mazes are tedious, not challenging
- Consider making mazes optional rather than required for progression
6.3 Vertical Space
Standard vertical exits:
upanddowndirections in the room graph- Sector types: UNDERWATER (below water surface), FLYING (requires flight ability)
- CircleMUD sector types: WATER_SWIM (6), WATER_NOSWIM (7), UNDERWATER (8), FLYING (9)
Height-mapped tiles:
- Z-level variable per tile for multi-story structures
- Default: tiles above ground level are empty/air unless specified
- Enables towers, cliffs, multi-floor buildings, caves beneath the surface
Evennia XYZGrid approach:
- Each z-level is a separate 2D map
u/dlink characters in the ASCII map definition connect levels- Special
fly/divecommands for vertical movement - Pathfinding operates within each map only; cross-map (vertical) transit not included in auto-walk
Design considerations:
- Vertical movement should feel distinct from horizontal (climbing, flying, diving, falling)
- Consider movement cost differences (climbing takes more effort)
- Falling damage for uncontrolled descent
- Flight/swim requirements gate access to vertical areas
6.4 Water and Underwater
- Surface water: Requires swimming ability or a boat; higher movement cost
- Deep water: Boat required, no swimming
- Underwater: Requires water breathing ability; may have different exit rules, limited visibility
- Currents: One-way exits representing river flow; rooms that push players downstream
6.5 Flying and Aerial
- Rooms with sector type FLYING require flight ability to enter
- Can create multi-layer maps (ground level, treetop level, sky level)
- Flying creatures can traverse flying rooms as shortcuts over ground obstacles
- Consider: can players see ground-level rooms from the air? (vertical scan)
6.6 Area Transitions
How areas connect to each other:
- Direct exits: A room in area A has an exit leading to a room in area B
- Portal/teleport transitions: Magical transport between distant areas
- Overworld entry points: Walk to a coordinate on the overworld map to enter an area
- Level-gated transitions: Area entrances that require minimum level or quest completion
- One-way entries: Enter an area through a chute/fall but must find an alternate exit
CircleMUD zone design:
- Each zone is a geographically coherent region, typically under 100 rooms
- Large regions subdivided into multiple zones (e.g., Midgaard city + residential area)
- Zones can define their own mobs, objects, shops, and reset behaviors
6.7 Secret and Hidden Exits
Types:
- Hidden doors: Don’t appear in exit list; require
searchorexamineto discover - Keyword doors: Require knowing the exact keyword (no abbreviations) to open
- Lever/chain doors: Opened by interacting with an object in the room
- Timed doors: Open based on in-game time, season, or moon phase
- Spell-opened doors: Require casting a specific spell (knock, passwall)
- Quest-gated exits: Appear only after completing a quest
Aardwolf exit flags:
hidden– Completely invisible, requires full keyword to interactnoscan– Invisible to scan commandnopass– Negates pass-through-door effectspickproof– Cannot be picked or bashed open- Custom exits support custom enter/exit/char messages and up to 5 alternate command keywords
7. Technical Implementation
7.1 Room Data Structures
CircleMUD Room Definition (C struct):
room_index_data:
- next_room pointer
- people (character list)
- contents (object list)
- extra_descriptions
- area pointer
- exits[6] (one per direction: N/E/S/W/U/D)
- name (string)
- description (string)
- vnum (integer)
- room_flags (bitvector)
- light_level (integer)
- sector_type (integer 0-9)
CircleMUD Room File Format:
#<vnum>
<room name>~
<description>
~
<zone> <room_flags_bitvector> <sector_type>
D<direction 0-5>
<exit description>
~
<door keyword>~
<door_flag> <key_vnum> <destination_vnum>
E
<extra desc keywords>~
<extra description>
~
S
Room Flags (CircleMUD):
| Value | Flag | Effect |
|---|---|---|
| 1 | DARK | Room is dark; requires light source |
| 2 | DEATH | Death trap; character dies on entry |
| 4 | NOMOB | NPCs cannot enter |
| 8 | INDOORS | Indoor room |
| 16 | PEACEFUL | No violence allowed |
| 32 | SOUNDPROOF | Shouts/gossips not heard |
| 64 | NOTRACK | Track skill can’t path through |
| 128 | NOMAGIC | All magic fails |
| 256 | TUNNEL | One player at a time |
| 512 | PRIVATE | No teleport if 2+ people present |
| 1024 | GODROOM | Immortal-only access |
Sector Types:
| ID | Type | Notes |
|---|---|---|
| 0 | INSIDE | Low movement cost |
| 1 | CITY | Streets |
| 2 | FIELD | Open terrain |
| 3 | FOREST | Dense forest |
| 4 | HILLS | Foothills |
| 5 | MOUNTAIN | Steep terrain, high movement cost |
| 6 | WATER_SWIM | Swimmable water |
| 7 | WATER_NOSWIM | Requires boat |
| 8 | UNDERWATER | Requires water breathing |
| 9 | FLYING | Requires flight |
Ranvier Room Definition (YAML):
- id: "entrance"
title: "Cave Entrance"
description: "A dark cave stretches before you."
coordinates: [0, 0, 0] # Optional [x, y, z]
script: "entrance-script" # Optional behavior script
metadata:
terrain: "underground"
npcs:
- id: "myarea:goblin"
respawnChance: 50
maxLoad: 3
items:
- id: "myarea:torch"
exits:
- direction: "north"
roomId: "myarea:deep-cave"
leaveMessage: "crawls northward into the darkness"
doors:
"myarea:outside":
lockedBy: "myarea:rusty-key"
locked: true
closed: true
Key design insight from Ranvier: Exits can be both explicitly defined and inferred from coordinates. Room.getExits() returns both types, letting builders use whichever approach fits the area.
7.2 Pathfinding
BFS (Breadth-First Search):
- Finds shortest path by hop count (unweighted)
- Ideal when all exits have equal movement cost
- Explores all rooms at distance N before distance N+1
- Time complexity: O(V + E) where V = rooms, E = exits
- Simple to implement; natural fit for room graphs
Dijkstra’s Algorithm:
- Finds shortest path by total weight (weighted graph)
- Required when rooms or exits have different movement costs (terrain, danger, preferences)
- Uses a priority queue; always expands the cheapest unexplored node
- Time complexity: O((V + E) log V) with a binary heap
- Mudlet mapper and Evennia XYZGrid both use Dijkstra
- Room weights in Mudlet:
setRoomWeight(roomID, weight)– higher = more costly - Evennia: link weights default to 1; long visual link chains are averaged so
#-#costs the same as#----#
A (A-Star):*
- Dijkstra + heuristic estimate to goal
- Only works if rooms have spatial coordinates (for distance estimation)
- Faster than Dijkstra for coordinate-based worlds
- Not applicable to pure room graphs without coordinates
Practical MUD pathfinding considerations:
- Most MUDs use BFS or Dijkstra; A* is rare because many areas lack coordinates
- Room flags affect pathfinding: AVOID rooms get high weights, BLOCK rooms are excluded
- Special exits (portals, custom commands) must be included in the graph
- One-way exits create directed edges; the reverse path may not exist
- Locked doors may or may not be traversable depending on implementation
- Performance: Evennia reports 500-step paths over 20,000 rooms in under 0.1 seconds with Dijkstra + caching
7.3 One-Way Exits
- Created by defining an exit from room A to room B without a reciprocal exit from B to A
- Common uses: chutes, falls, slides, river currents, trap doors, maze connections
- Aardwolf mapper displays one-way passages as half-lines
- TinTin++
#map link <direction> <room>(withoutbothflag) creates one-way links - Pathfinding must treat the graph as directed; BFS/Dijkstra handle this natively
- Client mappers need visual indicators so players know they can’t go back
7.4 Dynamic and Temporary Rooms
Dynamic rooms:
- Rooms whose properties change based on game state (time of day, weather, quest progress)
- Description, exits, or flags may change without the room being destroyed/recreated
- Server-side scripts can modify room attributes on events
Temporary rooms:
- Created at runtime and destroyed when no longer needed
- Use cases: player housing, summoned pocket dimensions, combat arenas
- Must be excluded from persistent maps or handled with volatile map markers
- Client mappers need to handle rooms that may not exist on reconnect
7.5 Instanced Areas
Areas where each player or group gets their own private copy:
- Same area definition, multiple simultaneous instances
- Prevents player conflicts in quest areas
- Room IDs must be dynamically generated or namespaced per instance
- GMCP must communicate instance-specific room IDs to mappers
- Procedural Realms uses automatic GMCP mapping with instanced zones and terrain-based room styling
- After the instance closes, rooms are cleaned up and map data becomes stale
Implementation approaches:
- Template area with prototype rooms; spawn copies with unique IDs per instance
- Namespace room IDs:
instance_42:room_301 - Track instance lifecycle (creation, active, cleanup)
- Coordinate with mapper: either don’t map instances, or use volatile/temporary map layers
7.6 Evennia XYZGrid – A Complete Reference Implementation
Worth studying as a modern, well-documented approach:
ASCII map definition:
+ 0 1 2 3 4
4 #-#---#
| |
3 # #
|
2 #-#-#
|
1 # #-#
| |
0 #-#---#
+ 0 1 2 3 4
Legend characters:
#– Room node-|– Two-way horizontal/vertical links/\– Diagonal links><^v– One-way directional linksud– Up/down linkst– Same-map teleporter (paired)T– Cross-map transition nodeI– Interrupt node (pathfinding checkpoint)b– Blocked link (pathfinder avoids, exit still exists)o– Router link (non-orthogonal connections)
Coordinate system:
- Origin (0,0) at bottom-left
- Each coordinate position occupies every-other character in the ASCII string
- Half-coordinates (x.5) describe link positions between nodes
- Z-coordinate is the map name/identifier
Performance:
- Dijkstra pathfinding with cached results (pickled to disk)
- 500-step paths across 20,000 rooms: < 0.1 seconds
- Rerunning
spawnupdates existing rooms safely without duplicating
Sources
Room-Based vs Coordinate Systems
- A Spatial Representation of the Virtual World – Raph Koster
- Coordinate AND Room Based Codebase? – Top Mud Sites Forum
- Coordinate/tile based MUDs and 3D terrain – Gammon Forum
- Spacial Systems – MudBytes
Automapping
- Mudlet Manual: Mapper Functions
- Mudlet Manual: Mapper
- IRE Mapping Script – Mudlet Wiki
- Adding Your MUD to the IRE Mapping Script
- MUSHclient Generic Graphical Mapper
- GMCP Mapper Plugin – Gammon Forum
- TinTin++ Map Commands
- TinTin++ Mapping Manual
Aardwolf
- GMCP in Aardwolf MUD
- Aardwolf GMCP Mapper
- Aardwolf RPG World Overview
- Aardwolf Building: Editing Exits
- Aardwolf Area List
- The Gaardian Map Archives
- Aardwolf Mudlet GMCP Mapper (GitHub)
- Aardwolf GMCP Mapper with Speedwalks (Gist)
- Aardwolf Hunt Trick
- Aardwolf Commands Reference
- Aardwolf Exploration Guide
MUD Design and Implementation
- CircleMUD Builder’s Manual: World Files
- CircleMUD Builder’s Manual: Mechanics
- Ranvier MUD: Rooms
- Ranvier MUD: Creating an Area
- MUD Cookbook: Design Meets Implementation
- Pathfinding in a MUD – GameDev.net