TL/DR: My BBC BASIC port of Scott Adams’s classic TRS-80 text adventure game Adventureland, as published in SoftSide magazine in 1980, is now complete and available to download or to play in your web-browser: Play Adventureland
Previously, I resurrected the original* version of Scott Adams’s second text adventure game, Pirate Adventure, and I ported it from TRS-80 BASIC to BBC BASIC — mostly for the heck of it but also because my port can be played in a web browser quite easily and the game is therefore more accessible now than it was before.
So I thought I might as well go back to the game with which Adams’s career as a digital dungeonmaster began: the TRS-80 BASIC version of Adventureland. I assumed that because I’d already ported Pirate Adventure to the Beeb, porting Adventureland would be a walk in the park.
Instead, I unexpectedly found myself puzzling over what appeared to be a forty-year-old bug. (Spoiler: it wasn’t.)
But first I had to get the program-listing into digital form, ready for converting. Like its successor Pirate Adventure, Adventureland had been published as a type-in listing, in the July 1980 issue of SoftSide magazine in this case, five months before Pirate Adventure appeared in BYTE.
Now, typing listings in by hand was bad enough in the 1980s, but today the twin problems of ageing and impatience have made it all but insufferable. Anyway, in the 80s most people had no choice but to type in a listing manually if they wanted to play the game. Today, though, in the internet age, there had to be another way to get hold of a digital copy of the listing, right? Even if the scan of the magazine at Archive.org wasn’t good enough to yield an accurate OCR of the text, surely someone, somewhere, had already found a way around the problem. Right..?
Well, if there was a digital copy of the SoftSide listing out there, I sure as heck couldn’t find it. What I did manage to find was the source code for several ports and variants of Adventureland, but they all seemed to derive from a later version of the game (which is widely available in “.DAT” format), and not from the SoftSide listing. But it was the SoftSide listing that I was specifically interested in.
What I ended up having to do was configure MAME to emulate an 8-bit TRS-80 Model I Level II microcomputer — which isn’t a job for the fainthearted, especially if you’re trying to set up the emulation on a Mac. I then downloaded a copy of Scott Adams’s adventure interpreter on a TRS-80 disk-image: the disk-image has kindly been made available by the Data Driven Gamer, who has also supplied the game-data for Adventureland as a .WAV audio file, which takes a full twenty minutes to load into the interpreter!
Once the TRS-80 was up and running in MAME, I set about hacking the BASIC interpreter program so that it would not only read in the Adventureland game-datafile but also print out all the data values (the lists of numbers and text-strings that make up the content and logic of the game). I hacked the program using only the line-editing facilities provided by the emulated TRS-80, none of which I’d ever encountered before, and all of which I intend never to encounter again if I can possibly help it. (Retrocomputing nostalgia can be extremely overrated.) The hacked program was able to print out the data values to a “virtual printer”, which was actually just a plain text file on my Mac.
I had finally managed to acquire a digital copy of the game-data for the original* BASIC version of Adventureland, without having had to spend hours painstakingly typing in the listing myself — I had just had to spend hours figuring out how to drive a TRS-80 in MAME instead. Which was at least a new variety of frustration.
Separation of concerns
Anyway, I massaged the data into a form that could be pasted into the “adventure builder” program from SoftSide, which, luckily, was the same version (1.3) of the program that had been used in Pirate Adventure — and I had already ported that! So I had saved myself yet more typing (and swearing).
The adventure-builder program reads the lists of numbers and messages in the game-data and spits out a datafile. The adventure-interpreter program will then load the datafile and turn it into a playable game.
Here again I managed to save myself a lot of work: last time, when porting Pirate Adventure, I had stumbled over the subtle differences between TRS-80 BASIC and BBC BASIC, which had made the task of porting the interpreter a little torturous, but now, thanks to Scott Adams’s forethought and software-design mavenry, I found that I didn’t have to type in or otherwise digitise the interpreter program for Adventureland at all — instead, I was simply able to use the later version of the interpreter, from Pirate Adventure, which I had already sweated over and converted! And it seemed to work fine with Adventureland. Huzzah!
I was on the home straight. I could see the finish line and I was charging ahead, full tilt. All I had to do was tidy up the BBC BASIC programs and package them up in a disc-image, and, hey presto, they’d be playable online. So I did. And they were. And then I found the bug.
The alleged bug
WARNING! Spoilers ahead.
Early on in the game, you come across an axe that has the magic word BUNYON on it. If you take the axe to the quicksand bog — which happens to contain a treasure, a statue of an OX — you’ll find that you can’t SWIM out of the bog unless you either drop the axe into the bog (where it’s of no use to you) or say BUNYON, which magically transports the axe to the grove.
In my BBC BASIC port of the game, which was using the interpreter from Pirate Adventure, that was all that happened: only the axe was sent to the grove. The OX wasn’t affected by your use of the word BUNYON at all — it simply remained in the bog, and there was apparently no way to get it out! If you carried it, you couldn’t leave the bog because the OX was too heavy to swim with. The OX statue seemed to be stuck where you found it, never to be moved and never to be deposited in the treasury — which is where you have to put all the treasures if you want to win the game. So the game seemed to be unwinnable.
But if it really was impossible to complete the game with a full score, then how come nobody had noticed the bug when the game was first published in SoftSide? Where were all the errata and the corrections? Was it simply that no one had bothered to type in the original listing? Surely not — we were gluttons for punishment in the 80s, as I’ve already said…
So, what on earth was going on? Hmm. Well, perhaps the reason that none of the avid players of SoftSide’s edition of Adventureland had reported the bug, back in the day, is that they had found an alternative route to success. Because, you see, the BUNYON/OX problem has a workaround.
But the workaround requires the use of another object, which is hidden deep in the underground maze, and you’d probably only find this object much later on in the game, after you’d been playing for a good long while. So it seemed unlikely that Scott Adams had intended this workaround to be the official solution to the puzzle of the OX in the bog. If he had, he wouldn’t have bothered setting up and clueing the BUNYON solution, especially when memory was at a premium in a TRS-80 with just 16 kilobytes of RAM! There wasn’t the space to waste on red herrings — or at least not on red herrings as perfunctory as this. If BUNYON wasn’t meant to be the solution to the OX puzzle, then there was no point in including BUNYON in the game at all!
My suspicion that the BUNYON-fail was a bug was soon strengthened when I came across a copy of the game that actually seemed to have had the bug fixed. On his website, the redoubtable Jimmy Maher provides a link to the savestate that he used when he played through the TRS-80 BASIC version of Adventureland for his Digital Antiquarian blog. So here was another copy of the TRS-80 BASIC version of Adventureland that I could compare and contrast with the copy that I had just cobbled together myself.
The trouble was that Jimmy had created the savestate with an old piece of software called “MESS”, which is a long-dead ancestor of the MAME emulator, and Jimmy’s savestate was incompatible with the latest version of MAME, which, naturally enough, is what I had installed on my Mac. Aargh.
After a lot of false starts I eventually hit paydirt with a particular historical version of MESS for Windows (which I ran in a virtual machine on my Mac). That version of MESS did seem to be capable of loading Jimmy’s savestate — once I had fiddled around, configuring it to emulate a TRS-80 Model I Level II, of course. (Déjà vu, anyone?)
Wonder of wonders, the BUNYON/OX bug didn’t manifest in Jimmy’s copy of the game. Instead, BUNYON transported both the axe and the OX to the grove, as the creator had doubtless intended:
At this point it would have been nice to inspect the data that Jimmy’s copy of the game was using, so that I could see how the putative bug had apparently been fixed. But, try as I might, I just couldn’t find a way to escape from the running BASIC program to inspect its variables, even after I’d worked out what the TRS-80 “Break” key mapped to on my Mac keyboard (Function + right-arrow, would you believe?) — because pressing Break just caused the emulated TRS-80 to hang. Nothing I did could then persuade it to respond to keyboard input!
I was at a dead end. I would just have to fix the so-called bug myself.
“Fixing” the “bug” (or vandalizing the game)
The game-data for Adventureland, as presented in the BASIC listing in SoftSide magazine, is just a comma-separated list of numbers. They don’t exactly trip off the tongue:
I could have tried to split the numbers (the “actions”) into groups of eight and to parse them all manually, with the help of Allan Moluf’s excellent guide to the Scott Adams database format (h/t pdxiv) — but even I’m not that much of a masochist! Instead, I turned to ScottKit, a very handy utility that can take the “raw” game-data and turn it into something that’s human-readable.
Of course, I first had to wrestle the game-data into a form that ScottKit could understand, which mainly involved padding the data out with a lot of empty strings and making sure that empty and non-empty strings alike had been properly enquoted. In due course I found myself looking at the “decompiled” Adventureland game-data, and there did indeed seem to be a bug in it. (In fact, ScottKit refused to proceed with the decompilation until I’d forced it to ignore bugs by specifying the “-b” flag.):
When the player said BUNYON in the quicksand, what seemed to be happening was that the game was moving the wrong object to a non-existent room! When I compared the decompiled SoftSide code with a decompilation of a widely available later version of Adventureland, the error seemed to be staring me in the face.
Surely, then, all I had to do was tweak the game-data and replace the embedded command-code 68 (“clear flag zero”) with command-code 60 (“clear the flag specified by the relevant parameter”) — and suddenly everything would fall into place: when the player said BUNYON, flag 7 would be cleared and object 47 (the OX) would be moved to room 25 (the grove), just as Scott intended.
So that’s what I did. And everything seemed to be working. Problem solved!
I appeared to have fixed a forty-year-old bug in a Scott Adams game! Wow. I was about to start writing this blogpost to crow about it when I was suddenly seized by doubt: what if the bug wasn’t actually, well, you know, real..?! I mean, of course it was. It had to be. The bug was right there in my BBC BASIC port, and that port was using the original game-data, so surely that was all the proof that anyone needed..?
But, then again, there was the fact that I was using a later version of the interpreter to play the game, rather than the interpreter that was actually published together with the game-data in SoftSide. Hmm. Perhaps I’d better just check that I was, in fact, able to reproduce the bug. I would use Data Driven Gamer’s copy of the TRS-80 BASIC version of the game — that would provide independent verification that the bug was real. I was sure I’d already done this at the start of my tanglings with Adventureland, but it couldn’t hurt to quickly check again…
So I spun up the latest version of MAME again. I booted the emulated TRS-80 and waited twenty minutes for Data Driven Gamer’s tape-image to load. Then, painfully slowly,** I made my way to the bog with the axe, and said BUNYON.
The axe vanished… but so did the OX!
The game was working fine..!?
The bug wasn’t real.
After I had come to, I began to reason thus: Data Driven Gamer’s copy of Adventureland was reading the game-data that had been published in SoftSide. And it was using the interpreter from SoftSide too. And everything was working without error.
In contrast, my port of the game was using that same SoftSide game-data but feeding it into the later version of the interpreter, from Pirate Adventure. So there had to be a key difference between version 4.2 of the interpreter (for Adventureland) and version 4.6 of the interpreter (for Pirate Adventure). And that difference must have been the cause of the BUNYON/OX bug in my initial port of Adventureland.
I had rashly assumed that the v4.6 interpreter would be backwardly compatible with the v4.2 Adventureland game-data. And, when I came across the BUNYON/OX bug, I had foolishly amended the v4.2 game-data to bring it into compliance with the v4.6 interpreter, naively thinking there was a bug in the SoftSide listing. But there wasn’t!
What I should have done instead was port the earlier version (4.2) of the interpreter — you know, the one that had actually been written with Adventureland in mind! And I should have used the v4.2 port to read the original Adventureland game-data from SoftSide, as Scott Adams had obviously intended.
I had also allowed myself to be misled by the output of ScottKit’s decompilation of the SoftSide game-data, which seemed to suggest that there was indeed a bug in the game logic. The problem was that ScottKit had been designed to work with a later version of the Scott Adams game-data format — it’s not clear exactly which version, but this linked document suggests that versions of the data format (and hence of the interpreter) up to at least v8.5 may exist. So ScottKit may have been expecting to see a much later iteration of the format than what I had been giving it.
To put it mildly: D’oh!
Okay. I would clearly have to bite the bullet and start porting the v4.2 interpreter to BBC BASIC — a task I’d been hoping to avoid, given how painful it had been to port v4.6 last time. Fortunately, the design of version 4.2 of the interpreter program was similar enough to version 4.6 that I found that I was able to complete the new port in record time.
Having ported version 4.2 of the interpreter (as published in SoftSide) to BBC BASIC, I now needed to test the port to see if it was working correctly with the v4.2 game-data (also as published in SoftSide). And I found that it was! I permitted myself a relieved but tentative huzzah!
Then, just as a sanity-check, I combed through the BASIC sources for the two versions of the interpreter to see if I could pin down exactly where and how they differed. This proved to be surprisingly tricky. The two programs (v4.2 and v4.6) were similar enough in structure and functionality that they induced a sort of code-blindness in me, which made it hard to spot the difference.
In the end, though, the location (if not the detail) of the difference turned out to be somewhat obvious and unsurprising: whenever a specified flag had to be cleared, the Adventureland game-data would trigger some code in the v4.2 interpreter, and that code was effectively the “handler” for “command 68”, and what that handler did was simply redirect to the handler for command 60 — and it was the handler for command 60 that finally did the work that needed doing.
In the later v4.6 interpreter, however, command 68 and command 60 perform two different functions. And the v4.2 Adventureland game-data had been triggering the wrong one! Hence the apparent bug whereby the OX never left the bog. Double d’oh!
What did we learn?
1. I was foolish to think I had found a bug in a well-known and seminal forty-year-old game — I should have just assumed that I had somehow messed up, which was always going to be more likely. I wasted so much time chasing phantom bugs!
2. Scott Adams seems to have added new features to his interpreter at short intervals, and sometimes in surprising ways. For example, I’m still not exactly sure why command 68 simply redirects to command 60 in v4.2. It’s almost as if command 68 was being used as a placeholder for new functionality that Adams wasn’t ready to implement yet..?
3. The differences between the various versions of the Scott Adams game interpreter (and hence of the game database format) aren’t fully documented. Even the generally excellent guide by Moluf doesn’t cover all the wrinkles, variations, and updates.
4. Scott Adams’s creation of an abstract adventure interpreter was highly ingenious in the 1970s and is still impressive today.
My BBC BASIC port of the version of Adventureland that was published in SoftSide magazine in 1980 is now complete and is available to download or to play in your web-browser. A map and a solution are also available. See Github for links:
* My use of the word “original” is extremely context-dependent (and probably wrong).
** Perhaps I’ve been spoilt by the relative speed of BASIC on the BBC Micro, but the TRS-80 BASIC version of Adventureland always feels very sluggish to me. It takes an age to respond to almost any command, even in the latest version of MAME. Worse still, in a historical version of MESS in a Windows VM (“double emulation” as it were), not only does the game seem just as slow but also the fan in my MacBook Pro spins faster and faster till it sounds like it’s gained enough angular momentum to break free of its housing, slice through the outer case of the machine, and embed itself in my stomach.