Advent of Computing - Episode 68 - Zork

Episode Date: October 31, 2021

Make sure you have some extra batteries for your lamp, this episode we are delving into the depths of Zork. Written in 1977 Zork would quickly become the epitome of text based adventures, pushing asi...de all competitors. A lot of this comes down to it's simple gameplay, and the simple fact that Zork is fun to play. But lurking deeper into the game is a hidden treasure. Ya see, the other huge part of Zork's success was it's portability. That was made possible thanks to some sick programming tricks, and a virtual computer called the Z-machine. Selected Sources: https://sci-hub.se/10.1109/MC.1979.1658697 - Early article from IEEE https://web.archive.org/web/20060427000213/http://www.csd.uwo.ca/Infocom/Articles/NZT/zorkhist.html - Tim Anderson's Zork history https://archive.org/details/a2woz_Zork_I_1981_Infocom_r75 - Go play Zork  

Transcript
Discussion (0)
Starting point is 00:00:00 You just finished work for the evening and make your way home. You walk up to your small white house, but before going inside, you decide you should check your mailbox. To your surprise, there's a strange, unmarked leaflet inside, no postage or anything. You grab the leaflet, unfold it, and it reads, quote, Zork is a game of adventure, danger, and low cunning. In it, you will explore some of the most amazing territory ever seen by mortal man. Hardened adventurers have ran screaming from the terrors contained within. In Zork, the intrepid explorer delves into the forgotten secrets of a lost
Starting point is 00:00:38 labyrinth deep in the bowels of the earth, searching for vast treasures long hidden from That can't be right. Looking up, you see that more has kind of gone wrong. Your door is now boarded shut, and the rubber mat in front of your door reads, Welcome to Zork. It appears that you're not quite home. You've stumbled into some interactive fiction. Now, that long passage, at least the quoted part, is how the game Zork describes itself in-game. It's an accurate description, at least as far as what the player will normally see during gameplay.
Starting point is 00:01:25 But there's a secret layer to this dungeon. What most adventurers miss out on are the technical treasures and wonders buried just a little bit deeper inside of Zork itself. Welcome back to Advent of Computing. I'm your host, Sean Haas, and this is episode 68, Zork. Today, we're wrapping up our celebration of Spook Month with a dive into the spooky fantasy world depicted inside the game, Zork. Now, as far as text-based adventure games go, Zork is probably one of the most popular examples of the genre. adventure games go, Zork is probably one of the most popular examples of the genre. It served as a good foundation for Infocomma, Juggernaut, and PC gaming in the 80s and early part of the 90s. This digital empire would all start with Zork, a very strange and technically fascinating game.
Starting point is 00:02:21 Now, Zork is a text-based adventure game, but you shouldn't be tricked into thinking that it's simple. Zork is anything but simple. It is relatively complex gameplay that covers a sprawling world, and it's just as complex under the hood. Zork has been ported to just about every platform you can think of. The game really has a wide reach. It even shows up inside other video games. I think Call of Duty actually has an easter egg where you can play Zork inside that game. A big reason for the spread is that Zork itself runs inside a virtual machine. That's right, Zork is such a complex program that it even has its own virtualized environment. That's not something
Starting point is 00:03:05 you really see often with any video games, let alone a text-based adventure game. It might seem out of place for something as deceptively simple as a text interface to have a virtual machine dedicated to it. But there is a deeper purpose to this madness. Zork's authors describe the game as a computer fantasy simulation. It's meant to be an immersive and engrossing experience, and even decades later, the game still retains a certain feel of wonder. From breaking into a small house, delving into the underground empire, to being eaten by groos and other nasties that lurk in the shadows, to being eaten by groos and other nasties that lurk in the shadows, Zork does really have a way of pulling you in.
Starting point is 00:03:52 So grab your trusty sword and, hey, maybe you'll need a sack to put some treasure in. Today, we're going to be looking at Zork the game, but more importantly, Zork the program. We're going to explore how project goals influence software design, how sometimes a radically complex solution can really pay dividends, and how the early internet made games like Zork possible. Most importantly, we'll try to parse out what makes Zork so much fun to play decades later. It's simple to just say that ARPANET was the predecessor to the modern internet. That's an easy tagline. Maybe if you're feeling a little more verbose, you could talk about the difference between public versus private ownership, or maybe the difference in communication protocol. Those are both valid approaches, but I think it misses
Starting point is 00:04:35 the really big picture. In practice, ARPANET was just cut from a different cloth. Part of it was the size, part of it was the user base, and part of it was timing. The internet has managed to connect just about everyone in the world. It's become a great place to build small communities of like-minded people. But by contrast, ARPANET was a lot closer to one community of like-minded people. There was also this rampant type of openness to ARPANET that we don't get online anymore. Yeah, it was a government-funded research network and it was hard to access if you weren't in the right places, but over time that kind of just became a cover story. There weren't
Starting point is 00:05:20 really malicious actors on ARPANET. First off, being a malicious actor on ARPANET was a federal crime, so you didn't really want to do that. You weren't supposed to mess around with a government network. Plus, the community was so small that it could effectively self-police if someone was getting out of line. So users were nearly free to come and go. It was just sort of assumed that you knew what you were doing. Mainframes were somewhat open to perusal, at least files could be really easily browsed.
Starting point is 00:05:50 Some systems even had their doors flung wide open for any passersby. This made the perfect storm to allow new phenomena to spread like wildfire amongst the small community. One of the first sparks came in 1976, and it was called Colossal Cave Adventure. This was one of the first text-based adventure games. Now, I've kind of gone back and forth on if Adventure was actually the first text-based adventure game or not. There are a few earlier examples, there are some far stranger examples, but Adventure was at least the first popular member of this species. It was initially written by Will Crowther at BBN, a computer company based in Massachusetts. Crowther
Starting point is 00:06:31 developed Adventure on a computer at BBN that was connected to ARPANET. Soon thereafter, the game was discovered by Don Woods, a programmer at Stanford University all the way out in California. He was browsing the ARPANET one day, found the file, and became instantly engrossed. In the coming months, he expanded the game further. In 1977, this souped-up version hit the network. Nearly everyone with access to the ARPANET was talking about Adventure. Tradition holds that the entire computer industry was set back by at least two weeks just by this game. It's pretty easy to see why Adventure had this kind of impact. It was just fun to play. It had a certain addictive quality to it.
Starting point is 00:07:16 In Adventure, you play as, what else, an adventurer. Gameplay revolves around spelunking the colossal cave in search of treasure, but a series of puzzles, hazards, and other dangerous cave dwellers stand in your way. The twist that pulled in so many computer nerds was the scoring system. Solving puzzles, slaying beasts, and collecting treasure, and more importantly, returning booty to the surface, all earn you points. The finalized game has a maximum of 350 possible points you can earn, so you have this incentive to keep scrounging for every last point. It's really like a big immersive puzzle, and in 1977 it was a totally new experience to see on a computer.
Starting point is 00:08:01 Portability also added to Adventure's popularity. The game was fully textual. Everything was explained to the player as a chunk of text, and all player actions were controlled by typing in short commands. This was roughly the same kind of interface used on every computer hooked into the ARPANET, so you didn't need anything special to experience adventure. Adding to this, the Colossal Cave was implemented in Fortran. Everyone used Fortran, or at least if you didn't use it, you had access to a Fortran compiler really easily. So once again, there wasn't really a barrier to entry. All you needed were the source files, which were already spreading all around the ARPANET. Thus, our perfect storm was constructed.
Starting point is 00:08:53 And the computer industry at large ground to a halt as programmers would disappear into the colossal cave for days at a time. This effect was particularly profound amongst a group of hackers at MIT's Dynamic Modeling Group. The DM group, as it was sometimes called, was something of a special place. The computer science-based research groups and labs at MIT in this era were working on really cutting-edge stuff, but they also had this unique air to them. One of the big things brewing
Starting point is 00:09:18 inside the Dynamic Modeling Group around this time was called the Incompatible Time-Sharing System, or ITS. I did a whole episode about this a while back, so if you want to know more, I'd recommend checking that out. The broad strokes are that ITS was a system designed by hackers for hackers. It incorporated some real cutting-edge features while focusing on user freedoms. There were no passwords or permissions on ITS. Anyone could hop onto the system if they knew its address on the ARPANET. ITS was very much built as a playground for new ideas. This kind of culture primed the DM group to have a very particular response when they came
Starting point is 00:09:59 into contact with Adventure. Call it a can-do attitude, or maybe just an expression of the hacker ethic. Tim Anderson was one of the early victims of the Colossal Cave, and this is how he explained the phenomenon. Quote, When Adventure arrived at MIT, the reaction was typical. After everyone spent a lot of time doing nothing but solving the game, the true lunatics began to think about how they could do it better. Adventure was written in Fortran, after all, so it couldn't be very smart. It accepted only two-word commands, it was obviously hard to change, and the problems were sometimes not everything one could desire. I was present when Bruce Daniels, one of the DMers, figured out how to get the last point in Adventure by examining the game
Starting point is 00:10:45 with a machine language debugger. People were obsessed with Adventure. There's no other way to put it. And I particularly like that last part, that one student went so far as debugging the program just to squeeze out that last point. The bug really bit some people hard. Perhaps more interesting here is Anderson's quip about Fortran. If you've never used Fortran, then maybe you should consider yourself a little bit lucky. It's a strange and archaic tongue, to be sure. Besides just being outdated, even by 1970s standards, Fortran wasn't really the best tool for text-based anything. It was designed for handling math, numeric data, and basically nothing else. Fortran can deal with text-based stuff. It can do a little bit of string manipulation,
Starting point is 00:11:40 but that's getting outside of its comfort zone. That's just the surface-level issue with Fortran for this application. Once you start actually profiling the problem a little deeper, things don't get much better. In fact, I'd say they get a lot worse. I'm going to put the cart a little bit before the horse here, but I need to introduce one crucial source. The article Zork, a computerized fantasy simulation game, was published in IEEE in 1979. Besides discussing Zork, which we'll get to in a few minutes here, the article gives a pretty comprehensive operating theory of text-based adventure games in general. The article describes these types of games as an exercise in data management,
Starting point is 00:12:26 something akin to a hyper-intelligent database. Further, the authors posit that objects are crucial when implementing this type of game. Now, I don't mean objects in the physical sense. We're talking about objects the programming construct. In the simplest possible terms, the programming construct. In the simplest possible terms, and this is a radical simplification so don't get too mad at me, objects are reusable data structures that can follow and inherit some predefined template. Each object can contain a mix of data, executable code, information about its relationships to other objects, and even entire sub-objects. It's basically a really flexible format for defining a system, and it's also a really modular and expandable framework. It's a great way to, say, model a network of interconnected rooms all
Starting point is 00:13:20 containing items. Fortran just plain doesn't support objects. At least it didn't at that time period. I think there's a few modern versions that do kind of have object support. You got a bunch of different data types for numbers, you got booleans, you even got arrays of any dimensions you want. Plus, you could encode characters and strings as variables. you want. Plus, you could encode characters and strings as variables. That's a usable set of variable types, but it's really basic. It doesn't give you a lot of advanced options. You can't, say, make your own new data types, and you certainly can't use objects. Talking more concretely, this inflexibility majorly impacted how Colossal Cave was written. This is a fabulous time to mention that we still have the original source code for Adventure.
Starting point is 00:14:11 Both Crowther's original version and Woods' expanded code are readily available online. If you like Fortran, then feel free to take a look. Otherwise, you might want to steer clear for your own safety, unless I guess you're looking for something really scary to do on Halloween. Anyway, Adventure the Program is composed of two main components, the actual code and a single data file. The code component is something like a game engine, at least sort of. It's essentially a big and somewhat complicated state machine that models a fantasy cave. It handles taking user inputs, giving textual feedback, and it tracks progression of states.
Starting point is 00:14:54 When I'm talking about states here, I'm just talking about a small set of simple variables. Things like what room the player is in, what items the player is carrying, where dwarves may be prowling, and the all-important score. There are also a handful of other relevant variables, but that's the basic gist. The data file, which in some source code comments is called the database, contains the bulk of game data. It describes every room in the Colossal Cave, the items that can be in rooms, vocabulary terms, and how everything is connected. Basically, it's all the text you see during the game of adventure. It's all stored in that one file. But calling it a database, I think, is a little bit of a stretch. When the file is actually loaded into memory, it just takes up a bunch of separate arrays.
Starting point is 00:15:46 Everything from rooms to items has its own array index. So you can traverse and manage the dataset, but it's all done in a kind of clunky Fortran way. That's no knock on Crowther or Woods. It's just how Fortran can handle large sets of interconnected data. I think a good example of this Fortran way of life is how Adventure handles, well, how it handles all user interactions. I know that's kind of a large swath, but I'm going to break out just a small bit of
Starting point is 00:16:22 this. Traversing rooms is the most common thing you do in adventure, and that's handled by one big table of values. This is basically a grid that lists which keywords the player must type at certain locations to advance to another location. It defines that if, say, you're in a room, then typing east will move you down a hallway. Or that saying exit will let you leave the house where the game starts. So far, pretty simple.
Starting point is 00:16:53 All of those interconnections, the mappings of keywords to progress the states, that's defined in the data file. But that's only part of the game's logic. The huge omission here, the big glaring hole, is puzzles. Well, that part of the program, possibly the most fun part of the program, isn't fully defined by the data file. This is where the inflexibility part should start to make some sense. I think a
Starting point is 00:17:27 good example from early in the game is the snake puzzle. This is your spoiler warning in case you haven't played the first few puzzles in Adventure. Anyway, you run into a big scary snake in the cave pretty early on in the game. The first time this happens, you die. That's kind of how puzzles and text-based games go. You eventually figure out that in another room, you can catch a bird in a small cage. Then, if you release it, the bird will scare away the snake. It doesn't make a lot of sense, but hey, it works. It's kind of funny. It's kind of the shtick to these types of games. Well, here's the weirdness. The bird is defined in the data file. It's just an item. The snake is also at least mentioned in the data file. It's part of a room's state. Specifically,
Starting point is 00:18:19 the snake room has a state with and without the snake. But there's nothing in the data file that defines how you get from one state to another. The actual action of unleashing the bird on the unsuspecting snake is all defined in the game's Fortran code itself. Specifically, it's a special case of the throw action, which gets aliased to a number of synonyms that cover the bird situation, such as release or drop. There's a line of code that checks if you're releasing the bird and if the snake is in the room with you, and then it handles those interactions. To mix this up and generalize a bit, what we're seeing is a coupling between the actual game data and the program. You could write a custom data file for Adventure, but no matter how much of the data you change,
Starting point is 00:19:13 the bird will always scare off the snake if it's dropped in the right room. That's burned into the code. It's baked into the binary. If you wanted the player to be able to, say, eat the snake, baked into the binary. If you wanted the player to be able to, say, eat the snake, then you would have to modify some Fortran and recompile the game. While that's not the end of the world, it's an annoying quirk. Adding new puzzles or any kind of new functionality means blowing up the complexity of the program. By way of example, we can look at Adventure itself. The first version, written solely by Crowther, was only 709 lines of Fortran. Woods expanded the game significantly. He added scoring and some general features, but crucially, he added a new slate of treasures and puzzles to solve. This bumped Adventure up to just shy of 3,000 lines of Fortran code.
Starting point is 00:20:07 In the long term, this kind of expansion can make a project hard to maintain, and it can make future expansion more difficult to handle. Every time you try to add complexity to the game, you end up with more and more complicated code. I guess this is just a long way of saying that Anderson's disdain for Fortran was, at least in this case, warranted. It just wasn't a good tool for the job. Plus, there was a more fitting tool that was starting to see some use inside the dynamic modeling group. This tool was a language called MDL. The actual meaning behind those letters is a little up for debate. Officially, it stood for Model Development Language, but it was sometimes referred to as
Starting point is 00:20:53 More Data Types Than Lisp. Personally, I like that one. But many of the programmers who worked with the language would simply call it MUDL. The language was developed by a team of programmers at the DM Group and MIT's better-known AI Lab. In short, MUDL is what it says exactly on the tin. It's LISP with more data types. The syntax and structure is a little bit different, but in general, MUDL is modeled closely off LISP. M Muddle was built to be the primary language used within the DM group and a native option for ITS. Lisp was used as a base because the older language had great support for strings, plus was already kind of being used as the lingua franca of artificial intelligence. Lisp was developed at MIT, so there's also this home team advantage to be aware of.
Starting point is 00:21:47 MUDL offered everything that Fortran was lacking. MDL was adept at handling strings for one thing, but most importantly of all, MUDL had much better support for data types. I mean, it should go without saying, it's in the name. You could define new data types on the fly, which was a huge boon in itself. But MDL also offered actual objects and all the features that came along with that. And, this is the big one, Muddle was able to treat functions as variables. This is a little subtle, but it makes a world of difference. Muddle lets you define a variable, or an object property for that matter, as a function.
Starting point is 00:22:32 That function can be reassigned, moved around, and executed. This would have a profound impact on what programmers were able to do with MDL. So this is the setup. Call it another perfect storm. We have a wildly popular game that blows up a pretty new genre. We have a group of wildly motivated hackers obsessed with that game, and we have a new tool that's just waiting to be exploited. All the pieces are set for something spectacular to happen. Zork proper begins with a core group of four programmers inside the dynamic modeling group. We've already met Tim Anderson. He's one of the key programmers. More importantly for me, Anderson wrote up a pretty comprehensive account of the history of Zork back in 1985.
Starting point is 00:23:20 As far as I'm concerned, that's the definitive first-hand account. 1985. As far as I'm concerned, that's the definitive first-hand account. According to Anderson's account, the first person to actually devote code to keyboard was Dave Lebling. As soon as Adventure was quote-unquote solved, Lebling set to work on creating a new text-based game. He already had some experience writing mainframe games. Most of the Zork group did. Lebling started by tackling the most front-facing part of any text-based adventure game. That's the command parser. This is the code that handles user input. It's how players actually interact with the world. Lebling's weapon of choice for this task was, of course, muddle. This parser showed promise, and this is
Starting point is 00:24:03 where Anderson gets involved with the new adventure. Tim and Mark Blank, another programmer, took Lebling's command parser and started using it to build a small virtual world. As Anderson recalls, quote, Mark and I, who were both in the habit of hacking all night, took advantage of this to write a prototype four-room game. It has long since vanished. There was a band, a band box, a peanut room, the band was outside the door playing Hail to the Chief, and a chamber, quote, filled with deadlines, end quote. Now, Blank is a really strange case of someone who became enamored with programming. And I think he's illustrative of a larger point here. In 1977, he was already enrolled in medical school in New York. But, as he put it,
Starting point is 00:24:55 that was boring. Blank was planning on having a career in medicine, but wasn't a huge fan of the endless lectures. He worked out his schedule so that he could just skip days worth of lectures every week to drive up to MIT and crash the DM group's lab. Blank just found programming to be much more fun than med school. I want to pause here to highlight this as a trend that's forming. Zork was never an official MIT research project. It didn't start off with funding or any research goals. Its only goal was to make a fun computer game in the mold of Colossal Cave Adventure. Everyone involved got in on the project because
Starting point is 00:25:41 it was the most fun thing they could think of. Blank is a great example here. He was driving back and forth between med school in New York and MIT just to program with his friends. He wasn't doing it for money or to publish a paper, this was all in the pursuit of fun. We can see how this attitude is leaking into the code even at this proto-Zork stage. What's the proof of concept look like? Is it an example of traversing data structures or rendering descriptions of simple rooms? No, it's a tiny world full of chambers. There's even a room full of deadlines.
Starting point is 00:26:21 Even at the beginning, Zork is shaping up to be a labor of love. It's a program full of fun and jokes. It just happens that it was backed up with some nifty data structures and some really sound programming by some really good programmers. According to Anderson, this proto-Zork was quickly dropped. It showed that a new adventure-ish game could be written in MUDL, but was left lacking. It was an early beginning. After some playtesting, this initial code was scrapped and the team set in on a larger project. A new member, Bruce Daniels, joined the group. This brings us up to the pack of four that's usually referred to as Zork's Implementers, or simply as Imps. But this four-person configuration here is a little misleading, at least to begin with.
Starting point is 00:27:12 The very first version of Zork, the game written after the four-room test version, was actually written while Leblanc was on vacation. This also brings us to another strange bit of terminology. I've actually been using the name Zork to reference the game that was taking shape in 1977 at the DM Lab. It's not entirely clear when that name was first slapped on the program. You see, Zork's name came kind of by accident. According to Anderson, quote, Zork was a nonsense word floating around.
Starting point is 00:27:47 It was usually used as a verb, as in Zork the Fweep, and may have been derived from Zorch. Zorch is another nonsense word implying total destruction. We tended to name our programs with the word Zork until they were ready to be installed on the system. End quote. The game was unfinished, so it was just being called Zork as a placeholder. The intent was to rename it later, but that didn't work out as expected. This seems like a simple enough explanation. These nonsense technobabble words are pretty commonly used among programmers. You can even see relatives like foo, bar, or baz show up in textbooks. But, you know me, I can't leave well enough alone. There's a strange detail here that's a bit of a tangent, but I certainly think it's worth addressing. This comes down to Zorch,
Starting point is 00:28:49 Zorch, as in Z-O-R-C-H. Anderson says that Zork may have been derived from Zorch. Usually, this kind of esoteric linguistic stuff is impossible to track down, but this is a case where we actually have a really good source to work off of. In 1975, the first version of the jargon file was written. This contains a pretty exhaustive lexicon of hacker words and phrases, and crucially, it was mainly contributed to by programmers at MIT and Stanford. There are also archives of the jargon file that we can consult for period-accurate words and definitions. During the first few years of activity, we have versions released every few months, so we can get really granular with it. The general idea that I had here is that if Zorch was in common use around this time, then it should be in the jargon file. And, well,
Starting point is 00:29:40 it's not. Zorch doesn't show up until the 1983 version of the file, which was later published as the Hacker's Dictionary. This is canonically called version 1.5. Stranger still, version 1.4 references Zork in a definition for another text-based game. The final puzzle piece here is that Anderson's written history of Zork was published in a newsletter in 1985. So, let's put all of this together. We don't have a full picture, but we do have some kind of complicated picture. Option one, Zorch was a word really specific to the dynamic modeling group. Most of the authors of the jargon file within MIT were from the AI lab, so conceivably there could be some missing DM group stuff.
Starting point is 00:30:36 Now, I'm kind of of two minds on this. References to ITS, a very DM group-specific thing, show up in very early versions of the file, so the jargon file should be covering this area of slang, but hey, maybe it's an oversight. Option two is that Zorch wasn't in use until the 1980s, and Zorch was an unrelated word used by a small group of friends. This is the one I'm kind of leaning towards, but I don't think we can ever prove either options. Anyway, this is all just a tangent to the larger history of Zork. I just think this is an interesting side mystery. Moving back onto topic, the implementers blazed through
Starting point is 00:31:19 the first version of Zork at really a breakneck pace. Loebling was off on vacation for only two weeks. By the time he returned, there was a playable version of Zork. At this point, it was still a pretty small game, but the basics were in place. There was also a new philosophy around the game taking shape. The team of implementers wanted Zork to be an immersive experience, one where the players could sink into a simulated world and forget about the computer. This was actually in pretty stark contrast to Colossal Cave Adventure. In general, all commands in Adventure are two-word sentences. Go west. Take lamp. Open cage. You can't give very complicated commands or the game will get confused.
Starting point is 00:32:06 It's not possible to say, Hit the troll with the rusty lamp. That would just result in an error message. This was a known problem, but Crowther actually ascribed Adventure's success to it, at least in part. He had this to say in a 1994 interview. Quote, And why did people enjoy it?
Starting point is 00:32:24 Because it's exactly the kind of thing that computer programmers do. They're struggling with an obstinate system that can do what you want, but only if you can figure out the right thing to say to it. End quote. Adventure is more like an intricate puzzle box. It has treasures tucked inside, but you need to figure out exactly how to open it. That's accomplished through this rigid and almost stilted dialogue. It's primitive, no doubt that's partly thanks to being written in Fortran, but at least according to Crowther, that made it fascinating to a lot of programmers. The problems here should be pretty plain to see.
Starting point is 00:33:03 This is a limiting format, and it's a bit of a grueling format to play. Programmers do this kind of problem-solving day in and day out. You can't really escape into a game if the game is just more of your normal existence. It also does a disservice to the roots the text-based adventure games grew out of. does a disservice to the roots the text-based adventure games grew out of. You see, whether we're talking Adventure or Zork or any other computerized fantasy game of this era, they all draw from the same well. Dungeons and Dragons. These games were all written by a gaggle of nerds after all. These early adventure games drew their high fantasy settings and some of their mechanics from tabletop adventures like those played out in D&D. This even shows up in
Starting point is 00:33:51 the text-based interfaces. A game of Dungeons & Dragons plays out like a conversation between a group of players and a dungeon master, or DM. A player will say what they want to do, the dungeon master then interprets that within the framework of D&D's rules and determines how to proceed. In the case of a complicated action like combat, for instance, the player may need to roll some dice to determine an outcome. In more simple cases like just moving around a map, the DM will just modify the game state. But the core gameplay all comes down to a spoken conversation. Players have to describe what they want to do, and the DM has to make sense of it.
Starting point is 00:34:33 Adventure functions like a digital dungeon master, but with a very limited scope and limited vocabulary. You can end up spending more time trying to work out how to talk to Adventure than actually solving the game. Zork's implementers didn't like that. They didn't think that it would be fun or make the game popular if you're just trying to struggle with the program. In the 1979 IEEE article I cited earlier, the Imps laid down a general framework for what they called a computerized fantasy simulator. According to the team, there was one aspect of the game that had to be put first and foremost. Quote, The heart of any CFS game is the ability to mimic omniscience. By this we mean that the game should simulate the real world sufficiently well so that the player is able to spend most of his time solving the problems rather than solving the program.
Starting point is 00:35:31 End quote. Put another way, Zork wasn't meant to be a puzzle box. It was meant to be an actual adventure. That's all fine and good as a concept, but with goals this broad, you tend to run into technical road bumps. How can you make a computer seem smart enough for an adventure to feel immersive? How can you, quote, mimic omniscience? In D&D, for instance, a player might say, hey, I want to run up to that troll, I'm going to punch it in the face, then while it's reeling from the blow, I want to pick its pocket. That's not a very complicated concept for a human to deal with.
Starting point is 00:36:10 Someone just wants to go have a confrontation with a troll. You have some steps, maybe something about a chance to hit or damage comes into play, maybe some statistics about how hard it is to steal from a reeling troll. This is the kind of interaction where a human dungeon master can use their better judgment. You reference some tables, you generate some kind of outcome to feed back to the player. That's easy for us to do. If you know how to play D&D, if you know how to be a dungeon master, you can work this out pretty quick. But how do you translate that kind of knowledge into a computer fantasy simulation? Well, Zork takes a few different angles of attack. One that I think gets overlooked is that Zork, and for that matter Adventure, breaks everything down into small and
Starting point is 00:36:58 simple actions. You have to step through the game one room at a time. You can't move and interact with items at the same time. This partly comes down to how the medium is structured, but it also limits how players can interact with the world. Everything has to happen in turns, and each turn can only accomplish one small task. That alone really simplifies the programmer's job. small task. That alone really simplifies the programmer's job. The second trick is that Zork radically limits what a player can actually do. Zork is, after all, just a computer program. There will always be a limit to the realm of possibilities. The implementers, praise be, got around this by carefully constructing the story of Zork. Once again, from IEEE, quote,
Starting point is 00:37:46 What it can do, however, is simulate enough of the universe to appear to be more intelligent than it really is. This is a successful strategy only because CFS games are goal-directed. As a consequence, most players try to do only a small subset of things they might choose to do with an object if they really had one in their possession. End quote. If you pick up a key, you can use it to unlock something, you can pocket it, or you can toss it. All those eventualities are programmed into Zork, and looking at that list, that's just
Starting point is 00:38:21 three things, that's not a lot of options. In the real world, you might try to give it to a friend, or's just three things, that's not a lot of options. In the real world, you might try to give it to a friend, or get a copy made, or even scrape your name into the surface of something using the key. But if you're deep in a dungeon and find a key in some dusty desk, you probably aren't thinking about what you can vandalize. So Zork just doesn't need to have code for key scratching. Once again, these limitations can be used wisely to limit the scope of programming needed. To complement this design
Starting point is 00:38:53 philosophy, Zork is also pretty smart when it comes to processing commands. Remember that the text parser was the first thing written for the game. One of the tricks that made Adventure so slick was that it employed synonyms. The take action could be invoked by typing take, but also by typing grab. It's just a quick and dirty way to make things easier on the player. Zork took this a whole nother level above. Sure, it had synonyms for actions and objects, but that was just the start. In general, a full command in Zork is composed of an action and up to two objects. This gives you such hits as Take the lamp. Or unlock the door with the key.
Starting point is 00:39:37 Thrilling. But you don't always have to follow that pattern. To make things more manageable, Zork's parser will try to aggressively assume what the player wants to do. If you're trying to do an action with only one valid object within reach, Zork can figure out the proper result. If you're in a room with a solitary lamp, you can just type grab and Zork will reply that you now have a lamp in your inventory. This extends to more dynamic interactions. Let's say you run into a troll and decide that you don't want to talk anymore. You may start off by telling Zork to attack the troll. If you have more than one weapon,
Starting point is 00:40:18 then Zork will ask what weapon you want to attack with. You then further specify your sword. That's an action in two words, so Zork now has enough information to process your request and start slashing at the troll. Next turn, instead of typing the full ATTACK THE TROLL WITH THE SWORD, you just type ATTACK. Zork is smart enough to infer what you mean, and the troll slashing will continue. The whole point with this tech system is to make things easier on the player. Inspiration here is definitely, at least in part, coming from D&D. A human dungeon master will very readily make assumptions about what a player is trying to do. You could very well have the exact same situation where a player just says they want
Starting point is 00:41:02 to attack, the DM has to ask for some clarification, and then moving forward can guess what the player will do next round. They're gonna probably attack again. For us humans with our squishy, malleable brains, this is a dead simple process, but computers have to be programmed carefully to do something this natural. But that's just the textual part of Zork. As we look deeper, we get into the more interesting details. I want to pull us back to one of the core issues of Colossal Cave Adventure. How do you add a new puzzle? The only option for that game was to extend some of the core parts of its source code. Zork took a very different approach, one that would prove to be much more flexible.
Starting point is 00:41:49 Down at the code level, things get a little muddy, at least in this early era of Zork. Unlike Adventure, the newer text game didn't really break itself up into a separate game engine that read and ran a data file. All of Zork is defined as MDL code. At first glance, that might make it seem that Zork suffers from the same fatal flaw as Adventure, but don't be so hasty. Zork's source code is designed to be modular. I know that's a big buzzword, but let me explain. On the surface level, Zork is broken up into multiple MDL files. When you get down to it, this is kind of a convenience more than anything, but I think
Starting point is 00:42:33 it does serve an important purpose. In Adventure, everything was dictated by one big Fortran file. Anytime you needed to change something, you had to modify the core part of the game engine because there was only one part of the game engine. It's all the core. Zork spread things out into separate code files for the parser, room definitions, vocabulary, items, actors, and so on. When you're adding a new item, you only have to edit the item file. This saves you from trudging around in the depths of the text parser when you're trying to find, say, the code for handling keys. But like I said, this is the more superficial aspect. We can go deeper, and that's where we start to see the real modularity at play. In Zork, just about everything is defined as an object. That includes locations, items, enemies, pretty much anything you see in the game has some object backing it up.
Starting point is 00:43:32 Even actions are defined as objects themselves, which gives you a whole lot of flexibility. Zork is built up by defining new objects and then registering them with the game engine or referencing them somewhere else. So why does the whole object orientation of Zork matter? This all comes down to how you expand the game. For this, I want to stick with the bird and snake puzzle from Adventure, since I just think it's a good example. Remember that in Adventure, that puzzle's solution is hard-coded into the game's drop item handling. Zork has an analogous glob of code for the drop command and its many synonyms. However, it's not a very large glob of code. It's pretty simple. When you tell Zork to release the bird, it would see that as a synonym for the drop command, so the internal drop handler is invoked.
Starting point is 00:44:29 The handler gets the birdcage object and starts making some checks. Each object is composed of a set of flags and properties that describe the item. First off, drop makes sure that the item is actually being carried by the adventurer, you know, in case you're trying to do something funny. So far, seems fine. The next step is where Zork really sets itself apart from adventure. The drop handler never checks if the player is trying to drop the bird. That's not drop's job. It never checks any special cases at all. Instead, it checks to see if the object has its own handler function. Muddle objects can contain functions, their own little blobs of code that can
Starting point is 00:45:14 be executed on a whim. In Zork, each object carries with it a small function that's invoked whenever the player tries to perform an action on that object. This allows items to override the action's default behavior. Under normal circumstances, a dropped object will fall to the floor. But for the bird and snake puzzle, there needs to be an override. When you drop the bird from its cage, the bird's own handler gets called. It checks if there's a snake in the room. If so, the bird goes forth to scare off the snake and the puzzle is solved. You get some points. Otherwise, the bird just plops on the floor and sits there. The key element here is that Zork's core functionality doesn't need to be changed in order to add a new puzzle. Once the drop command was implemented,
Starting point is 00:46:04 it didn't need to get retouched for every new item interaction or new puzzle. Once the drop command was implemented, it didn't need to get retouched for every new item interaction or new puzzle. Instead, all the new features were added inside new items, enemies, and room objects. This might sound like it's just shifting around some code, but it had major implications. For one, it made expanding Zork much easier than expanding Adventure. You don't need to know how Zork's core programming logic works to add a new puzzle. This also insulated Zork from at least some snafus and bugs. Adding some bad code for a new object will just break that object. But it won't break any other part of Zork. just break that object. But it won't break any other part of Zork. The bottom line here is that modularity opened up new options for Zork's implementers. That allowed the game to blossom.
Starting point is 00:46:53 The game saw massive growth through the summer of 1977. By fall, ARPANET users were starting to notice something funny going on. Zork was being developed on a machine running ITS, an operating system totally devoid of security and barriers. So computer nerds across the ARPANET started seeing this strange Zork process running, and they would soon fall into the underground empire themselves. Zork spread in a somewhat similar way to Adventure, but once again, there were major differences between the two games. Adventure was so spreadable because everyone had access to a 4chan compiler. Zork was written in MDL, a language that at the time only ran under ITS, and there was only one mainframe that ran ITS. To play Zork, you had to connect to the dynamic modeling group's computer. Luckily,
Starting point is 00:47:47 the aforementioned lack of security made this an easy process, and so Zork enticed untold numbers of adventurers. But this lack of portability would be something of an Achilles heel for the game. The next phase of Zork's development takes us deeper into the realms of true madness. This final dive all starts with the question of portability. Within a year of its initial release, or at least its first sighting by outsiders, Zork already had a port. You see, Zork's implementers have been trying to guard the source code for the game since day one, either to protect their project or to keep players from getting spoiled on solutions. The code was hidden in a mislabeled folder on ITS, but the source was also encrypted to keep prying eyes further at bay.
Starting point is 00:48:38 However, we are talking early ARPANET. Everyone online at this point was a programmer or hacker of some stripe. It was only a matter of time before the code escaped. In 1978, Robert Supnik, a developer at DEC, decided that they wanted that code. At least, we believe this was the perpetrator, the name may be a little lost to history. Anyway, through some creative use of ITS and some free computer time, he was able to track down and then decrypt the source. Sure, it was in a language that could only be compiled for ITS, but it gave Supnik something to go off. Anderson describes the debacle in his Zork history like this, quote, As a result of the purloined sources at DEC, a lunatic there decided to translate Zork into Fortran. We had always assumed this would be impossible.
Starting point is 00:49:32 Muddle is very, oops, very different from Fortran and much more complicated, and we'd used most of its features in designing Zork. The guy who did it was mostly a hardware person, so perhaps he didn't know what he was up against. At any rate, shortly after the great blizzard of 78, he had a working version implemented initially for PDP-11s. Since it was in Fortran, it could run on practically anything, and by now it has." This is mostly a sideshow to the main story. I don't really want to do another code deep dive into a Fortran program today, but the Fortran port is important for two big reasons. Every mainframe had a Fortran compiler. The wild port made Zork even more popular since now
Starting point is 00:50:23 anyone near a computer could experience Zork, even without an ARP net connection. As 1978 drug on, Zork became more and more popular amongst a certain crowd. The 4chan port went a long way towards proving that there was an audience for this kind of software. Just as important, it also proved that Zork didn't necessarily need to be written in MUDL. But the implementers were about to face another problem. Graduation. Zork was nominally finished around 1979,
Starting point is 00:50:57 with the final mainframe version taking up just over one megabyte of memory. That's a lot for the time. It was a major achievement, and the ragtag team of programmers wanted to do more. Mark Blank, Tim Anderson, Dave Lebling, as well as a few other programmers around the CS department wanted to somehow stick together and keep on hacking up projects. The only viable way to do this after graduation was to start some sort of company. They would need to create a productive outlet for their collective programming obsession. In 1979, Infocom was formed. The initial plan was to do something about software.
Starting point is 00:51:39 From Anderson's account, it seems like the real goal was just to keep having fun and hopefully find a way to make a living out of it. Zork wasn't their first go-to, but it soon took center stage. Joel Perez, one of the other MIT programmers that joined Infocom, and Mark Blank figured that it might be possible to get Zork running on a home computer. I mean, some madman had ported it to Fortran, so anything was possible, right? The market environment of the time played heavily into this next big leap. In the 70s, the home computing market was relatively diverse, at least more so than the current PC monoculture. The Apple II, TRS-80, and Commodore PET made up the majority of the market, with Altair and Altair-like computers somewhere on the periphery. So ideally, any software
Starting point is 00:52:33 manufacturer would want to court multiple platforms at once. You really wanted to be able to sell ports of your software for all major machines in the market. The other complicating factor for Zork specifically was the matter of memory. All home computers of the time period had RAM sizes measured in the tens of kilobytes if you were lucky. Zork may not have any graphics, but it's still a pretty complicated program. It has a whole lot of text and a good amount of logic to run everything. It was designed to run on a mainframe, after all. So shrinking it down to run on a home computer and trying to make it portable
Starting point is 00:53:11 at the same time, well, that was going to be a challenge. But it would be a fun challenge. Luckily, the Infocomp team, fresh from graduation, was really up to the task. Anderson recalls, quote, Joel and Mark began some seat-of-the-pants design work, much of it on Joel's parents' coffee table, on how much Zork could be compressed, and how to do it in a flexible way to allow for different incompatible personal computers in the future. They considered using some available portable tools for programming, like UCSD Pascal, but it soon became clear that Zork had too much text in it. They finally concluded that, by inventing a programming system specifically for Zork, they could fit about half of it into a computer with 32 kilobytes of
Starting point is 00:53:58 memory and one floppy disk drive, end quote. Calling their solution a, quote, programming system undersells the complexity a little bit. What Blank and Barrez hashed out on a coffee table was called the Z-Machine. It's an entire computer designed from the ground up just for running Zork. This is, perhaps, the most complicated solution possible. But this wasn't just flexing their degrees to show off. There was a method to this madness. For one, the Z-Machine isn't a real computer. It's a virtual machine.
Starting point is 00:54:37 It's a specification for a theoretical computer that can then be implemented as software. computer that can then be implemented as software. Think of it as a tiny software-designed computer that's built up just to run text-based adventure games. The Z-Machine has its own registers, its own stack, its own memory space, and input-output routines. It just so happens that everything is mediated through software instead of silicon. In a more modern parlance, we call the Z-Machine a bytecode interpreter. You pass the Z-Machine a program, sometimes called bytecode, that's written specifically for this virtualized computer. The Z-Machine interpreter then reads the bytecode and figures out how to run each instruction using its host computer. In that sense, it's interpreting the bytecode for the host. That host computer can be anything. An Apple II, a TRS-80, even a modern PC. The glue that makes
Starting point is 00:55:33 it all possible is the bytecode interpreter, or as Infocom called it, the Z-Machine Interpreter Program, aka the ZIP. This may sound outlandish at first, but this is a pretty common practice. The most high-profile example of a bytecode interpreter has to be Java. In the 90s and early 1000s, Java was able to rise to prominence thanks to its wild portability. It seemed like just about any computer could run Java. The portability was all thanks to the fact that Java compiled down to bytecode that ran on the Java virtual machine. To spread Java to a new system, all you had to do was rewrite the JVM for that new platform and boom. Every Java program in existence worked on that new computer. It should be plain to see why this was such a big draw for the Zork team.
Starting point is 00:56:26 The zip was a lot less code than Zork itself, so porting the game would be considerably easier. But how does this address size? Well, this gets us into the actual implementation details of the Z-Machine. The short story is the Z-Machine was designed to work with objects, so it made for more efficient bytecode. Let me unpack why that matters and why I think that's so wild. For this to have its proper impact, I think it's important to keep in mind that Infocom's version of Zork was targeting 8-bit home microcomputers. At the time, these machines were running either assembly language or BASIC programs. Compared to something like MUDL, these small environments were primitive. BASIC doesn't have objects, and assembly language doesn't offer you anything.
Starting point is 00:57:19 Talking technically, Zork was a program that used objects to manage data. While possible to reimplement without objects, that would destroy all of the sophistication of the game's engine. So when the shadowy implementers sat down to design the Z-Machine, they had objects in mind. This approach of building a virtual machine for a very specific task allowed them to create the best possible environment for that task. So the Z machine was designed for managing object data. Specifically, it was designed to work with trees of objects. A tree in this context is a data structure that stores data in a hierarchy, such as rooms connected to other rooms or items inside of rooms. The immediate benefit is that working with objects on the Z-Machine is dead simple.
Starting point is 00:58:12 It has built-in instructions for moving objects in memory, traversing the object tree, and getting and setting object properties. It goes further, but just those four operations should give you a taste of what the Z-Machine offers. further, but just those four operations should give you a taste of what the Z-Machine offers. You can accomplish really complex object manipulation using a single instruction. That's just plain convenient. What's interesting is when we start looking at the impact of these complex instructions at scale. For example, let's take the insert object instruction. This instruction will insert an object into a specific
Starting point is 00:58:45 location in the object tree. If my reading on the docs are correct, then it takes a grand total of four bytes to encode that instruction and its arguments as Z machine code. For a normal computer, this type of operation would require multiple instructions. You'd need to do something along the lines of shuffling around pointers in memory, maybe changing some values of certain memory locations. When all's said and done, you'd probably end up using more than four bytes of machine code. So the Z machine helps you shave off a few bytes here and there. Moving around objects takes less machine code. So does accessing objects and their properties. So does moving around trees and there. Moving around objects takes less machine code, so does accessing objects and their properties, so does moving around trees and tables. Since most of Zork's code is just shuffling around
Starting point is 00:59:32 objects and manipulating data, the savings really adds up. The net result is that a Zork port for the Z-Machine ends up being a much smaller program, even when you take the size of the Z machine interpreter into account. This is phase one of the true madness. Anderson said that we're dealing with an entire programming system, and he wasn't wrong. The Z machine was a totally new computer, or rather, a totally new fake computer. It didn't have any native compilers or programming tools, so the next step after defining the machine was to make some tools to actually use with it. The big one here, and the final wild choice that we need to talk about, is called the Zork Implementation Language, or ZIL. The language was developed by Mark Blank
Starting point is 01:00:22 as the final piece that would make a microcomputer Zork possible. ZIL is essentially a remixed version of MUDL. Blank took out all the parts of MUDL that Zork was actually using, simplified that even further, and then continued the simplification some more. ZIL looks a lot like MUDL. The syntax is roughly the same, but ZIL is actually a pretty rudimentary imitation of the larger mainframe language. The big difference comes down to stuff like memory allocation and garbage collection. I know, riveting. MUDL has both, but ZIL has neither. Blank gets away with stripping out these more advanced features because, for all the complications going on here, Zork is a really simple program.
Starting point is 01:01:10 Like I keep saying, the backend of Zork is all about managing data. But you aren't ever making new data, you're just interacting with a mostly static pile of objects. We can even see this deep inside the Z machine. The memory map for the virtual computer is broken up into three major sections. Global variables, the object tree, and object functions. The object tree is, for the most part, static. Sometimes objects will get moved around in the tree,
Starting point is 01:01:41 for instance, when you drop an item, that changes its location in the object tree. Functions are, well, just functions. That's static. You don't want that to be any other way. That just leaves global variables, which are used to keep track of the game's state. Those are defined on compile time, their values change, but their location and size in memory stays constant. Once again, it's all static. It may be a bit of a hyperbole, but ZIL seems to share more in common with a data descriptor language like HTML or LaTeX than a general purpose language like MUDL. When you put this all together, the Z-Machine specification, the actual Z-Machine interpreter program, and ZIL, you get a surprising recipe for success. The Z-Machine spec was written
Starting point is 01:02:33 really soon after Infocom forms. The first interpreter was written soon after for a DexSystem 20 that Infocom bought to use as a development system. A ZIL compiler called Zilch was next on the list. By the end of 1979, the first big section of Zork had been ported to ZIL, and a second Z machine interpreter had been written for the TRS-80 Model 1. This is, in no uncertain terms, a wild pace of development. In under a year, the implementers had pulled off a really amazing feat, and here's where it all paid off. By the beginning of 1980, the first third of Zork, what Infocom would sell as Zork 1, was running on the TRS-80 Model 1.
Starting point is 01:03:21 The retail release of Zork required just 32 kilobytes of RAM. By the end of 1980, a new Z machine interpreter was written for the Apple II, and Zork was suddenly running on two of the three most popular home computers. The IBM PC was released in August of 1981. By 1982, it had its own port of Zork. By 1982, it had its own port of Zork. Alright, that brings us to the end of this episode. At the tail end of our discussion of Zork, I think we can see a pattern formed. At first, the idea of developing an entire virtual computer and new programming language sounds kind of laughable.
Starting point is 01:04:05 But as time went on, that choice really paid off. Now, what made this all work so well was that Zork was, and still is, really fun to play. It would be one thing if Infocom made a highly portable game that was just okay. But Zork is a fantastically fun game in its own right. The way I see it, Zork, especially the retail release, was an absolute labor of love. The implementers started off just having fun programming, and they wanted to keep the fun going. To couch this in fancier terms, Zork's implementers made effective use of abstraction. Zork's implementers made effective use of abstraction. Once we get to the retail release, Zork wasn't really written for the Apple II or the TRS-80 or even the IBM PC. It was written for the Z machine.
Starting point is 01:04:58 It just so happened that Z machine code could run on many multiple platforms. That's the technical side of things, but we can't forget the creativity at play here. One of the huge reasons for Zork's success is that it's fun and impressive. The implementers said it best themselves. They wanted Zork to be about solving puzzles, not solving the program. We can easily say that Zork was heavily influenced by Adventure. That much is crystal clear. Adventure was the whole reason Zork was created in the first place. But when we get down to it, I think Zork is more of a response to adventure than a direct descendant. All the way back in the dynamic modeling group, a small team of programmers
Starting point is 01:05:36 decided that Zork would be different than Adventure. That it would be better. And luckily, they had the technical chops to make that possible. In closing, go play some Zork. Thanks for listening to Adrin of Computing. I'll be back in two weeks' time with another piece of computing's past. And hey, if you like the show, there are now a few ways you can support it. If you know someone else who'd be interested in the story of computers, then why not take a minute to share the show with them?
Starting point is 01:06:04 You can also rate and review on Apple Podcasts. If you want to be a super fan, you can support Advent of Computing directly through merch or becoming a patron on Patreon. Patrons get early access to episodes, polls for the direction of the show, and bonus content. You can find links to everything on my website, adventofcomputing.com. If you have any comments or suggestions for a future episode, then go ahead and shoot me a tweet. I'm at adventofcomp on Twitter. And as always, have a great rest of your day.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.