---
title: Representing Retro Grid Maps
tags: maps, goldbox, retro
description: Thinking through some requirements around Gold Box style maps.
category: coding
date: 2023-09-22
---

Modern computer RPGs have complicated, detailed, three-dimensional
maps, but it was not always thus. Back in the 80s, as they were first
crawling from table to monitor, the capabilities of the PCs of the era
were better suited to the more spare graph paper maps of old AD&D modules.

I have a fair bit of nostalgia for many of the games from that period,
in particular the [Gold Box
series](https://en.wikipedia.org/wiki/Gold_Box). If you tease apart
the Gold Box file format[^1], there are eleven bits of information
associated with each grid square:

  - what wall graphic (if any) for each of the four cardinal directions
  - mobility for each of the four cardinal directions (e.g. if there's
    a wall, or door, or locked door, or whatnot)
  - the "backdrop"--an image which is used to, for example,
    distinguish indoor and outdoor locations)
  - the "zone"--what, if any, environmental subdivision of the map the
    grid square is part of. This is used to have different lists of
    random encounters, designate places safe for resting, stuff like
    that.
  - and an event, if any, that occurse in that square. Events cover
    everything from stores, to NPC interactions, to fixed-location
    battles.

If I wanted to store a map with information like that, I could do
worse than using a JSON representation. Something like:


~~~ {.json}
{
  [
    "x": 12,
    "y": 5,
    "backdrop": "sky",
    "zone": "shopping district",
    "event": "none",
    "wall_north": "none",
    "wall_east": "rock wall",
    "wall_south": "none",
    "wall_west": "storefront door",
    "move_north": "open",
    "move_east": "blocked",
    "move_south": "open",
    "move_west": "unlocked door"
  ],
  ...
}
~~~

And that might be fine if you're making something purely
machine-written and machine-read. It's essentially a much more verbose
form of the old format, with `x` and `y` map coordinates explicit
rather than position-based. But if you're making something only for
machine consumption, then you don't need to be that explicit in the
first place.

I'm interested in what a human-centric map file format might look
like.

