Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

2024 Participants: Hannah Ackermans * Sara Alsherif * Leonardo Aranda * Brian Arechiga * Jonathan Armoza * Stephanie E. August * Martin Bartelmus * Patsy Baudoin * Liat Berdugo * David Berry * Jason Boyd * Kevin Brock * Evan Buswell * Claire Carroll * John Cayley * Slavica Ceperkovic * Edmond Chang * Sarah Ciston * Lyr Colin * Daniel Cox * Christina Cuneo * Orla Delaney * Pierre Depaz * Ranjodh Singh Dhaliwal * Koundinya Dhulipalla * Samuel DiBella * Craig Dietrich * Quinn Dombrowski * Kevin Driscoll * Lai-Tze Fan * Max Feinstein * Meredith Finkelstein * Leonardo Flores * Cyril Focht * Gwen Foo * Federica Frabetti * Jordan Freitas * Erika FülöP * Sam Goree * Gulsen Guler * Anthony Hay * SHAWNÉ MICHAELAIN HOLLOWAY * Brendan Howell * Minh Hua * Amira Jarmakani * Dennis Jerz * Joey Jones * Ted Kafala * Titaÿna Kauffmann-Will * Darius Kazemi * andrea kim * Joey King * Ryan Leach * cynthia li * Judy Malloy * Zachary Mann * Marian Mazzone * Chris McGuinness * Yasemin Melek * Pablo Miranda Carranza * Jarah Moesch * Matt Nish-Lapidus * Yoehan Oh * Steven Oscherwitz * Stefano Penge * Marta Pérez-Campos * Jan-Christian Petersen * gripp prime * Rita Raley * Nicholas Raphael * Arpita Rathod * Amit Ray * Thorsten Ries * Abby Rinaldi * Mark Sample * Valérie Schafer * Carly Schnitzler * Arthur Schwarz * Lyle Skains * Rory Solomon * Winnie Soon * Harlin/Hayley Steele * Marylyn Tan * Daniel Temkin * Murielle Sandra Tiako Djomatchoua * Anna Tito * Introna Tommie * Fereshteh Toosi * Paige Treebridge * Lee Tusman * Joris J.van Zundert * Annette Vee * Dan Verständig * Yohanna Waliya * Shu Wan * Peggy WEIL * Jacque Wernimont * Katherine Yang * Zach Whalen * Elea Zhong * TengChao Zhou
CCSWG 2024 is coordinated by Lyr Colin (USC), Andrea Kim (USC), Elea Zhong (USC), Zachary Mann (USC), Jeremy Douglass (UCSB), and Mark C. Marino (USC) . Sponsored by the Humanities and Critical Code Studies Lab (USC), and the Digital Arts and Humanities Commons (UCSB).

Code Critique: Hitchhiker's Guide to the Galaxy

Software: Hitchhiker's Guide to the Galaxy (Game)
Authors: Steve Meretzky and Douglas Adams
Language: ZIL: Zork Implementation Language
Year: 1984
Source file:
Code repository:
Zil Code Manual:

The Hitchhiker's Guide to the Galaxy was a text adventure game based on the book/radio/television series that was known in the universe for serving puzzles that made you want to smash your brain with a brick wrapped in a lemon. See this discussion for some common reactions. In this puzzle, and this is a spoiler, you need to have previously removed your common sense so that you can at once have "tea" and "no tea" in your inventory.

