Browse Source

new entry about gridmaps a la gold box

john melesky 1 year ago
parent
commit
15d16cf699
1 changed files with 262 additions and 0 deletions
  1. 262 0
      content/blog/2023/09-20-noodling-map-representations.md

+ 262 - 0
content/blog/2023/09-20-noodling-map-representations.md

@@ -0,0 +1,262 @@
+---
+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/).
+