Let's make a few assumptions. First, for example, most walls are going
to be walls on both sides (one-way walls or one-way doors are
representable based on the above, but it's hard to make sense of a map
unless they're in the minority). Further, walls (and their absence)
and doors will, in most cases, imply the navigability (that is, if
there's a wall, you can't go that way, etc). I also imagine that many
maps are going to use one wall and door type primarily. Likewise, I
assume that "event" squares are the exception, not the rule. Finally,
for the moment, I'm going to ignore "zone" and "background" (don't
worry, I'll pick them back up later).

That brings us from eleven down to four bits of information for each
cell: in each direction, is there a wall, door, or nothing?

Here's one take[^2]:

~~~ {.text}
+---------+-+-+-+-+-+-----+-----+
|         | D D | | D     |     |
| +D----+ +-+ +-+D+D+ +---+-----+
| |     D   D D     | |   |     |
| | +---+   + +     | +D--+-----+
| | |       D D     |     |     |
| | |       +-+-----+ +D+ +-----+
| | |                 | |       |
| +D+   +D+     +-----+ | +-----+
|       D D     D       | |     |
+--S--+ | +---+ +-------+ +-----+
|     | | D D |     D D         |
+-+ +-+ | +D+-+ +---+-+   +-----+
| | |   | D   | D     |   |     |
+-+ +-+ +D+--D+ +-----+   +-----+
|     D | D   |                 |
+-+ +-+ | +   | +----D--+ +-+ +-+
| | |   | |   | | |     | | | D |
+-+ +-+ | +--D+ | | +---+ +D+ +-+
|     D | D   | D | |           |
+D+ +D+ | |   | +-+-+ +D+D+ +--D+
| | |   | |   | | D D | | | |   |
| +D+   +-+---+ +-+-+ +-+-+ +---+
|               D | | D |       |
+D+ +D+ +D+ +-+ +-+D+ +-+ +-+ +-+
| | | | | | | D       D | | | | |
| +-+ | | | | | +D---D+-+ | | | |
|     | | | | | |   | |   | | | |
+-----+ +-+ +-+ +--D+-+   | | | |
|     D                   | | D |
+-----+-------------------+-+-+-+
~~~

That's fairly readable. A `D` indicates a door, there, while `|` and
`-` are walls. The `+` are walls, too. Well, corners.

Well, actually, that's a bit of a thing: the `+` are used for
intersections, but looking back at what we're tracking, there's no
mention of intersections. It's a grid, after all--if your grid cell
has walls on adjacent cardinal directions, it's an
intersection. Otherwise, no. So the `+` are visually helpful, but
convey nothing useful about the map from the machine's perspective.

In fact, there's quite a lot of useless visual help there. Each cell
is taking up nine characters across three lines. Sure, there's overlap
in the cell information, but that's still bulky for four pieces of
information.

As a purely aesthetic aside, theoretically that map is 16x16, but it
looks much longer north/south than east/west. That's a side effect of
the aspect ratio of our text characters, but it would be nice if the
representation looked a bit more proportional. Human-readability is
part of the point, after all.

Between that aesthetic concern, and the fact that we have so much
visual padding, that sparks a bit of a brainstorm. Let's try something
a little different.

~~~
_________________________________
| _______ |_| |_|_|_| ____|_____|
| | ____|   | |     | |___|_____|
| | |       |_|_____| ___ |_____|
| |_|   ___     ______| | ______|
|______ | |____ |_______| |_____|
|__ __| | |_|_| ____|_|   ______|
|_| |__ |_|___| |_____|   |_____|
|__ __| | |   | _________ ___ __|
|_| |__ | |___| | | ____| |_| |_|
|__ __| | |   | |_|_| _____ ____|
| |_|   |_|___| |_|_| |_|_| |___|
|__ ___ ___ ___ |_|_| |_| ___ __|
| |_| | | | | | ______|_| | | | |
|_____| |_| |_| |___|_|   | | | |
|_____|___________________|_|_|_|
~~~

I'm ignoring doors for the moment, just for this proof of concept, but
that looks nice and clean and much closer to square.

There's still redundant information, mind you, but it's much more
compact. Each grid square is down to six characters across two
lines. And we're making efficient use of the overlap: instead of 33
lines for a 16-length north/south, we only have 17. Our first line is
just the northern wall, then each row handles the east, west, and
south walls of each grid cell.

We're still using 33 columns, but, again, that ends up looking closer
to square.

If we look at an random grid cell, the four bits of information are in
one character of one line, then three characters of the following
line. That does leave useless extra `_`. If we eliminated those, it
might look like this:

~~~
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|  _ _ _  |_| |_|_|_|  _ _|_ _ _|
| |  _ _|   | |     | |_ _|_ _ _|
| | |       |_|_ _ _|  _  |_ _ _|
| |_|    _       _ _ _| |  _ _ _|
|_ _ _  | |_ _  |_ _ _ _| |_ _ _|
|_   _| | |_|_|  _ _|_|    _ _ _|
|_| |_  |_|_ _| |_ _ _|   |_ _ _|
|_   _| | |   |  _ _ _ _   _   _|
|_| |_  | |_ _| | |  _ _| |_| |_|
|_   _| | |   | |_|_|  _ _   _ _|
| |_|   |_|_ _| |_|_| |_|_| |_ _|
|_   _   _   _  |_|_| |_|  _   _|
| |_| | | | | |  _ _ _|_| | | | |
|_ _ _| |_| |_| |_ _|_|   | | | |
|_ _ _|_ _ _ _ _ _ _ _ _ _|_|_|_|
~~~

Most of those extra `_` are in spots that might otherwise have east or
west walls, so we couldn't just delete them. Instead, we replaced them
with spaces. I have to say, it still seems pretty readable to me. This
seems like the sort of thing that could come down to personal
preference, and since the contents of those spaces aren't going to be
used in the map, that's probably fine.

Personally, I prefer the more-connected walls. Let's go back to that,
and add doors while we're at it.

Roguelikes have been using `+` to represent doors for decades, so
let's start with that, at least for the doors to the east and
west. They're not going to line up as well with the southern
walls. I'm going to try `.` for those.

~~~
_________________________________
| _._____ |_+ +_|.|.+ ____|_____|
| | ____+   + +     | |.__+_____|
| | |       +_+_____| _._ |_____|
| |.|   _._     ______| | ______|
|__.___ + +____ +_______| |_____|
|__ __+ | +.+_| ____+_+   ______|
|_| |__ |.|__.| +_____|   |_____|
|__ __+ | +   | _____.___ ___ __|
|_| |__ | |__.| | | ____| |.| +_|
|._ _.+ | +   | +_|_| _._._ ___.|
| |.|   |_|___| |_+_+ |_|_| |___|
|._ _._ _._ ___ +_|.| +_| ___ __|
| |_| | | | | + _.___.+_| | | | |
|_____| |_| |_| |__.|_|   | | | |
|_____+___________________|_|_+_|
~~~

Adding the doors definitely makes it a fair bit busier, but I still
find it readable. I think the placecs with the most possible confusion
are where there are a bunch of doors adjacent to each other--the
training hall in the center of the north edge is a good example.

Overall, I like this. It seems reasonable to have a map file consist
of a grid like the above, then a bunch of additional data below for
all the exceptions.

I promised I'd get to the concepts of "backdrop" and "zone", and I
will, but not in this entry. Stay tuned.




[^1]:
    Which turns out to be a bit tricky. The file formats can differ
    slightly between games, are all stored in a janky compression
    format, and don't include information about the file contents.

    Bits were expensive way back when, and if you knew that the map of
    the civilized quarter was in the third block of the `GEO4.DAX`
    archive file, there was no need to label it. Of course, that
    starts falling apart when your dev team gets bigger, or if you
    want to make the functionality more general.

[^2]: Savvy readers may notice this is the map of the civilized section
of Phlan from the first Gold Box game: [Pool of
Radiance](https://www.mobygames.com/game/502/pool-of-radiance/).

