From the “this is how my mind works sometimes” department…
Some definitions, as they relate to my career as an embedded programmer:
- Can of Worms – when you go to fix something that should be simple and quick, but as you try to fix it, you realize it’s tied to other things that will also need fixes and thus your one quick fix turns in to days of many not-so-quick fixes.
- Whac-A-Mole(tm) – when you fix a bug only to find that it manifests another bug, and then you fix that bug and it causes yet another bug, and then… (See also: Unintended Consequences)
- Rabbit Hole – when you think something will be simple, then you look, and have to go to another section of code to find what you are looking for, but that sends you to another section of code which also sends you to another section of code and that…
Today, a quick rabbit hole in relation to text adventure games.
Down the rabbit hole: the beginning of playing
I was fascinated with text adventure games when I first learned of them back around 1981 or 1982. I do not recall what the first one I saw was, but it was likely something at the local Radio Shack playing on a TRS-80 Model 3. I definitely remember buying Mission Impossible by Scott Adams on a cartridge for my Commodore VIC-20.
This led me to trying to write my own text adventures. The “most successful” one was probably a custom game I wrote for the *TALK TO ME* BBS in Houston, Texas. The game was a recreation of the SysOp’s (system operator) apartment, and the goal was go roam around the apartment collecting parts of the system that ran the BBS and hook them all back up. It was a very simple game, with the only challenge being something random you couldn’t do anything about — a killer cockroach (if I recall) that would randomly show up and scatter all your work back randomly across the apartment. Randomly. One day, I hope to find this program on a cassette tape somewhere.
But I digress…
Down the rabbit hole: the beginning of coding
Over the years, I wrote various routines for doing text adventures — word wrap, verb/noun input, moving from room to room, getting and dropping objects, etc. When I started going through my old CoCo stuff years ago, I found notes on old games I’d forgotten I had been working on. The most complete one was “The ODDyssey” which I was co-writing with my MC-10 buddy Paul T. (We had intended it to run on both CoCo and MC-10.) I have the engine of that game and the complete map, but we never finished the goals and objects beyond some early test ones.
Still, it looked pretty good, and using a trick I think I read about in The Rainbow magazine, you could type in “get the black book” instead of just “get book.”
In addition to various CoCo adventures, I also tried writing one in Java that would run as an applet on a web browser. That game, based on Disneyland/Disney World’s Haunted Mansion, even included background music :)
Heck, I even wrote a “WebVenture Generator” MS-DOS program that would let me make simple walk-through web pages using digital photos I took. Here is one from Disneyland using photos I took in August 1996:
None of this has anything to do with today’s topic except to say that I’ve toyed with adventure games numerous times over the years in several different languages.
Down the rabbit hole: the beginning of the point
When I’m starting a new adventure game, I usually make a test map. Ideally I have rooms that have exits in different directions so I can verify all of that works. It might start as something very simple like this:
[ 1 ] --- [ 2 ] | | [ 3 ] --- [ 4 ] --- [ 5 ]
That has rooms that have exits leading North, South, West and East, but it doesn’t truly exercise all the possibilities. A proper “engine” shouldn’t care, but if one wanted to be thorough, you’d want to make sure you have every possible combination of room exits covered in a test map.
How many exits can one room have?
For simplicity, we will limit our exits to the four compass directions – North, South, West and East. A fancier adventure game might allow diagonals (Northwest, Southeast) and vertical (Up and Down). But for now, we’ll stick to the four basic directions.
Initially I started drawing out a map by hand, trying to make sure I had a room with only an exit East, a room that had only an exit West, etc. I quickly lost track of what I was trying to do…
So I wrote a program to show me all the combinations. Since there are four exits that can either exist or not exist, I decided to use four bits to represent them.
- Bit 0 – North
- Bit 1 – South
- Bit 2 – West
- Bit 3 – East
Side Note: I am using NSWE here, but I recall, when I first learned about writing adventure games from some VIC-20-era magazine I had, they used the order of NEWS – North, East, West, South. That might be easier to remember, but the order doesn’t matter for this example.
Here are what those bits would look like:
0001 - Exit North 0010 - Exit South 0100 - Exit West 1000 - Exit East
…then all the other combinations. Once I thought about it this way, it was easy to see I had everything from 0000 (0, no exits) to 1111 (15, exit in all four directions). Thus, there would be 16 possible room types.
I wrote this program to print them all out:
10 PRINT "ALL POSSIBLE EXITS:" 20 FOR D=1 TO 15:PRINT D; 30 IF D AND 1 THEN PRINT "N"; 40 IF D AND 2 THEN PRINT "S"; 50 IF D AND 4 THEN PRINT "W"; 60 IF D AND 8 THEN PRINT "E"; 70 PRINT,; 80 NEXT
Side note: If you wanted to include the diagonal directions of NW, NE, SE and SW, you’d expand that to eight bits. If you were also including Up and Down, add two more bits. That would make 1024 possible room types — and now you see why I limited it to just four directions.
And from there, I started drawing a map, making sure that I had at least one room of each of the 15 times listed above. (A room with no exits would also be possible, though maybe not useful.)
And this led me even further down this rabbit hole… I wanted to make the most compact map I could that had a room of each type in it. That would be my “test map” for the adventure game project.
Down the rabbit hole: the beginning of brute force
After initially trying to map out all the combinations using brute-force…
-  - | | | |  -- | | | |  ---- | --- TODO: 13 NWE, 14 SWE
…I wondered if there might be an easier way. Instead of just spending ten minutes drawing this by hand, I could probably spend a few hours or days to come up with a program that would help me create the map.
And as I thought about that, it sorta sounded like one of those sliding puzzle games I enjoyed as a kid.
Micha L. Rieser, via Wikipedia
In a number puzzle, the goal is to get the numbers in order. For a photo puzzle, it was to get the photo assembled. For my project, there could be multiple solutions — just as long as all rooms had a/an exit(s) that connected to another room’s exit(s).
And that reminded me of a game I had for my Sega Genesis called Junction. Or the relatively new CoCo game Pipes by Nick Marantes.
In those games, you are either sliding pieces around to complete a track for some object to follow, or you are placing pieces down (ala Tetris) to create a track.
For my use, instead of having the “playfield” be locked to some fixed width and height, it could be anything — very wide, very tall, or both. The more compact, the higher the score. The score might be calculated by the fewest number of duplicate pieces (15 being the least you could use, since you had to have at least one of each room type) and the least amount of empty spaces in the final map. For example, if there were only four pieces, they could be represented in a 4×4 grid with no empty spaces — a perfect score:
-- | | --
But if the same four pieces had been represented like this:
-- xxx | xxx --
…it is now using a 3×2 grid with two empty spaces and that would be a lower score. Somehow.
And if I could create something like this, and get people to play it, they could work out the best and most efficient way(s) to represent a text adventure demo map that covered all possible room types.
And that, my friends, sounds like even more work than just brute forcing a map until I am happy with it.
So naturally, I may just have to do this.
Until next time…