Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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!

share|improve this question
1  
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. –  Kylotan Oct 31 '11 at 11:22
add comment

1 Answer

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.