One of the first decisions all game designers have to make somewhat early in the design process is how to represent and draw maps in their world. There are several strategies, mostly predicated upon the type of world design you have architected. This falls into three categories: room-based, coordinate, and hybrid. These categories describe how the world is represented and presented to the user and how the user navigates from one location to another.
This is probably the most prevalent in the MUDs found in use today. It's probably also the simplest to represent and implement. Each location, such as a room, section of road, a shop or building, etc, is its own separate entity called a room and often supports ten directions: north, south, east, west, northeast, northwest, southeast, southwest, up, and down. Some older MUDs only support the four cardinal directions. You move from room to room through the use of navigation commands like 'n' for north.
This form of world lends itself to a grid-based map where every grid is a room or a path. The figure below shows an example with a few rooms.
A coordinate system is based on a Cartesian coordinate graph. Locations are assigned and represented with coordinates such as (x,y) or (x,y,z). Players move around often by issuing movement commands like 'move shop' or 'go ' where is a descriptive landmark from the area description. Naturally, a hallmark of coordinate-based worlds are landmarks. Coordinate worlds are a little more difficult to implement because they are not so conveniently compartmentalized like room-based worlds are.
A hybrid world is really just a combination of room-based and coordinate-based worlds. They are often represented by rooms having internal coordinates. Movement from location to location typically is accomplished in the same manner as with room-based worlds but once inside a room it can have custom and varying dimensions. This allows more precise positioning of objects and players inside the room. Objects can now obstruct the line-of-site of players or block their movement or even provide cover and concealment in combat situations. The world knows the relative positions of every object and player in a room compared to each other. This is the implementation that Government SanctionedSM uses for its world.
How is the world actually represented in the game? It's actually a very straight-forward setup. Each room is instantiated as a room object that has certain actions and properties associated with it. Actions include firing an event when a player enters a room, and adding or removing players from the room. Properties include its lighting conditions, whether its inside or outside, and lists of containers and their contents.
When a player attempts to move in a given direction, the exit is first checked to see if it allows it (the door could be locked or may not be a valid exit at all). If it allows movement, the room at the other end of the exit fires off a PlayerEntered event and adds the player to the room. To reduce lag, latency, and load times, all rooms at the end of all exits in the newly entered room are loaded from the database at this time and the rooms at the end of the exits from the previous room that were not taken are removed from memory.
Once entered and all of he contained entities notified via the PlayerEntered event, the player is positioned at the coordinates given by the portal he used to enter the room. Note that it is possible for multiple players to occupy the same coordinate. This doesn't become important unless a combat action is taken and then range becomes an essential element. After entering the room, the player can move to distant locations in the same room with the 'approach' command. If the object of the approach command is another player, the player being approached can either do nothing or 'avoid' the approaching player.
The game engine uses a specific data structure called a Direction-Table Map (DTM) to directly implement the world map. The DTM is generated when the game server first starts up based on the room associations given in the database. While querying the database for the next room would be fast enough, its even faster using a DTM and doesn't take up a database connection or query to do so. The tradeoff is in memory cost. The size in core memory of a DTM with 15,000 * 9 * 8 rooms is 1.08MB; still not very much considering the amount of RAM used on the game server and the cheap cost of memory these days.
Using the example figure given in the discussion of room-based worlds above, here is a direction-table map representing it.
In code the DTM is implemented as a standard 2-dimensional array with the first dimension being the room id and the second dimension representing all the possible directions the room can have. Inside the second dimension are integers of the room ids that moving in that direction would take you. Using the DTM consists of nothing more than indexing the array with the room id of the player's current room and the enumerated type of the direction in which they are moving, as so:
new_room_id = dataTableMap[player->CurrentRoom()][Direction.North];
This yields an incredibly fast lookup, but the astute reader may have noticed one big drawback: lots of wasted space in the array. In fact, statistically, there will be more directions without exits than with exits so in the entire array there will be more unused space than used space. In game coding terms, this space isn't actually "empty" but contains the value -1 meaning "not a valid exit." So really, the "empty" space is quite useful because it tells us if the direction a player is trying to move actually has an exit there.
I hope you've enjoyed this brief foray into the mapping process world representation procedure used in the game. If you have any questions or suggestions you are welcome to contact the development team or project manager. And as always, have fun playing in the world of espionage and intrigue known as Government Sanctioned!