I wanted to start a thread to invite you all on a sidequest to explore the code of this game that I encountered at a very formative time of my life. Pretty much influenced everything I do as an e-lit artist. But I do recognize (especially having tried to teach it) that this game goes beyond the usual level of frustration-inducing puzzles that @jeremydouglass has written about. Some argue that the difficulty of the puzzles was tied to a profit motive -- selling more hint books, increasing gameplay time. A later game from Adams, Bureaucracy, would make frustrating puzzles its main theme. I'm not sure this is the best passage to start with, but I'd like to use this to open a code exploration of this game and perhaps also The Restaurant at the End of the Universe code, which I am just learning exists!

                <PRSO? ,ME>>
              (<VERB? HELLO>
              (<AND <VERB? WHAT>
                <PRSO? ,OBJECT-OF-GAME>>
"\"Unless you're here to show me some clear sign of your intelligence, please
leave me alone. I'm a very busy door.\"" CR>
             <VERB? SHOW GIVE KNOCK OPEN>>
        <TELL "You already induced the door to open." CR>)
             <VERB? CLOSE>>
"The door snaps, \"Hey! I'm resting. I've had a very busy day.\"" CR>)
           (<VERB? KICK>
"\"I suppose you think that since you have legs and I have not, you can get
away with that sort of thing. Well,\" the door continues stiffly, \"maybe you
can and maybe you can't.\"" CR>)
           (<VERB? SHOW GIVE>
        <COND (<AND <PRSO? ,TEA ,NO-TEA>
                <HELD? ,TEA>
                <NOT <PRSO? ,TEA-SHOWN>>>
               <COND (<PRSO? ,TEA ,NO-TEA>
                  <SETG TEA-SHOWN ,PRSO>)>
               <COND (<PROB 50>
"The door says \"Big deal. Anyone can have">
                  <ARTICLE ,PRSO>
                  <TELL ".\"" CR>)
                  <TELL "The door yawns." CR>)>)>)
           (<VERB? OPEN KNOCK>
        <COND (<AND <HELD? ,TEA>
"The door is almost speechless with admiration. \"Wow. Simultaneous tea
and no tea. My apologies. You are clearly a heavy-duty philosopher.\" It
opens respectfully." CR>)
"The door explains, in a haughty tone, that the room is occupied by a
super-intelligent robot and that lesser beings (by which it means you)
are not to be admitted. \"Show me some tiny example of your intelligence,\"
it says, \"and maybe, just maybe, I might reconsider.\"" CR>)>)
           (<AND <VERB? ASK-ABOUT>
             <PRSI? ,OBJECT-OF-GAME>>
        <TELL "\"To keep out sub-intelligent beings.\"" CR>)
           (<VERB? THROUGH>
               <DO-WALK ,P?EAST>)
               <DO-WALK ,P?WEST>)>)
           (<VERB? EXAMINE>

A few questions:
How does this code speak to the frustration-inducing nature of the game?
What does this code reveal about ZIL as a language?
Or does this code show that the game is just terribly misunderstood?
Is this a representative passage from the game?
How does this compare with puzzles of other Infocom games of the time?
What other passages of the HGTTG code should we explore?


  • I'm not sure what on line 24 does, but I like how it reflects a programmer's or user's actual language in use; after all, who hasn't periodically sworn at their machine?

    I did peek into the source code for ZIL verbs, and happened to find HO-HUM. While it "doesn't do anything", it does make me laugh and reflect on 'ho-hum-ness' and ineptness on a planetary scale:

         " doesn't do anything."
         " accomplishes nothing."
         " has no desirable effect.">>  

    link to source code:

  • @Lesia.Tkacz said:
    I'm not sure what on line 24 does, but I like how it reflects a programmer's or user's actual language in use; after all, who hasn't periodically sworn at their machine?

    Yeah, my first thought is that there was a CLEAR command that didn't quite work and someone finally added FUCKING-CLEAR out of frustration. I bet this sort of thing was way more common before the expectation that everyone's code would eventually end up in public on github!

  • I have never seen this -cool! At first I thought - LISP (but not lisp). Then I thought is screening door only set to the winner within the conditional (so you can never access this block of code).

    As I started reading this I realized that I don't want to read this. I want to see this represented as a graph. I started reading the ZIL manual, which I found more interesting than this code. Why? The ideas and metaphysical assumptions that go into ZIL are perhaps richer than the implementation.

    The main conceit behind the hhg code seems more about playing with variable names, and playing up the fact that code is written in human readable language. There is a DSL aspect to to this program, enabled by ZIL, which provides x-ray vision into the world of hhg, and that is one of the things literature does, ie. create its own world.

    My main gripe with this work is that it has a punch line, the play with language makes it appear like a piece of work by Gertrude Stein or something, is open to a multiplicity of interpretations. Where as with this program, the puzzle nature of it, implies a right and wrong way of reading it. To read it in another way is to 'queer' the game (recommended reading

    I did have an inexplicable flashback to uni and writing a wumpus ai.

  • Hi! Mark invited me to drop in on this conversation.

    I have the advantage of having written a lot of text games in this format, although I didn't use ZIL. So I have a pretty good idea of what the code is doing.

    It's not exactly written in human-readable language. But given its genesis in the MIT community, maybe the developers didn't consider "human-readable" and "programming language" to be separate concepts!

    I agree that HO-HUM is a fine example of a well-named data structure. (It's an array of strings, not a verb per se.) Even better is the function that makes use of it: HACK-HACK, which is used to print a sentence of the pattern "XXX doesn't do anything" or "YYY accomplishes nothing." (See verbs.zil:2887.) The word "hack" has a dense cultural history in the MIT world; I really don't have a sense of what "HACK-HACK" would have meant to an MIT alum circa 1984.

    An even better example is the variable WINNER. In Infocom's parser code, this always refers to the character who is taking action at that point. It goes back to the earliest Infocom games -- you can see the same variable in Zork 1, where it essentially always referred to the player. In HHGG, WINNER switches around quite a bit. It can refer to the playable characters (Arthur, Trillian, Zaphod) or the active NPCs (Prosser, the Beast, etc).

    "Winner" was common MIT slang. The Jargon File ( says "often sarcastic" -- i.e., a euphemism for "loser". But not always. I sense that the ambiguity was part of the fun. Referring to the player as "WINNER" was some kind of joke, but cruel or kind?

  • HACK-HACK looks like a common routine (although implementations vary across games).

    There's a description in one of the infocom memoires (which I can't currently find, alas) of the way that a new game would be started: the source for something recent copied across to a new directory, the imp hacking out the game-specific stuff, and then building on that. So there are many common idioms that would grow and become the established way of expressing ideas, I think (even if the implementations behind those ideas became more sophisticated over time). This would be a rich source for analysis.

    Just out of curiosity, I've tabulated routine definitions across a bunch of infocom games for which source is available. You can see the result here. It's a pretty low-fidelity start [assembled using awk, so it's not even aware of the syntax of ZIL] to that kind of analysis, but it does indicate some things that shared common ancestry.

    (I was wondering if FUCKING-CLEAR was one of those inherited features - but it looks like it wasn't. I wonder if that was a contribution directly from Adams?)

  • (I was wondering if FUCKING-CLEAR was one of those inherited features - but it looks like it wasn't. I wonder if that was a contribution directly from Adams?)

    So, in perhaps my most juvenile bit of research and no doubt a shining moment in CCS, I just checked the repository for the other Meretzky games and did not find it in any of them.

    However, it does appear in the unreleased code for the Restaurant at the End of the Universe game in the files people.zap and people.zil, code attributed to Stu Galley and others. Seems to point to that coming from Adams.

  • Jimmy Maher's writeup ( is pretty clear that Adams was not involved in the coding of the game. Meretzky did all the implementation.

    The definition of FUCKING-CLEAR in Restaurant is identical to that in HHGG, except that one line is commented out. (The routine clears two parser flags, P-CONT and QUOTE-FLAG. But all use of QUOTE-FLAG in the Restaurant code is commented out.) So I figure that the Restaurant project was started by cloning the HHGG code, and then rearranging, tidying up, and removing features that wouldn't be used in the new game.

    The function name could still have been Adams' voice coming through, but it could equally well have been Meretzky. One can easily imagine the sort of day (or late night) where you spend two hours tracking down a bug, say "I forgot to fucking clear that fucking quote flag?!", and then write a function to fix it.

  • One of the things I was thinking about when posting this snippet was the way the frustration of the way this game is implemented is epitomized by a puzzle that requires the player/winner to possess tea and no tea at the same time. You need to possess not possessing tea, while not possessing your own common sense.

    Can you all help me out. Is "no tea" a flag? a variable state?

    How does that (whatever it is) change the way we read the scene with the puzzle or this code?

  • "No tea" is defined as an object just like any other object in the code. It's an 'object' in both the programming sense (as seen in object-oriented programming) and also, literally, an object manifest in the game- in this case an inventory item.

        <OBJECT NO-TEA
            (IN GLOBAL-OBJECTS)
            (DESC "no tea")
            (SYNONYM TEA)
            (ADJECTIVE NO)
            (ACTION NO-TEA-F)>

    Having the absence of something as an inventory item (a felt absence) is a good joke in itself, and the joke is really committed to by giving the standard dropping and taking messages for the "no tea":

     <ROUTINE TEA-F ()
         <COND (<AND <VERB? TAKE>
                 <PRSO? ,TEA>>
            <MOVE ,TEA ,PROTAGONIST>
            <SETG HOLDING-NO-TEA <>>
            <TELL "no tea: Dropped." CR>)
               (<VERB? DROP>
            <MOVE ,TEA ,HERE>
                   <SETG HOLDING-NO-TEA T>
                   <TELL "Dropped." CR>)
                   <SETG HOLDING-NO-TEA T>
                   <TELL "no tea: Taken." CR>)>)

    Moreover, there is a text adventure convention that player will soon check their inventory on starting a game, and so placing a goal in the inventory is a fine way to begin motivating the player, especially as the goal can then be checked later at the player's convenience.

  • But note the existence of a global variable HOLDING-NO-TEA, which is set true or false in sync with the NO-TEA object.

    Well, let's verify that... it's set true when you TAKE the NO-TEA. It's set false when you TAKE the TEA. (This is in TEA-F and NO-TEA-F, the action handlers for those two objects.) Things get messier when you DROP the TEA, though! That's the end of the function quoted just above... it looks like it distinguishes the case of DROP TEA when you're holding the tea ("no tea: Taken") from the case when you're holding both ("Dropped.")

    Makes sense once you squint at it and count on your fingers.

    There are a few other places where the flag is set true. Turning on the Drive when it's running off the tea, and -- curiously -- when taking inventory. Perhaps they were worried about the flag getting set wrong, so they fix it up at INVENTORY time?

    The interesting question is why have a flag at all? It should be sufficient to test <HELD? ,TEA> at any time.

  • Greetings—Not sure if the group is already aware of these links, but in case there’s an interest in playing the game alongside the code, here are some running implementations.

    This one is a no-frills, pure-text implementation:

    And this one, commissioned by BBC, has a more elaborate graphical wrapper around the core game but I presume it's still the same game within:

    I wonder if there's an easy-to-start Z-machine implementation where one can load the code, play it, mess with it a bit, then play it again, just to see what happens (or if one can dodge/change certain puzzles in the game).

  • The interesting question is why have a flag at all? It should be sufficient to test <HELD? ,TEA> at any time.

    Perhaps flags are checked with a higher priority than objects and this was to ensure the correct line triggered somewhere. Or possibly they had it as a flag first, wrote some code for it, and then introduced it as a physical object in the inventory later and then never cleaned everything up again. I know from my own experience in authoring, it's very easy to end up with variables that have been made obsolete but may continue to be used. For instance, I might originally define a flag with a true/false boolean, and then later a third possibility is written and so a new numerical variable is created: if I'm lazy and it's relatively minor, both those variable might continue to persist in the code.

  • edited January 2020

    Douglas Adams also comments on the "no tea" puzzle from Infocom's Hitchhiker's Guide to the Galaxy in this production note shared by Jess Morrissette:

    To provide some context for this code, here is a walkthrough narrating the gameplay by
    Lisa Fitzsimmons,[1] who describes the conclusion of the screening door puzzle in this way:

    War Chamber and Maze (hearing, "below")

    Hear the Dark, and go aft. Get the awl, then just wait until you arrive in the Maze. This maze (whose room descriptions may amuse players of Zork I) is actually inside your own brain. There's no pattern here; just wander around in any directions you like until you see a "large black particle". This particle is your common sense. Take it and you will once more be returned to the Dark. Wait four turns, hear the dark, and go aft, aft, and up to the Bridge.
    [....] take the tea. Then, take the "no tea" that you dropped when you got the tea - which will now not force you to drop the tea, since you've removed your common sense. Have a look at your inventory: tea, and no tea. Well, well, well!
    [...] Go down and aft to Corridor, Aft End. Try to go port and you will be told the "screening door" is closed, so open it. Since you are intelligent enough to have both tea and no tea, it will open for you.

    There is also a possibility of encountering minor bugs elsewhere related to the way that TEA / NO TEA work as objects. From Nathan Simpson's More bugs in Infocom games list:

    In all versions, if you DROP TEA in Maze, then it stays there instead of disappearing.

    1. Fitzsimmons is clearer on this point than the HHGTG Walkthrough by Jason Coxon on IGN. ↩︎

  • @jeremydouglass What a find!

    So it looks like this Tea/No Tea was of interest to Adams.

    I wonder if then, it is worth meditating on the ways this seeming absurdity speaks to the very heart of the game (and in keeping with the theme is equally irrelevant with the game) as Adams and Meretzky en route to Bureaucracy are attempting to encode the impossible, taking on the inventory system as a proxy of the very binary nature of computing itself, asking the machine to be at 1 and 0 at the same time, with the perfect British icon (perhaps a bit of Postcolonial play here as well) tea!

    In my caffeinated morning state, this notion strikes me as epicly deep (and perhaps consequently sophistrically shallow)! Perfection!

  • @jang said:
    Just out of curiosity, I've tabulated routine definitions across a bunch of infocom games for which source is available. You can see the result here. It's a pretty low-fidelity start [assembled using awk, so it's not even aware of the syntax of ZIL] to that kind of analysis, but it does indicate some things that shared common ancestry.

    Thanks so much for sharing this! I finally had a moment to come back around to it and give the data a look. I'd love to see the script and sources at some point if you would care to share. I haven't looked closely at ZIL decompilers in a few years, but there are many options -- in particular, I can imagine approaches that would harmonize well with data mining other languages like Inform and TADS for cross-comparison. At any rate, rather than tackle the parsing question, I took a quick pass with the data keywords as-is. I noticed:

    1. One of the works has two versions included (planetfall, planetfall-gold) -- I dropped the gold version for comparative analysis
    2. Two versions (zork1-gold and hitchhikersguide-gold) are "gold" versions only. These are later revised releases, so they aren't ideal for attempting to chronologically track influences, but I marked them as if they were the originals -- 1980 and 1984, respectively.
    3. Many of the data entries have duplicate links to a individual works -- e.g. LIGHT-INT zork1-gold zork2 zork2 zork3 zork3 zork3 zork3 -- this broke my assumptions about representing presence / absence and counting the number of works in which keywords occurred, so I deduplicated this.
    4. There are 8313 keywords in the data set, 6805 of which are unique (only appearing in one work) and 1508 of which appear in multiple works. I filtered out the unique terms and focused on shared keywords.
    5. There are 23 works -- 22 excluding "restuarant", which is a partial draft. Of those 22, a few keywords appear in every work:

    Once I had a handle on the data I wrote a python script to transform it into CSV data for tabular visualization in the format function, title, year. I chose a simple d3 heatmap (among several options) and rendered several Infocom CSV data files, filtered in different ways, including:

    • All shared keywords (2-23)
    • Keywords shared exactly 2 times (unique pairs)
    • Keywords shared 4-23 times (anything multiply recurring outside a series)
    • Keywords shared 10-23 (common across many titles)

    I have a temporary draft of the full-size interactive visualizations up here:

    Infocom shared keyword visualizations

  • Whoa, @jeremydouglass, you never cease to amaze me. Can you talk a little more about what we're looking at here and what might do with these results in an interpretation?

  • In each of four images we see the Infocom works arranged along the x-axis roughly by publication date, 1980-1989. Along the y-axis we see code keywords, filtered differently in each image, but grouped vertically by first appearance. The keywords that appear first in Zork I are in a vertical band on the lower left, the ones that first appear in Restaurant at the End of the Universe are in a band on the upper right.

    In the left-hand image we see everything. Zork acts as infrastructure, with most of its keywords appearing in most of the subsequent works. Most other words have shadow bands that echo some of their new keywords in later works, and these may be occurring across series and authors. If you look up Deadline and check to its right, you see that a group of its keywords, like DO-FINGERPRINT, reoccur in Witness. If you look up the Witness column to see keywords that appear in it first, then look to the right of those keywords, you find a group of keywords like V-HANDCUFF that all reoccur in Suspect

    The first image shows everything; the second image focuses only on unique pairs that are repeated in just one other work.

    Reading the second image, most notably:

    1. Zork I, II, and IIII are not "uniquely joined" -- perhaps unsurprisingly given their origin, the fact that their keywords are used by a great many other works, and the fact that they were not written serially in the same way as other Infocom series.
    2. Some works like Witness or Leather Goddesses of Phobos were big influencers on the code in multiple later works. Some, like Infidel, don't have much impact on later work reflected in their keywords.
    3. Outside Zork, code travels through series in expected ways, where earlier works become the basis for later ones. Many of these are not a surprise. Deadline influences Witness influences Suspect. However, some are not intuitively obvious from series titles or genre. For example, Spellbreaker shares a lot of unique code with Lurking Horror, while Wishbringer is the same with Trinity.

    Reading the fourth, the focus is on commonly recurring keywords so you can see which works did not implement something (or altered / renamed it, or intentionally removed it). For one example, every single work in the data set includes TAKE_CHECK except one: Trinity. For a more specific keyword history, the Zork series introduces an V-INFLATE for a raft, and it is then selectively included in the Enchanter series, Infidel, and Leather Goddesses / Nord and Bert / Plundered Hearts, but no others.

Sign In or Register to comment.