5
\$\begingroup\$

I am working on a text-based game totally from scratch and one thing I am not sure how to do is the map system.

In my mud engine totally writen in Javascript (that will be executed in a Node.js environment), I use that kind of data to design an area and the links between rooms.

/**
 *       [003]-[004]
 *         |     |
 * [001]-[002] [007]
 *         |     |
 *       [005]-[006]
 **/     
var map = {
    "001" : {
        "Id" : "001",
        "Name" : "Room 001",
        "Directions" : {
            "N" : "",
            "S" : "",
            "E" : "002",
            "W" : ""
        }
    },
    "002" : {
        "Id" : "002",
        "Name" : "Room 002",
        "Directions" : {
            "N" : "003",
            "S" : "005",
            "E" : "",
            "W" : "001"
        }
    },
    "003" : {
        "Id" : "003",
        "Name" : "Room 003",
        "Directions" : {
            "N" : "",
            "S" : "002",
            "E" : "004",
            "W" : ""
        }
    },
    "004" : {
        "Id" : "004",
        "Name" : "Room 004",
        "Directions" : {
            "N" : "",
            "S" : "007",
            "E" : "",
            "W" : "003"
        }
    },
    "005" : {
        "Id" : "005",
        "Name" : "Room 005",
        "Directions" : {
            "N" : "002",
            "S" : "",
            "E" : "006",
            "W" : ""
        }
    },
    "006" : {
        "Id" : "006",
        "Name" : "Room 006",
        "Directions" : {
            "N" : "007",
            "S" : "",
            "E" : "",
            "W" : "005"
        }
    },
    "007" : {
        "Id" : "007",
        "Name" : "Room 007",
        "Directions" : {
            "N" : "004",
            "S" : "006",
            "E" : "",
            "W" : ""
        }
    }
};

On the MUD game I am actually playing, the mud command display something like this:

enter image description here

I would like to know in pseudo-code the way to do this in the most efficient way.

Please note that it has a maximum character length for each lines and that the map is centered around You (@).

Thank you for your help!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Note that most MUD developers/designers type out those maps by hand, rather than auto-generating them. This is because the map rarely adheres to a perfect grid. \$\endgroup\$
    – Kylotan
    Commented Oct 31, 2011 at 11:22

1 Answer 1

4
\$\begingroup\$

If your room layout is consistent enough (all connections are the same length and can be traversed in both directions, and no rooms overlap), this is a simple exercise in recursion. Here's a quick piece of code that should do it:

var offsets = {
    "N": [0, -1],
    "E": [+1, 0],
    "S": [0, +1],
    "W": [-1, 0]
};

// recursively plot the locations of the rooms on a grid:

function drawMap ( map, room, grid, x, y ) {
    var loc = x + "," + y;
    if ( loc in grid ) {
        if ( grid[loc] !== room ) {
            // inconsistency detected
        }
        return;
    }
    grid[loc] = room;

    if ( x < grid.minx ) grid.minx = x;
    if ( x > grid.maxx ) grid.maxx = x;
    if ( y < grid.miny ) grid.miny = y;
    if ( y > grid.maxy ) grid.maxy = y;

    var neighbors = map[room].Directions;
    for ( dir in neighbors ) {
        if ( dir in offsets && neighbors[dir] !== "" ) {
            var off = offsets[dir];
            drawMap( map, neighbors[dir], grid, x + off[0], y + off[1] );
        }
        // else handle unknown direction
    }
}

var grid = { "minx" : 0, "maxx" : 0, "miny" : 0, "maxy" : 0 };
drawMap( map, "001", grid, 0, 0 );

// draw the grid in pretty ASCII art:

var mapString = "";
for ( var y = grid.miny; y <= grid.maxy; y++ ) {
    var line1 = "";
    var line2 = "";
    for ( var x = grid.minx; x <= grid.maxx; x++ ) {
        var loc = x + "," + y;
        if ( loc in grid ) {
            var neighbors = map[ grid[loc] ].Directions;
            line1 += ( neighbors.E !== "" ? "+-" : "+ " );
            line2 += ( neighbors.S !== "" ? "| " : "  " );
        } else {
            line1 += "  ";
            line2 += "  ";
        }
    }
    mapString += line1 + "\n" + line2 + "\n";
}

// document.write( "<pre>" + mapString + "</pre>" );

Some possible improvements left as exercises include:

  • Drawing different rooms and connections differently, and generally making the output fancier.
  • Support for diagonal connections.
  • Handling one-way connections correctly.
  • Allowing variable (integer) connection lengths.
  • Detecting situations where a room seems to appear more than once on the map (e.g. where a room is connect to itself), which can cause the code above to recurse forever. (This is fairly easy, just maintain a separate list of mapped rooms.)
  • Automatically resolving situations where two rooms seem to appear in the same location (e.g. where going S,E,N,W gets you into a room other than the one you started in).

The last exercise is a difficult one, since it potentially gets you all the way into the complex realm of arbitrary graph layout algorithms.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .