Critical Code Studies Conference - Week Three Discussion

Critical Code Studies Conference - Week Three Discussion

2011-05-25

In Week 3 of a six-part series, Critical Code Studies contributors spelunk the mysteries of Colossal Cave Adventure, a seminal text adventure game. Delving into close readings of the original FORTRAN code, the group plots the twisty passages linking media theory, deconstruction and philosophies of programming.

Group Code Annotation: Colossal Cave Adventure

According to Donald Knuth, designer of the “literate programming paradigm,” Colossal Cave Adventure is the “ur-game for computers” (Knuth 1998/2002).

Because computer games have, for decades, been a point of connection between the worlds of technology (from the Greek techne, “skill”) and art (from the Latin ars artis, also meaning “skill), it seems fitting to revisit Adventure” in the context of Critical Code Studies (CCS).

I’m thrilled at the opportunity to invite the CCS community to collaborate on an annotated edition of Will Crowther’s original source code, using a series of public-editable files. The appendix at the bottom of this page shows the oldest known version of Crowther’s source code (dated March 11, 1977).

Also part of our project for this week - and also included in the appendix - is the accompanying data file, which contains text descriptions of rooms, vocabulary recognized by the game’s parser, and a data model of the connections between various game locations.

About Colossal Cave Adventure

The game, originally created by BBN programmer Will Crowther, was expanded by Stanford graduate student Don Woods in 1977; the expanded version made a splash on the emerging Internet, quickly inspiring a group of MIT programmers to produce their own text game, eventually known as Zork, the cornerstone of the legendary 1980s gaming company Infocom. (For details, see “Somewhere Nearby is Colossal Cave: Examining Will Crowther’s Original Adventure in Code and in Kentucky.”) A partial video walkthrough of the game is available here.

About the Crowther/Woods Source Code

In a 106-page demonstration of the literate programming model, Don Knuth (with the help of Don Woods) deconstructs the FORTRAN source code of the Crowther/Woods version of “Adventure,” “recast[ing] it in the CWEB idiom” (Knuth 1998/2002). Knuth writes,

I believe people who have played this game will be able to extend their fun by reading its once-secret program. Of course I urge everybody to play the game first, at least ten times, before reading on. But you cannot fully appreciate the astonishing brilliance of its design until you have seen all of the surprises that have been built in.

About the Crowther Original

The original source code for Will Crowther’s “Colossal Cave Adventure” was discovered in 2005, on a backup of Don Woods’s student account at Stanford University. Les Earnest, Bruce Baumgart, Martin Frost, and Don Woods collaborated to dig up the files I had been seeking for years. Countless others gave advice, and encouragement, along the way.

Comment by Mark Marino on February 16, 2010 at 7:53am

To my knowledge this marks the first time the source code from a program has been collectively annotated with eye toward interpretation. Do people know of other examples?

Also, to simplify this process, Jeremy came up with this current configuration, but since annotating code (either collectively to discover interesting aspects to discuss or individually to present readings) is likely to be a key component of CCS, I wonder what other ways would people consider implementing this process?

Dennis had originally mentioned a wiki. I’m also thinking about social annotation tools like Diigo or blogging comment tools like Commentpress. What way would you see as most effective? What are the advantages and disadvantages of various options? If you had your dream annotation system, what might it include?

Comment by Jeremy Douglass on February 15, 2010 at 8:49pm

Dennis says this in his Digital Humanities Quarterly article and elsewhere, but just in case: the code above is FORTRAN, developed on the PDP-10. Also in case it wasn’t clear from the above, the linked Knuth “CWEB” example is a reimplementation in C, called CWEB because both C code and documentation is being generated out of Knuth’s literate programming framework.

Comment by Jeremy Douglass on February 16, 2010 at 8:52am

Re: collaborative code annotation software (for our group, or in general) - it might be useful to look at how others have collaboratively annotated code.

Code review and collaborative code annotation software are actually a category of program in software engineering. For example, the commercial Code Collaborator promises “you can carry on a full conversation within your code.” In the much geekier and more CVS-inflected world of full code review tools, Rietveld is an interface that works with Google Code and was developed based on their in-house-only code review tool, Mondrian. Because they are more focused on locating and squashing bugs, these interfaces tend to be about partitioning the conversation rather than aggregating it.

Some people do code commentary in a lightweight way through snippets rather than inline, as in sites like Refactor :my ==> ‘code’, which work more like our code critiques only with simple excerpting and syntax highlighting.

Finally, there are some academic papers on in-development or hypothetical code collaboration systems such as BRIDGE (annotation for software education) and courseware with CS use cases, like iHelp.

Comment by Stephen Ramsay on February 16, 2010 at 11:36am

I spent years of my childhood playing Adventure using the version that came on a 5.25-inch floppy with the original IBM PC. To be honest, it’s hard for me to talk about the game without growing extremely nostalgic. I was positively obsessed with it.

It’s a difficult game. There are a number of puzzles that I would charitably describe as having arbitrary solutions. Some took me months to solve, and in fact, I didn’t completely solve the game until about twenty-five years after I began it (while teaching a course in interactive fiction at the University of Georgia).

Through most of the time I played it, there was no such thing as the Web, which meant there was no real way to cheat. I knew a couple of people in high school who had played it, and one of them had managed to lay his hands on a “map” of the infamous maze. But basically, I was completely on my own. Colossal Cave became a kind of psychomachia. Navigating it (E,E,N,NW,N) became almost like muscle memory. I really think I could replay the entire game in my mind even today. I just loved it.

In week 2, Jeremy Douglass asked us to consider who reads code and why, which got me thinking about what source code means before you’ve undertaken the often slow and tedious process of understanding how it works (something I’ve done many times as a practical matter).

Now comes the source code for Adventure. I can see it’s in FORTRAN (a language I’ve never had to use). I can make out what’s going on. I can see the lineaments of the game’s structure. And all I can think is: I am absolutely not supposed to be looking at this.

It’s such a visceral response. I can’t believe it. I feel like I need to call my friends from junior high. “Dude, it’s the fucking source code.”

Comment by Mark Sample on February 16, 2010 at 12:16pm

Stephen - great response! I do think nostalgia can play a very important (and productive) role in critical code studies. (And I’ll take issue with anyone who says that nostalgia can’t be a critical reaction.)

I remember Adventure from visits to the University of Akron’s mainframe computer lab, where my mother would sometimes work on her M.A. while she’d let me be entertained by one of the several games available on the terminals (Hang Man was there too, but why play that when you can go caving?)

I imagine there are many of us who grow sentimental and nostalgic when the subject of interactive fiction comes up. Though we probably didn’t call it IF in the late seventies and eighties, right? We likely used “text adventure game” or even the eponymously-derived “adventure game.” For me, IF actually inspired my first experiences with hacking (hacking in the pre-phreak sense of the word), as I would “peek” sequential memory addresses, trying to find hints to the puzzles in Madness and the Minotaur and Bedlam on my old 16K TRS-80 Color Computer.

Comment by Mark Marino on February 16, 2010 at 12:56pm

Stephen and Mark,

Can you elaborate a bit more on the way in which looking at this source code is like looking behind the sanctuary curtain (or Wizard of Oz curtain, for that matter)?

Interesting how we might feel that intensely here, but not so when poking around through the simulation of Micropolis.

Anyone else have thoughts about the particular relationship between source code and player in IF?

And re: nostalgia, I agree that it might prove a driving force, even more so than in the case of literary scholarship, since you are reminiscing about a time that seems to exist before the pixel curtain of all these GUIs.

Also, I wonder what such nostalgia might obscure?

Comment by Jeremy Douglass on February 17, 2010 at 1:23pm

To give some perspective on the data file, I’m uploading these screenshots of the appendices from Mary Ann Buckles’ 1985 dissertation on Adventure“Interactive Fiction: The Computer Storygame ‘Adventure’.” Ph.D. Thesis. U. Cal at San Diego, 1985. Keep in mind that this is code for a different system (note the use of lower case), several generations changed (such that Buckles describes it as “folk art”), but that the structure of the data files themselves and their relationships are largely preserved, even where their contents are changed.

We could go into this in greater depth, but my point was not to distract us away from the original source and towards the literally hundreds of extant adaptations post-Crowther & Woods. Instead, I’m pointing out another way that the data file is itself code and not just “content”. While tabular text is not a database design, it is still a structure of relationships that carry forward as much as (and occasionally more than) the logical methods expressed in FORTRAN statements.

Formal Languages and Their Relation to Automata, published by John E. Hopcroft and Jeffrey D. Ullman in 1969 (one of the foundational texts of the theory of programming languages).

Reading this text is a never-ending project and for me it really shows how hard it is (and perhaps not particularly useful) to tell reading code apart from reading 'other' texts (e.g. texts in natural languages).

Anyway, for me Hopcroft and Ullman (1969) show that code is constituted as a process of linearization (since the whole theory of programming languages, of which the BNF is a part, is based on the sequentialization of 'discrete symbols' (a term Hopcroft and Ullman use, in the very material sense - I would say - of material inscribed with recognizable traces of some sort).

To cut it short, I will just look at the first stage of compiling of this line of Fortran code.

Classical definition of a compiler: an automaton that 'reads' any program previously written in the high-level programming language for which the compiler has been designed (the 'source language') and re-inscribes it as binary code (the 'target language'), or, eventually, as circuits (and I do not consider myself a Kittlerian, strictly speaking: I do believe that there IS software).

Now, for me the terms 'read' and 'translates' used in the above passage are metaphors for the material re-inscription of the source program - a process of re-inscription that is technically called 'compilation.' But how does this re-inscription work? What does it do?

Again, I think that compilation linearizes code. This process of linearization (which the French paleontologist André Leroi-Gourhan associated with the development of graphism in the Mediterranean and European group of civilizations, and Jacques Derrida and Bernard Stiegler have called grammatization - I'm oversimplifying here) is the basis on which code works. However, I am quite convinced that linearization in code is an always incomplete process which undoes itself continually - yet, it must be kept up in order for code to exist.

Ok, so I would look at how the line of code is parsed. I quote Aho et al. 2007 (another of my favorites): the first stage of compilation is "lexical analysis or scanning. The lexical analyzer reads the stream of characters making up the source program and groups the characters into meaningful sequences called lexemes. For each lexeme, the lexical analyzer produces as output a token ... that it passes on to the subsequent phase, syntax analysis" (5).

Now, the above passage uses all the rhetorical devices that are common in technical descriptions of programs: it switches from terms denoting temporal 'phases' of execution of the program ('lexical analysis') to terms denoting agency of (parts of) the program itself ('lexical analyzer'). Yet, what this passage makes clear is that the process of compilation consists first of all of detecting 'interruptions' in the string of the program (such as blanks and semicolons) and of re-grouping the symbols of the string into smaller sub-strings called 'lexemes.' The 'blank' here is not Derrida's 'blank': it is a specific binary code for a blank space in the page. This means that a blank is physically inscribed into the memory of the computer and it occupies the physical space of (usually) two bytes.

It must be noted that the compiler is an automaton that follows the rules of production of a specific grammar (in a Chomskyian-BNF sense) - and it is this grammar that establishes what works as an interruption in the source program (for instance, a blank space or a ';' work as interruptions, but not an 'a'). The symbol of interruption therefore ruptures the chain of symbols and functions as a discriminating tool for re-grouping the other alphabetical symbols into new groups ('lexemes').

For each lexeme, the phase of lexical analysis produces a 'token' - in other words, each lexeme is re-inscribed as a slightly different string with a few explanatory symbols added. At this point, the initial single string of the source program (for the theory of programming languages, the whole code that Dennis has analyzed is a single string of symbols) has been completely re-inscribed.

For me, it is important to notice that the lexical analyzer also works on the basis of linearization and discreteness: its function is to 'read' the ruptures in the source program, to make them work as ruptures, to make them function in the context of the computer so that the originary string is transformed into a different string (the sequence of tokens).

The lexical analyzer works with the rupture in order to re-inscribe the string. The ruptures (the blanks, the semicolons) disappear from the initial string as symbols - that is, as characters with their own binary encoding in the computer memory - and they are re-inscribed literally as the 'tokenization' of the program. They are actually what enables such tokenization.

The above line code (string) would be broken down by the compiler into the following tokens:
DO
10
I
=
1
10

Starting from the sequence of tokens produced in the phase of lexical analysis, another re-inscription is carried out.

If we go down this path we find that "the second phase of the compiler is syntax analysis or parsing. The parser uses the first components of the tokens produced by the lexical analyzer to create a tree-like intermediate representation that depicts the grammatical structure of the token stream" (still quoting Aho et al. 2007).

It is not important to understand all the technicalities of this passage. What is important is that the tokens are 'rearranged' once more according to the syntactical rules of the grammar on which the language is based, with the help of the additional symbols inscribed into the tokens in the previous phase.

The way this happens varies physically: obviously no graphical representation of a tree is actually 'depicted' in the memory of the computer. The parse tree is also a rebuilt string: in other words, the sequence of tokens is regrouped in order to be then analyzed by the 'semantic analyzer,' which in turn checks the consistency between the tokens and produces the so-called 'intermediate code.'

Aho et al. (2007) explain: "In the process of translating a source program into target code, a compiler may construct one or more intermediate representations, which can have a variety of forms" (Aho et al. 2007: 9). They define the intermediate code as 'assembly-like' - however, it is a further re-inscription of the source code and a further transformation of the ruptures inscribed in the source program - ruptures that actually make it possible for code to function.

While performing all these re-inscriptions of the source program, a compiler also checks the program for correctness - that is, it assesses the program's compliance with the rules of transformation defined for the specific programming language in which it was written.

Now, how is this important for CCS?

For me, it is important because a compiler can only detect errors according to such rules (for instance, it can easily locate a missing ';') but it cannot anticipate whether the source program will function in an unpredictable way when executed. For instance, it cannot anticipate whether a perfectly correct portion of the source program will cause the computer to enter an infinite loop with unforeseeable consequences.

This is why I think that code is at its most interesting when it does not work rather than when it works - even more interesting, in fact, when it looks like it is working but it actually does unexpected things - and we have to make a decision about these unexpected things being either an acceptable (although unintended) behavior or a malfunction/failure.

In fact, the above line of code presents an interesting similarity with the following one:

DO 10 I = 1.10

This is the legendary FORTRAN line of code said to have caused the crash of the Mariner I space probe in 1962. There it becomes obvious how a perfectly linearized code can still give rise to unforeseen consequences - thus showing how unpredictability is inscribed in code at what I would call a constitutive level.

Now, if you ask how this analysis is specific to Dennis' game code, the answer is: it isn't. It is more specific to Hopcroft and Ullman's theory of programming languages as it was developed in the late 1960s (think of the GOTO discussion, Dijkstra etc. - which deserves an analysis in its own right).

To be more specific I would need to read thoroughly the whole code posted by Dennis - I might or might not come up with interesting observations. Cannot say without trying (we never know before doing the actual reading, right? Otherwise what would the point of reading be?)

But what I want to point out (referring back to the discussion of the past two weeks) is that:

1) the above (tentative) reading is not functional - it is not an explanation of how code works as programmers would do it. It is a deconstructive reading of how code as a material inscription (for lack of a better term here but I'm open to suggestions) works and what it tells us about how code has been constituted, why it 'resembles' language/writing (without ever being 'the same as' any other historically specific form of language/writing. It also tells us something about the reason why we (CCS people) find it so difficult to establish if code 'is' language/writing/software/code. My opinion is that this is the wrong question: rather than trying to establish the ontological status of code, we should start by analyzing texts (e.g. Hopcroft and Ullman's book, with its excerpts of code, or the above game source code) where code AND language AND writing are constituted together in their specificities.

2) the above is not a history of FORTRAN/the theory of programming languages/BNF/games as professionals would write it (people like Sebesta, for instance - and perhaps even historians like Michael S. Mahoney or others - see e.g. the Annals of the History of Computing). In fact, my experience tells me that professionals are quite good at writing (and very aware of) the history of code, software etc. I have always heard fellow programmers talk about 'the philosophy' of a certain programming language, or discuss the features of a certain language from a 'historical point of view.' They (we) are not unaware of economical/political implications, vested interests in technology, etc. We can and should look at all this as CCS people, but perhaps we should add a bit more (as we are actually trying to do in this group).

3) The above is an attempt to read/discuss code 'itself' (for lack of a better phrasing rather than the cultural formations surrounding it.

Comment by Stephen Ramsay on February 18, 2010 at 1:57pm

Federica's (fascinating) post serves to clarify something I've been thinking about (worried about?) since the beginning of this discussion in Week 1. I'm going to call it the "Code on a Grecian Urn" problem. Let me begin by calling attention to Nick Montfort's wonderfully pithy note at the end of Week 1:"Hm, I don't know. The concept appeals to me, but the technique itself just isn't doing it for me yet." I think that captures a lot of peoples' reaction. The concept appeals. But how do we do it? What does it mean to do it? And what is the concept again?

From the start, I have accepted the premise of CCS because I feel as if I can say the following: humanistic study is the study of the artifacts of the human experience. Code is one of those artifacts. So if we can study books, and sculptures, and designs, and railway timetables as objects that do cultural work, then surely we can also undertake critical study of code. I'm not trying to limit the definition of critical study or the humanities. I'm just trying to convey a simple idea about why the critical study of code makes sense to me. It makes sense, I think, because it shares something with the other things we typically study. Human beings create novels. They also create code. It might be legitimate to say that these critical practices should be methodologically distinct in some way (pace game studies versus literary studies), but we've come together because we think the critical practices we engage in with other human artifacts might also be useful in the study of code.

So the concept appeals. But when we try to do it, I think we fall into one of two modes of speaking - neither of which seems quite right to anyone who wants to talk about CCS as something distinct. The first mode really wants to talk about the *software* and its role in the culture (and really, I'm using phrases like "role in the culture" to signify an extremely ramified set of diverse methodological practices). So we can talk about Adventure as part of game history, as part of the culture of the 70s, as a form of virtual reality, as an interactive narrative, as part of my childhood, and so forth. This is all fine. Many of us come from disciplinary backgrounds that engage in one or more of these kinds of "readings." Most of us were trained to do them, are comfortable doing them, and we are generally convinced of the utility of this kind of practice.

But then, none of this (we are told) is critical code studies. CCS really tries to *read the code*. Here's Mark again from Week 1:

[T]the focus of this working group is the interpretation of computer source code. It is not to speak in the abstract about the nature of code, though we will do that. It is not to speak about the viability of the practice, which shall be demonstrated by our readings. It is instead an opportunity, in the context of a talented and committed set of peers, to generate close readings of source code.

Now, what's most interesting to me - and the thing that really has been a revelation over the last few weeks - is just how hard it is to do that. The most fascinating part of Federica's post is this:

"the above (tentative) reading is not functional - it is not an explanation of how code works as programmers would do it. It is a deconstructive reading of how code as a material inscription (for lack of a better term here but I'm open to suggestions) works and what it tells us about how code has been constituted, why it 'resembles' language/writing (without ever been 'the same as' any other historically specific form of language/writing."

It's true that this is "not an explanation of how code works as programmers would do it," but it is absolutely not "a deconstructive reading of how code as a material inscription works and what it tells us about how code has been constituted." Or rather, it *is* that, and the term for this kind of thing is not critical code studies, but simply formal language theory. This has been a very common move throughout our discussions. Jeremy Douglass writes a post about "who reads code." It's frankly brilliant, but let's face it: it's not critical code studies. It's the cultural study of code. So we hear the call again. Back to the code! And then we get either the history of computers or one of the standard theoretical subjects in computer science.

What is going on? Why is this so hard?

Let’s take the example of Grecian urns. Grecian urns are very easy to talk about from the standpoint of cultural study. They play an important role in the history of art. They are themselves aesthetic objects of exquisite beauty. They were also objects that played a concrete role in the material culture of ancient Greek society. You can see here the outlines of critical study in all of these statements. There are methodological questions to be hashed out, but at some fundamental level, we know exactly how to undertake the critical study of urns. We know how to embed them in certain kinds of conversation about culture.

But now, let’s turn our attention to the study of urn-craft (the making of urns). There’s a lot to talk about here as well. For one thing, the making of urns is a subject of great technical complexity. In fact, it’s hard to talk generally about urn making without getting into the specifics of tools and techniques. Moreover, the technologies of urn-craft underwent a number of modulations throughout its history: tools and methods changed, techniques went in an out of fashion. We know how to have these kinds of conversations too, but they’re really quite different.

I am now more-or-less convinced that these are two distinct kinds of conversations. You can transform the latter into the former if you want, but you will at that point stop doing the latter in some fundamental way. Even if the result of your efforts is entitled “A Cultural History of Pattern Incision in Cycladic Pottery,” it’s probably not that, but instead a cultural history which also includes some interwoven discussion of the techne of ancient pottery.

I was trained as a student of human culture. I feel like I know how to have that conversation. I’m also a pretty good hacker (good enough to recognize that Federica is not adding anything to what the writers of compilers already know). And that leaves me with two choices. I either talk about compilation as a cultural practice (which actually sounds like a lot of fun) or I go build a compiler (which is also a lot of fun).

Strangely, the past few weeks have made me feel a lot better about being a humanist who likes to build things. If you want to understand software (or code) as an artifact of human culture, then by all means assume the critical distance and the set of philosophical positions requisite for that discussion. But if we really want to undertake “close readings of code,” then I suggest we move this conversation to GitHub.

Comment by Dennis G. Jerz on February 18, 2010 at 2:27pm

Stephen Ramsay wrote: I am absolutely not supposed to be looking at this.

Yes, in some ways, this is like realizing how the coins really get under your pillow when you lose a tooth. Our reaction to the deconstruction of an icon we’ve revered since childhood is no doubt similar to the reaction of the entry-level student who just wants to “appreciate” art, without having to do all the intellectual work that goes into analyzing it.

Jeremy, regarding the tables from Buckles: While I haven’t done an exhaustive study of the differences between Crowther’s original code and Woods’s expansion, what I gained from examining the data was the observation that Woods was very good at spotting what worked and adding onto it; he made very few changes (other than fixing some dead ends and other bugs). Other than the addition of line numbers and the standardizing of spacing with tabs, I don’t see any major structural differences in the tables that Buckles present and the tables that are in this sample. What the code does with the tables will, of course, be another story. Woods more than doubled the number of lines in the data file, but he more than quadrupled the length of the code file. The number of possible connections (and bugs) would probably have increased exponentially, so Woods would have been motivated not to mess with any structure that was already working well.

Mark Marino wrote: And re: nostalgia, I agree that it might prove a driving force, even more so than in the case of literary scholarship, since you are reminiscing about a time that seems to exist before the pixel curtain of all these GUIs.

Yes, our exposure to code is very spatial now, in a way that I doubt original coders would have experienced their code, except when printed out on paper.

I’m assuming Crowther edited his source code using a line-editor - a command-line program that displayed one line of text at a time, optimized for use by people sitting at printer terminals (which displayed one line of text a time, on a roll of continuous paper). It would be possible to print out your source code, mark it up, and then enter the changes one line at a time. That’s the way most business people composed letters, with the help of a secretary/typist in that era, and there were of course punchcard operators who did much of the mechanical work for the early programmers.

Martin Heller’s essay that recounts a rock-climbing trip with Crowther (http://www.mheller.com/Adventure.html) notes that Crowther is playing mental chess, without needing a board. That behavior indicates his skill at keeping a complex structure in his head. In the days before object-oriented programming, I’m not sure how one could handle certain complex behavior without GOTOs. Or, to be more accurate, I *am* fairly sure that the workarounds were just not worth the effort. One of the problems with GOTO statements is that they don’t follow any logical structure - at least, not if you’re tasked with finishing the spaghetti code that someone else started (and didn’t bother to comment).

With the right command-line statement, you can call up, in your line editor, the line of code marked as the target of the GOTO statement, wherever that line of code might be in your source.

The GOTO statements whisk us from one area of the code to another, not unlike XYZZY and PLUGH. The impact is disorienting to the newcomer, but once you learn the geography, the GOTO label is very useful, because it marks a place where you are likely to keep returning to as you edit the code (much as XYZZY marks the place where Woods rewards us for depositing our treasures).

I write this based on recollections I had using learning to use a line-editor when I was in about seventh grade (1982?), and the last time I used one for any significant purpose was around 1993.

Comment by Dennis G. Jerz on February 18, 2010 at 3:15pm

A good FORTRAN 77 tutorial: http://folk.uio.no/steikr/doc/f77/tutorial/

The standards for FORTRAN 77 weren’t finalized until after Crowther stopped developing his code, so he would have been using FORTRAN IV. I don’t believe anybody has written a modern FORTRAN IV compiler.

Matthew Russoto made minimal changes to Crowther’s FORTRAN IV code so that it would run in a g77 compiler. He’s posted the resulting files here.

http://www.russotto.net/~russotto/ADVENT/

A windows-executable version made from those modified files is available here:

http://www.ifarchive.org/if-archive/games/pc/adv_crowther_win.zip

Much of what I learned about the source code I learned from playing the game, and working from the observed result back to what the code most likely does. (The moment when the structure of the data map crystallized, and I could suddenly see the pattern, was just as thrilling as seeing the “real” rod and the “real” Y2 rock when I visited Colossal Cave in Kentucky.)

Comment by Dennis G. Jerz on February 18, 2010 at 3:22pm

Federica Frabetti wrote: For me, it is important because a compiler can only detect errors according to such rules (for instance, it can easily locate a missing ‘;’) but it cannot anticipate whether the source program will function in an unpredictable way when executed.

Would you say that’s because anticipation and prediction require a value judgment (so that I should approach your statement from the realm of artificial intelligence) or because following the rules and achieving a desired outcome are two different intellectual tasks (so that I should approach your statement from the realm of composition theory)? I don’t mean to suggest the options are mutually exclusive.

Federica: You introduce “DO 10 I = 1.10” as the line of code that allegedly caused the Mariner crash. Was there ever any closure on that? I believe the story goes that the period should have been a comma, but I’m not sure anyone conclusively proved that the mistake caused the crash. (I recall a study concluding that the Mars Climate Orbiter mission failed because Lockheed was relying on English measurements while NASA was using the metric system, but the code was just the means of transmitting an error, the error itself was at best only tangentially a coding issue.)

What resource would you recommend for a further exploration of the Mariner issue?

Stephen: the very name “Code on a Grecian Urn” makes me want to work up an IF mini-competition that asks entrants to annotate their own simulated urn, as a way to encourage readers to explore the poem.

You bring up the distinction between the study of urns and the study of urn-crafting. That reminds me of Plato’s dialogue with Ion, the mad poet who, once backed into a corner by Socrates, insists that, because he knows the sort of thing that a general would say, he’d actually be able to run an army as well as a real general.

Or maybe simply the distinction between the English literature major and the English creative writing major, both of whom approach a text for different purposes, but both of whom can draw from the same set of tools.

Buckles analyzed Adventure in a purely social context, using a methodology that asked non-gamers to play Adventure and share their subjective reactions. She barely mentions the source code (other than as a mechanism for quoting textual passages encountered during the game), or the experiences of the original players, or the intentions of the original authors. I don’t mention this to complain, but rather to acknowledge that an approach that focuses on one path of inquiry necessarily ignores other paths. Likewise, Steven Levy’s Hackers: Heroes of the Computer Revolution tries to capture the environment in which Adventure was played, in basements, after hours, on the sly. But to Levy, as to Buckles, the code itself was not an object of inquiry. On the other hand, Donald Knuth, in his CWEB re-implementation of Adventure, recommends that his readers play through the game several times so that they are thoroughly familiar with the user experience, but says that only through examining the source code can we really appreciate the brilliance of the Crowther/Woods collaboration. To Knuth, then, the gaming experience is just a prelude: an executable that hides its code holds out the promise of fulfillment, but cannot deliver it or change beyond its current limitations, just as the still picture on the urn freezes the relationships thus depicted.

So Stephen, is the distinction you make - choosing to study the artifact OR the process - radically different from the choice of formalism over new historicism, or reader-response over intentionality (within the realm of literary criticism), or the academic question of, say, spinning a particular critical study so that it appeals to creative writing majors as well as literature majors?

Comment by Mark Marino on February 19, 2010 at 12:08am

>You are standing before the Colossal Code of Adventure. You see INSERT FOOTNOTES, a keyboard, a Google Doc.

Don’t be afraid of marking up this “sacred” text. This should be a messy process. We are not printing the variorum right now, we’re hacking and slashing our way through the wild -> you won’t hurt the text by going in and marking it up, posing questions, taking a leap. That document (like this thread) is meant to be our discussion space but also the back of the napkin and the whiteboard for our late night riffs, rants, and readings.

Comment by Mark Marino on February 19, 2010 at 2:16am

I’ve been reviewing Dennis’ Digital Humanities Quarterly article, a fascinating work of scholarship, and I’ve been tracing out some themes that he notes, some critical moves that can be made on Adventure. I’m now wondering if there are places in the code that resonate with these motifs (and a few others).

This has lead me to begin searching the code (data and instruction file) for instances of or points of connection with:

Hardware limitations
Elegance of the code
Innovation of the code
Similarities to MUDs
Influences of previous software
Connection with Crowther’s work on BBN
(his) influences on later IF
his kids as the imaginary audience
D & D
his divorce
1970s programming culture
the physical materiality of the Kentucky caves

These range from the material specificity to the biographical to the cultural to the generic (as in genre).

Are there other motifs (and corresponding code) we can add?

Comment by Mark Marino on February 19, 2010 at 2:27am

Say, while annotating the code, I came across this strange and seemingly undefined line:

CALL IFILE (1, ‘TEXT’)

Then, I came across some patches. Hmm, where will this crack in the urn lead?

Comment by Federica Frabetti on February 19, 2010 at 6:15am

DENNIS: Would you say that’s because anticipation and prediction require a value judgment (so that I should approach your statement from the realm of artificial intelligence) or that’s because following the rules and achieving a desired outcome are two different intellectual tasks (so that I should approach your statement from the realm of composition theory)? I don’t mean to suggest the options are mutually exclusive.

As for unpredictability: I would really be interested in the results of applying both approaches (artificial intelligence/composition theory) to this problem. I am not sure what that would mean. For me, the very distinction between ‘following the rules’ and ‘achieving a desired outcome’ is somehow questionable.

Or, to say it better and to give you a broader example (coming from the methodologies of Software Engineering) such a distinction is put into question throughout the whole process of software development, including coding. There is always some decision that (supposedly) precedes coding - a decision on what a piece of code is supposed to do. But then, there is always the possibility that, once coded, that piece of code behaves in an unexpected way (due to a syntax error or to other circumstances, such as the interaction with other pieces of code). At that point another decision is necessary - i.e. whether that behavior is acceptable (so it becomes part of the ‘requirements’ of that piece of code, retroactively changing what we thought that specific technical object - say, a game - was meant to do) or not (so it is declared a malfunction and it must be fixed).

The way I see it, though, is that as programmers and software engineers we like to think of the process in this way, when in fact the originary decision (the decision of developing a piece of code or even a software system that does something) is just a fictional narrative for the origin of software - a kind of expulsion of ‘the reason for the existence of software’ in the world ‘out there’ (e.g.: it solves a problem, it fulfils a need).

Software Engineering tends to acknowledge the unavoidable iteration involved in software development (which cycles between the activities of specifications, design, coding and testing), but it does not think through the consequences of this (some of these consequences for me would be: there is no repetition without difference, and in this respect code is always citational; every cycle of iteration potentially introduces unexpected consequences in/of code; ‘perfection’ in code - what Fred Brookes used to call ‘software as a perfectly executed spell’ does not exist, etc.).

DENNIS: What resource would you recommend for a further exploration of the Mariner issue?

Yes, the dot should have been a comma (otherwise it goes into an infinite loop).

In a posting dated 28 Feb 1995 on http://www.rchrd.com/Misc-Texts/Famous_Fortran_Errors John A. Turner debunks the myth of the FORTRAN error by referring to a previous discussion posted by Dan Pop on the newsgroup http://comp.lang.fortran (Mon, 19 Sep 1994).

I think his analysis is meant to be conclusive (i.e. the ‘legend’ results from the conflation of two separate events. Mariner I was in fact destroyed on 22 July 1962, when it started behaving erratically four minutes after launch, but such an erratic behavior was due to a combination of hardware and software failures (Ceruzzi 1989), while the DO-loop piece of code was identified (and corrected) at NASA during the summer of 1963 during the testing of another computer system.

Thanks for mentioning the Lockheed accident - in fact I’d say that ‘mismatching’ different systems of measurement could be viewed as a problem in/of code.

Stephen wrote: What is going on? Why is this so hard?

Stephen, I like your question (and your criticism of my post) because it hits a nerve. The problem you mention has been bothering me too from the start. Curiously I thought I had come up with a way out of it, but you think I haven’t!

I do not believe I have sort of given a lecture on ‘the formal theory of programming languages’ in my posting above. What I was trying to do was to read a line of code TOGETHER WITH a (specific) text on the formal theory of programming languages (incidentally, I am against sweeping generalizations on ‘the’ theory of programming languages or any other theory - but let’s say for the sake of simplicity that I am reading that line of code AND the theory of programming languages) in order to show how and where their conceptual structure does not hold/comes undone.

For instance: ‘the’ theory of programming languages is based on a perfect linearization of symbols into strings. This, in turn, is meant to provide the basis for substitutions that generate all and only the grammatical sentences within a language (I am hugely over-simplifying here).

My intent is to show how such linearization is in fact unachievable - in a number of ways, including the fact that iteration entails difference as well as repetition. This is NOT what the theory of programming languages claims. Quite the opposite. The theory of programming languages has to believe that such a linearization is possible in order for programming languages to exist (i.e. to be developed and used). In fact, programming languages DO exist. But if you give a problematizing (questioning, ‘deconstructive’) reading - namely, a CCS reading - of programming languages, of grammars and of code, you find out that they exist in the tension between linearization and the impossibility of achieving it.

Incidentally, this has nothing to do with the difference between ‘theory’ and ‘practice’ (e.g. prescriptive literature on Software Engineering as opposed to the ‘actual’ practices of software engineers) - it has to do with the fact that in every conceptual system (that of a programming language, of software engineering, of code, of generative linguistics, of structural anthropology) we can detect a concept that is actually unthinkable within the conceptual structure of the system itself - therefore, it has to be excluded by the system, or, rather, it must remain unthought to allow the system to exist. A deconstructive reading of a Fortran program would ask: what is it that has to remain unthought within the structure of that Fortran program?

What I asked above is: what is it that has to remain unthought in the line

DO 1001 I=1,300

for it to exist as such (i.e. as a line of code rather than a random sequence of characters, or even of flickering dots, on my/your screen?)

My tentative answer is: the impossibility of perfectly linearizing code needs to remain unthought in

DO 1001 I=1,300

Of course to support my claim I have to explain what I mean by linearization - which amounts to looking into other texts (for instance a text on the theory of programming languages, but it could have been a Fortran manual, or one of Chomsky’s text on grammars).

Which brings us back to the point: I do not think that the distinction between process and product is tenable. Of course to read code you need to read source code, but that is only one form in which code exists. You also need to read the corresponding sequence of bits encoded in the computer’s memory, which can be re-inscribed (and must be read) as a sequence of hexadecimals and as a sequence of mnemonics and as a dynamic process of transferring bits between registers at run-time. On the other hand, code also exists only as part of a programming language which has been constituted in a certain way because of a certain way of reflecting on digitality (in the late 1960s perhaps?), which maybe is connected to a certain way of thinking about language in general, and maybe even to a certain way of thinking in the Western world.

I said I am against sweeping generalizations, and this is why I am looking at specific instances of code - but on the other hand even reading a short, innocuous line of Fortran one can go very far, as you see.

You may think that interrogating the premises of the theory of programming languages in relation to the processes of grammatization at work in Western thought is useless/non-productive/not the best way to go, etc. Fair enough, but it is certainly NOT what the theory of programming languages does. It is what I have attempted to do in my effort to produce (one possible) ‘CCS reading’ of a line of code.

However controversial and uncertain a definition of ‘deconstruction’ might be, I am essentially taking it up here as a way to step outside of a conceptual system while simultaneously continuing to use its concepts and demonstrate their limitations (Derrida, ‘Structure, Sign, and Play’). Deconstruction in this sense aims at ‘undoing, decomposing, desedimenting’ a conceptual system, not in order to destroy it but in order to understand how it has been constituted (Derrida, ‘Letter to a Japanese Friend’).

This is the whole point of deconstruction for me. If this is not a deconstructive reading, than what is?

Comment by Stephen Ramsay on February 19, 2010 at 6:35am

So Stephen, is the distinction you make - choosing to study the artifact OR the process - radically different from the choice to choose formalism over new historicism, or reader-response over intentionality (within the realm of literary criticism), or the academic question of, say, spinning a particular critical study so that it appeals to creative writing majors as well as literature majors?

I don’t think it’s at all like the difference between formalism and New Historicism (which, in this context, is not very radical at all). The difference between creative writing and critical study is closer. Closest of all, though, might be the difference between literary criticism and textual criticism (scholarly editing). In fact, that’s what I think you are doing with Adventure, and I think it’s dazzling. I just don’t think you’re doing critical analysis of it, really (“close reading” the adventure code).

But the fascinating point for me is that whenever someone tries to do close “critical” reading of the code, they do one of two things: they either treat the code like it’s a text, or they treat the code like it’s code and start doing what is basically the ordinary work of either computer science or the history of computing.

In fact, let me annotate Mark’s list above in terms of the methodology that must ensue:

Hardware limitations (CS)
Elegance of the code (CS, Software Engineering)
Innovation of the code (History of Computing)
Similarities to MUDs (Code as Text, unless you mean comparing the two object models, which will take you to CS)
Influences of previous software (History of Computing)
Connection with Crowther’s work on BBN (History of Computing)
(his) influence on later IF (History of Computing)
D & D (Code as Text, History of Computing)
his divorce (Code as Text)
1970s programming culture (History of Computing)
the physical materiality of the Kentucky caves (Jerzian Analysis)

I hope I don’t seem like I’m just being perversely critical here. I’m not trying to assert a negative theology of code studies (well, maybe I am). I just think this difference - this point where you can’t really *do* critical study without lapsing into some other discourse - is a really fascinating one. I almost want to see it as a hard limitation of criticism - as the point where, actually, *not* everything is a text.

That’s probably disquieting to some. It’s liberating to me, because it suggests that the only way to study it, really, is to do it. Or rather, that doing it is the critical move with the code, all other things being various critical moves with the software.

Comment by Stephen Ramsay on February 19, 2010 at 7:18am

You may think that interrogating the premises of the theory of programming languages in relation to the processes of grammatization at work in Western thought is useless/non-productive/not the best way to go etc. Fair enough, but it is certainly NOT what the theory of programming languages does. It is what I have attempted to do in my effort to produce (one possible) ‘CCS reading’ of a line of code.

No, no. I think it’s marvelous, Federica. I’m not critiquing what you’re saying at all. What I’m trying to decide is whether you are “doing critical code studies” (a new thing) or making a move within the existing language game of formal language theory.

More later. I just wanted to make sure you understand that my critique isn’t about whether what you are saying is interesting or not. It’s completely fascinating. I just want to understand in what context it is already fascinating.

Comment by Dennis G. Jerz on February 19, 2010 at 12:31pm

Stephen, what you call Jerzian analysis I’d call a mashup of ecocriticism, travel reporting, and a splinter of New Games Journalism. I did consider splitting off the cave part of the article and getting it published somewhere else, but the code/cave pairing was just too inviting to resist.

Comment by Jeff Nyhoff on February 19, 2010 at 12:35pm

Like Mark, my first exposure to Adventure was through tagging-along with a parent to a college campus in the late 1970s - in my case, as the teenage son of a computer science professor. There was still some interest in the game when I was an undergraduate. I never reached the point of being an Adventure devotee. However, one of the remembrances that examining this code has called to mind is the extraordinary amount of mental, spatial mapping it required, to the point that players in the computer lab began drawing diagrams on the chalkboards, collaboratively - and over the course of many months - constructing maps of the game’s space and logic flow. Today, it sets me thinking of the tensions between textuality and the ancient “art of memory” that Frances Yates and others wrote so much about.

For myself, this interaction between software map, cartographic map, and mental map also calls attention, of course, to the subtle dialog between software models, interface illusions, and mental models that operates in all of our GUI software interactions.

In examining this code from a bygone era and programming paradigm and looking to follow its logic and remember the flow of experience it produced, I found myself - out of reflex - returning to a what was a fundamental programming practice that has since been widely abandoned (and often scorned outright): drawing flowcharts. This practice was increasingly displaced by “pseudocode.” I’ve always mourned this shift because, for many of us in that generation of student programmers - and perhaps especially those of us with interests in more visual, spatial, and kinesthetic cultural forms - it was this on-paper, multi-linear thinking, charting, and drawing that felt most like the “real programming.”

In fact, at various points since, certain forms of “visual programming” have emerged that have come very close to literalizing this notion of “flowcharting as programming” - e.g., Max/MSP leaps to mind. Does such iconic, visual, diagrammatic programming fall within the notions of “code” operant here? Or are we risking privileging alphanumericity as a defining characteristic of “code”?

Also, I like Stephen’s admission of experiencing an “I am absolutely not supposed to be looking at this” reflex. For me, this, too, invokes the question of whether there is an implicit “hiddenness” in our notions of code. Again, I think that the more-than-a-quarter-century of the commercial GUI paradigm has been driven largely by a circular definition where the “end user” identity is defined as “someone who does not see code,” and “code” has operationally become “what(ever) the end user must not see.”

Finally, in reading through the messages, I was surprised by the number that included “I.” I didn’t remember this projection of a first-person persona as being part of the experience. For whatever reasons, I remember experiencing these utterances as shaping more of an interior dialog with myself as the player, rather than being accompanied by a “guide” character.

Comment by Mark Marino on February 19, 2010 at 12:47pm

Stephen,

I’m looking at your annotations of my strategies or topics for annotations and think you have located well the disciplinary or methodological locations of each. I think these are useful categories.

However, while I think something like hardware limitations are clearly part of the field of “CS” (as is source code), the annotations drawing upon these fields of knowledge will become the stuff of the Media Specific Analysis, just as people can use knowledge about the paint, the painting strokes, the kiln, the clay, the urn-making tradition…. to build into a critical interpretation.

It’s that final link that for me differentiates the work of critical analysis of these codes from the associated fields and, in my mind, tools for building these readings. I realize that for some, the history, the materiality, is meaning enough - though scratch any of those readings and you’re liable to find something much more interesting.

Take this book. When I read Ulysses, I had this book, well, also in my lap, or awkwardly sprawled next to the main text. Annotations ranged across addresses of the historical tobacco shop, references to myths, correlations to Joyce’s schemata, translations, literary allusions…

Now, by the end, we might talk about all of these as originating in particular fields (history, narrative studies, folklore, et cetera). My understanding was that with these tools, I could build a reading of the work that fully engaged the rich milieu from which the work arose and in which it circulated.

Again, above, we are not trying to create the ultimate annotated Adventure, though we may do a bit of that work. Instead, I believe Dennis is inviting us to engage fully with this code, to poke at it, prod it, and begin to gesture toward the many levels of meaning within and brought upon this code.

We might decide to bring a deconstructive, new historical, generic… approach. We might decide to apply our knowledge of hardware, software, programming practices, code languages. We might decide to read this against other software, other versions, other processes. We might apply the paratexts of biography, the discourses of Geek culture, the instruction of programming, the history of computers.

To me, though, to address your earlier point, as I’ve seen with the study of literature, film, computer games, and consumer electronics, the more we know about these objects and the ways in which they can “mean,” the more we can discover and produce as we grapple to better understand (and here I join the two supposedly separate spheres) technoculture and culturetech.

Comment by Dennis G. Jerz on February 19, 2010 at 1:25pm

Adventure was a first. It’s taken several decades for the stars to align in such a way that we can study it, conscious of our own encounters with the game, knowing what we know now about its significance, but as a community knowing far less about its code, and only beginning to identify the kinds of questions we should ask about the code, so that we have a clearer idea what we should be asking of our own critical studies.

Comment by Susan Garfinkel on February 19, 2010 at 1:50pm

Hi all, I’m afraid I’ve been lurking so far (and learning a lot!) due to unexpected time constraints, but as he did for Federica, Mark also prompted me to come in on this one because I claimed to have once known some FORTRAN. And now I’m intrigued to see the code, but realize that the FORTRAN I once knew was somewhat different-more advanced-than what we’re seeing here. GOTO statements, for example-or CONTINUE-were considered bad form by the time I took my first class as a college freshman (with punched cards!) in Fall 1980. But I am fascinated by the GOTO statements we see here, perhaps simply because there are so many of them that they seem to form the backbone of the coding. I see others have noted them as well.

In fact, I started to form some thoughts about the GOTO statements before reading other comments on them-that they are not “logical,” for example, and are hard for someone other than the author to follow-and will try to get those down before becoming too influenced by the ongoing discussion.

I am coming to this as someone who played Adventure a few times in the early 80s, on a mainframe, and doesn’t remember it very well. I have also not kept up on the literature about it, so I didn’t know until this week that there is a real cave on which the game is based! Wow, that adds an interesting dimension. I had played D&D in high school in the late 70s and thought Adventure was just “something like that,” that is, entirely made up. Meanwhile, only a little related to that background, I actually wrote my own historical text-based computer game for my undergrad senior honors project in 1983-84. Later, in the mid-90s, I became very immersed in MOO, and that’s where I did most of my significant programming (if MOO and “significant” can be used in the same sentence) and where I formed my ideas about text-based virtual environments/games as well as how to “script” them.

So I think about how I would have programmed a similar sort of move-through game first in the kind of FORTRAN, or especially PASCAL, that I learned in the early 80s (when I wrote a somewhat different kind of game) and then how I would have written it in MOO. And wouldn’t you know it, I would have used a lot of subroutines (whatever you want to call them in your language of choice). None of this if 1 goto 13, if 2 goto 27, if 3 goto 45 stuff. Do the same thing over and over (pick something up, move in a direction, send out a message) but just use different values for your variables depending on your location in the game. That is, find where you are, plug in the variables, spit out where you’re going.

Now, had I programmed the game as built around one or more subroutines and then tried to diagram or map the structure of the program, there would be lots of circular arrows coming back to the same black box or boxes, with what happens inside the box less important than what goes into it and what comes out: the code that through textual interaction moves the player from one encounter to the next. It wouldn’t have looked much like a cave.

So what immediately occurs to me is that while the GOTO style is infinitely harder to make “logical” sense of (in fact, it is as logical as you can get, just not easy for a human reader to parse), the map of the GOTO code is probably a lot closer to something that looks like the player’s experience, or the cave, then my preferred looping method. You make a choice, you go somewhere, you encounter something; you make another choice, you go somewhere else, etc. This is not to discount the presence of iterative (DO 1102 I=1,300) or backward loopings within this Adventure code, but just to point out that it embeds sequence and branching in a way that you don’t see in routine-based, script-based, or object-oriented languages.

Comment by Dennis G. Jerz on February 19, 2010 at 1:57pm

Near the end of Crowther’s source code:

SUBROUTINE YES(X,Y,Z,YEA)

Does the sequence “X,Y,Z,YEA” remind anyone else of something?

Comment by Dennis G. Jerz on February 19, 2010 at 2:06pm

Susan: I don’t have the vocabulary for what I wanted to express about the GOTO statements, so if I said GOTOs aren’t logical, I suppose I mean they are more associative and… er… ad hoc? In a sort of “this urn is precious because it is unique” way, as opposed to the behavior-based object-oriented structure, which aims for universality and re-use, in a “this urn is valuable because it meets behavior standards” way.

Comment by Susan Garfinkel on February 19, 2010 at 3:38pm

Dennis, “ad hoc” strikes me as quite appropriate here, although there may be more underlying structure in the GOTO sequences than I’ve yet discovered. FORTRAN certainly gives you the opportunity to be much more ad hoc about structure in a way that object-oriented languages actively work against. I guess it just strikes me that since computer code is so fundamentally based in the practices of logic that “logical” is an adjective best left out of more interpretive discussion.

Comment by Dennis G. Jerz on February 19, 2010 at 3:59pm

That makes sense. My use of “logical” was a loose reference to “order that I understand” as opposed to “order that I do not yet understand and which therefore seems illogical to me”.

Comment by Susan Garfinkel on February 19, 2010 at 3:27pm

Dennis wrote: “The GOTO statements whisk us from one area of the code to another, not unlike XYZZY and PLUGH. The impact is disorienting to the newcomer, but once you learn the geography, the GOTO label is very useful, because it marks a place where you are likely to keep returning to as you edit the code (much as XYZZY marks the place where Woods rewards us for depositing our treasures).”

This practice of teleporting back to a starting place carried over into MOO (so I assume many intermediate MUDs as well), even though the code there is object-oriented. Every player has a home and teleports there with the command “home;” the verb @go xxx takes you to numbered or named places; and then various players in various MOOs had/have built verbs or objects that enabled that skip-the-details-just-get-me-there motion (I had a great glass elevator at PennMOO long before Google unveiled theirs last week!).

I like this idea of thinking about code itself as having a geography of its own.

Comment by Mark Marino on February 19, 2010 at 4:23pm

Say, haven’t seen reference to this yet, but combining Week 2 & Week 3, I wanted to add the Slashdot thread about the discovery of the code as another source to spelunk for annotations. This is an example of CCS (and CCS-enabling moves) “in the wild” with a wide range of reactions, full of emotional investment in the marshalling of code snippets.

They also take up our “GOTO” discussion, comment on the programming language, but with an eye toward the cultural environments of the code and the way these FORTRAN statements look in the context of contemporary programming and computational discourse.

Comment by Mark Sample on February 19, 2010 at 5:55pm
I don’t want to wade too deeply into the critical code studies / cultural code studies debate, except to say I’m wary of hammering in any signposts that delineate either as fixed fields with prescriptive methodologies. Computer science is already intimidating enough to most humanists, and my goal is to involve *more* literary scholars and historians in science and technology studies, even if in low stakes kind of ways (such as my own participation on this forum). I think Dennis’s “ad-hoc” bricolage approach is extremely valuable, opening up lines of inquiry from nearly every perspective.

Going back to the idea of nostalgia that several of us mentioned. I do think nostalgia can offer a productive approach to code studies (whether you want to call it critical or cultural). It occurs to me that some of Susan Stewart’s grammar of longing, which she elaborated upon so brilliantly in On Longing, might be particularly useful to revisit when thinking about code.

Mark, I’ve been thinking that perhaps there is precedent for a group annotation of code, though it was done with a different goal in mind. The source code for the “default” Atari 2600 game Combatwas disassembled in the late nineties, and heavily commented by a group of three programmers. You’ll find the Definitive Combat Disassembly on AtariAge.

Speaking of annotation, I’m surprised at how little we’ve actually done with the code. Is there something inscrutable or illegible about the code that’s hindering us? Is the problem more procedural, and footnotes turn out to be inadequate to the task? Jeremy and I both point out different places where a different kind of “distant reading” (à la Franco Moretti) or other data visualization might be more useful than simple annotations. Maybe to annotate code with anything other than new code is a problem?

Comment by Evan Buswell on February 19, 2010 at 11:21pm

Stephen Ramsay: What’s going on? Why is this so hard?

I think you’re absolutely right in pointing out a problem here; we are not just all being comfortable scholars of the humanities applying our critical resources to the text of code, and it is very interesting to ask why not. I’m not sure I agree with your answer, but I don’t feel completely orthogonal to it either.

Code does have two sides to it, as the urn does. Every program ends up as software; and it seems from our experience here that software may be easier to analyze in its packaged, operational form. But the surface of the urn can’t be decompiled into the methods used to produce it in the same way that a program can be decompiled into code. There are a lot of programs that claim to be bug-for-bug compatible (especially within various Unices, where sancta simplicitas tends to carry the day). That is, in these programs, the procedure (supposedly) was exactly reproduced through code. I suppose this doesn’t necessarily prove anything, but I’m inclined to think that the code that built the software is in the software in a sense that the urn-building methods are not in the urn.

However, I think you hit on something in saying that code might be “a hard limitation of criticism.” Rather than suddenly finding ourselves able to easily draw out all kinds of things that are deeply hidden in code–and this is really not that hard with most types of language–we’re finding that instead of us critiquing code, code is critiquing us. Look at a random selection of the terms of textual analysis: signifier, signified, translation, meaning, author, reader, text, medium, construction, context, recontextualization… We can see how these words apply to code, but they do not fit quite as neatly as we may like.

For example, although code has meaning to the programmer as reader–that’s certainly its main purpose–in some ways its definitive meaning is created in compilation. I worked for a while on the JRuby project–porting the Ruby language to Java–and every once in a while we’d run across under-documented areas for which we’d devise very specific tests to see what some particular language construction really “means” in Ruby. Often the meanings we found would be somewhat unexpected, but they were almost always considered “right.” I think the gap between these two meanings, the meaning for the programmer and the meaning for the compiler, is what Federica was trying to get at. But they’re not just two different meanings; they’re two completely different concepts of what it means to mean. A compiler might be said to generate “meaning” by “translating” code from one “representation” to another. But the transformations that actually occur have a very problematic relationship to these terms. According to Claude Shannon’s theory of information, “meaning” doesn’t occur here; there is no “signified.” It is not so much a “translation” as a “transcoding,” a transformation in the form signifier-signifier. (According to my understanding of informatics, even running the program itself merely transcodes its stored information into various on-screen and on-disk signifiers.)

And yet: this transformation of the form signifier-signifier is a major factor in the creation of meaning for the programmer; it is a major factor in the creation of an actual signified. That’s why we’re inclined to use these terms–meaning, translation, representation–as I did above.

I think we may not yet have the tools to actually do a critical reading of a specific piece of code, at least if we interpret CCS in the strictest sense possible. But - as I think was one of the outcomes of the Week 1 thread - this isn’t necessarily a call away from critical code studies and towards something like critical code philosophy; there’s no reason that we can’t do something first, or at least make an attempt, then start to understand it, then do it better.

Comment by Mark Marino on February 20, 2010 at 8:23am

Evan,

Fascinating reflection. So, we may need different terms for these semiotic units? (If we can call them that.) I believe some here have suggested using some adaptation of J.L. Austin’s terminology of the performative, and the like. What other language or systems could we draw upon? What are the ways of describing these functional signs, these (often) letter-based cues, traces, and strings of intermediaries, transcodings, and interfaces? What methods do you prefer? Or do we need new terms for describing these in particular? Do you think “signs” might not be the best word?

Comment by Federica Frabetti on February 20, 2010 at 9:57am

I think that part of what came up in Week 3 brings us back to Week 2’s discussion and to Jeremy Douglass’ fascinating contribution.

Maybe a part of what I’ve attempted to do with Fortran is similar to Jeremy’s move of looking for practices of code reading ‘in the wild’ - i.e. looking at what people are already doing ‘out there’ (if there is such as a thing as an ‘out there’ when we look at code)? In fact, I think that Jeremy’s contribution implicitly highlights how the questions ‘how should we read code?’ and ‘how do we read code?’ are not mutually exclusive/opposed (unless I am misreading your intervention, Jeremy).

Jeremy Douglass wrote: ‘two cultures’ stereotypes of the code programmer with a mind of winter and the code poet with a heart too easily made glad.

I completely agree with Jeremy that people are already reading code, and that pros are well aware of the historical/philosophical/cultural dimensions of code/software, and I also agree that pitching programmers (functional readers) against literary critics (interpretative/imaginative readers) risks positing a new ‘two cultures’ debate - thus obscuring the existence of a multiplicity of readings.

So, hunting for interesting readings of code makes a lot of sense to me. Even more importantly, I think that CCS can go beyond an interdisciplinary approach that accommodates many finely nuanced readings. It can in fact become a field that actively problematizes the very concept of disciplinarity IN EVERY SINGLE ONE OF ITS READINGS.

(Incidentally, that’s why I do not think that ‘theoretical issues’ can be opposed to ‘actual readings’; indeed, every reading enacts or ‘performs’ CCS differently; to some extent, every reading disturbs previous assumptions about what code is, and every reading should be made accountable for its decisions about what code is, who is reading it and in what way).

I don’t know if code is territory (Jeremy), but I think that there is an unavoidable ‘territoriality’ in code readings/readers. This can be thought as part of the unavoidable violence of disciplinarity (a point that already came up in Week 1). However I also want to mention here the concept of ‘territoriality’ as it is outlined by one of the most famous voices of open source, Eric Steven Raymond, in his article ‘The Cathedral and the Bazaar’ (first presented at the Linux Kongress of 1997, republished online many times: http://firstmonday.org/htbin/cgiwrap/bin/ojs/index.php/fm/article/view/578/499). This article is considered the Bible of Software Engineering in the open source era. Not surprisingly Raymond argues that the best open source programmers are those who are less territorial toward their code. I think it makes for a fantastic reading and I’d recommend it to all CCS people.

Now, can we say that the best CCS practitioners are those less territorial with their readings of code? Conversely, are CCS practitioners somehow forced to be territorial? Many of us are academics, after all, and (let’s face it) academics tend to be territorial. Maybe we (academics, again) tend to spend waaaay too much time in discussing what single disciplines are, but then this is because ultimately disciplinarity influences not just our thinking but (let’s be honest again) our careers, our place in the university, our possibility of being in the academic institution critically and politically, our freedom of movement across and between fields and institutions and countries, the distribution of academic power, etc.

There is this wonderful book about cultural studies by Gary Hall, titled Culture in Bits(2002). In brief, Gary argues that cultural studies (its British tradition, at least) has an open and unfixed identity as a field (which makes it the ideal field for an investigation of digital media). For him, a critical attitude toward the concept of disciplinarity has characterized cultural studies from the start, and it informs cultural studies’ own disciplinarity, its own academic institutionalization.

Yet Hall argues that cultural studies has not always been up to such self-critique, and very often it has limited itself to an ‘interdisciplinary’ attitude understood as an incorporation of heterogeneous elements from various disciplines - what has been called the “pick’n’mix” approach of cultural studies. He therefore suggests that cultural studies should pursue a deeper self-reflexivity, in order to keep its own disciplinarity and commitment open, and he suggests that this self-reflexivity would be enabled by a ‘dialogue’ between cultural studies and deconstruction. He understand the latter first of all as a problematizing reading that would permanently question some of the fundamental premises of cultural studies itself.

Thus, cultural studies would remain acutely aware of the influence that the university, as a political and institutional structure, exercises on the production of knowledge (namely, by constituting and regulating the competencies and practices of cultural studies practitioners). It is precisely in this awareness, according to Gary Hall, that the political significance of cultural studies resides.

Now I am wondering whether CCS has an analogous potential - and I would say it does, but we need to be extremely attentive and self-reflexive to keep its disciplinary boundaries open.

But again, for me such self-reflexivity is what makes CCS particularly interesting (in a way, this is the meaning I would like to give to the word ‘Critical’ in ‘Critical Code Studies’) as a field capable not ‘just’ of questioning the nature of code but of having a much larger influence on our way of conceptualizing what counts as ‘academic knowledge’. For me, ‘looking out there,’ to readings of code that already exist, in and out of the academy, is part of this broadest picture.

Comment by Federica Frabetti on February 20, 2010 at 10:30am

Evan Buswell wrote: I think the gap between these two meanings, the meaning for the programmer and the meaning for the compiler, is what Federica was trying to get at. But they’re not just two different meanings; they’re two completely different concepts of what it means to mean. A compiler might be said to generate “meaning” by “translating” code from one “representation” to another. But the transformations that actually occur have a very problematic relationship to these terms. According to Claude Shannon’s theory of information, “meaning” doesn’t occur here; there is no “signified.” It is not so much a “translation” as a “transcoding,” a transformation in the form signifier-signifier. (According to my understanding of informatics, even running the program itself merely transcodes its stored information into various on-screen and on-disk signifiers.)

GREAT! You have just rephrased what I was trying to say, only much, much better than I did.

I am completely disinclined to use terms like ‘meaning’ and ‘representation’ when talking about code. In fact, I use the term ‘re-inscription’ precisely in order to avoid the above terms.

I’m not saying that using semiotics is ‘bad’. I am just saying that I want to try and read code without recourse to the structuralist dichotomy signifier/signified. NO, I guess what I am trying to do is: acknowledge that programming languages have been developed by using Chomskyan grammars etc., therefore ultimately on the basis of structuralist linguistics, and for this reason we cannot do away with the dichotomy of signifier/signified (syntax/semantics, etc.) when ‘reading’ code. BUT (and this is why I attempt a deconstructive reading of code) it is also possible to show that the concepts of structural linguistics ultimately do not hold in code (as e.g. Evan points out very well). When reading code with a problematic approach, we invariably reach a point where the distinction between signifier and signified becomes undone.

This is also why I have a problem with identifying signifiers and signifieds in code. I am not 100% happy with the idea that ‘the meaning of code is what it does’ either.

I am more comfortable with the idea of code as a performative, but again Austin needs to be re-read through Derrida’s Limited Inc. (1988) to be made useful for a reading of code, at the very least. For instance, I would argue (in dialogue with Jeremy Douglass’s contribution again) that ALL code is citational (and I am following Derrida’s deconstruction of Austin here) - because code is material mark(s) (or inscriptions), and ‘what would a mark be that could not be cited?’

Comment by Dennis G. Jerz on February 20, 2010 at 11:36am

On the issue of code critiques in the wild:

In what contexts do we find critiques in the wild? Amazon.com reviews are generally spoiler-free, consumerist recommendations. Likewise, while Roger Ebert draws on a huge store of knowledge in every review he writes, many of his readers are simply looking at his trademarked thumbs. I’m impressed at the level of textual analysis going in Harry Potter fandom that I’ve looked into, and I’m embarrassed by the level of detail that goes into the Star Trek and Star Wars fandom in which I’ve actively participated.

Fanfic and remixing is a way of hacking the subject matter traditionally explored by critical analysis, and while a successful culture jammer must know culture at least as well as the cultural theorist who judges the jamming, the line between theory and praxis isn’t that great in media where the critiquing and the creating both use the same medium (words). So, it would seem that modding and hacking would be the natural way that coders evaluate code. Adventure attracted collaborators, innovators, and imitators, and we can learn about the value of a code artifact by tracking the success of the memes that have escaped the immediate context of the code. (I’m thinking of maze puzzles, timed light sources, reincarnation, the wry, slightly antagonistic voice of the text-adventure narrator, and the setting of games in underground spaces…. why was Rogue set underground, for instance, and not in ascending levels of a tower (such as the one Sam fights through to get to Frodo’s body, or forest clearings connected by forest paths (such as the Elvish celebrations that the starving dwarves kept pursuing in Mirkwood?)

Adventure started a lot of memes rolling, and perhaps nostalgia is a good index to identifying processes - not texts or locations, but rituals - that we have internalized because we know them so well. And only because we know the rituals of our favorite childhood computer game are we (the non-professional programmers) familiar enough with the behavior of a program to start making the kinds of deep connections that we’re used to making when we study a static text.

Socrates lamented the cultural losses that would result when people started turning away from dialogue, repetition, and memorization (the traditional tools of knowledge acquisition in an oral culture), and turned instead towards the shallow and impersonal technology of writing, which permitted anyone to sound intelligent by simply reading aloud from a script. It took a while for a new form of scholarship to develop, that counted on the scholar’s universal access to authoritative, standard texts. In fact, it took the invention of the printing press to fully unlock the potential of textual scholarship. As we contemplate the study of code, we can’t assume that every scholar has universal knowledge of programming (especially when the language in question is obscure, at least from the perspective of most of the coding that’s being done today). And I find this page is getting so slow to load - presumably because of the changes to the Google Docs churning through the framed windows - that the annotation of the code may be hampering our ability to carry on the relatively old-fashioned conversation here in the comments.

Comment by Stephen Ramsay on February 20, 2010 at 11:39am

But they’re not just two different meanings; they’re two completely different concepts of what it means to mean. A compiler might be said to generate “meaning” by “translating” code from one “representation” to another. But the transformations that actually occur have a very problematic relationship to these terms. According to Claude Shannon’s theory of information, “meaning” doesn’t occur here; there is no “signified.” It is not so much a “translation” as a “transcoding,” a transformation in the form signifier-signifier.

I just want to note the interesting relationship that this observation has to Searle’s Chinese Room (and to the Turing test). Shannon may argue that Meaning doesn’t occur here, but are we sure of that? Are we sure that translation is not evidence of meaning or even understanding? What criteria would we use to say that “the compiler does not understand what it’s doing.”

I’m trying very hard not to argue against Derrida by arguing against Federica, but I’m a lot more comfortable with the idea that meaning is use (or, less precisely, that the meaning of code is what it does). Programming languages remind me of nothing so much as Wittgenstein’s language games (“RED SLAB!”), and I think part of my unease in this discussion is thinking of what he might say about our attempt to barge into one of these games with news of the unutterable utterance that sustains their discourse. The main problem with the unutterable utterance is that as soon as you are understood by the speakers of SLAB, you are effectively within the discursive space of SLAB (just as - and I still think this - Federica is not revealing the unspoken assumptions of formal language theory, but saying something that is entirely intelligible to that discourse. Because it *is* that discourse).

Comment by Dennis G. Jerz on February 20, 2010 at 4:47pm

In 2002, Sun programmer Richard Gabriel gave an interview on “The Poetry of Programming,” in which he described an MFA in software.

http://www.dreamsongs.com/PoetryOfProgramming.html

Comment by Susan Garfinkel on February 20, 2010 at 6:40pm

As a big fan of the work, I’d love to hear Mark Sample say more about the relevance of Susan Stewart’s On Longing to these discussions.

Comment by Mark Marino on February 21, 2010 at 12:22am

This is where I’m sorry this discussion page isn’t threaded, as I want to raise an issue that isn’t directly following the above conversation.

Jeremy and I spent some time looking at this line:

CALL IFILE(1,’TEXT’)

Neither of us could find where IFILE was specified and determined that it must have been defined elsewhere. But if not in these two files, where?

Hunting around turned up a few interesting notes:

Andrew retro98se [at] gmail.com had tried to implement Dennis’s code and had to write a new function for IFILE to make it operate. He created a patch to solve the problem of the unspecified command, basically creating a function that, as Jeremy put it, put a wrapper around the specified OPEN function.

Then came this other work around, where another programmer changed the invalid (FORTRAN 77) instruction or undefined IFILE function to the OPEN function, altering this original source code.

Chatting with Jeremy on back channels, we both felt these approaches warranted discussion, since one avoids changing this original source code, perhaps avoiding tampering with a sacred artifact, while the other treats the code as a functional object, a Model T that needs a tire patch. No doubt the differing approaches raise issues about the relationship of programmers to these artifacts when they want to restore them to working condition.

But then, we started to ask questions about this particular source code. Where was “IFILE” defined? Was there some other library accessed by Crowther’s code? What would such a library look like? Or is there some other explanation? Essentially, do we have all the code?

To raise these questions is more than asking: do we study the code (one discrete set of instructions and data) or the entire code milieu (operating system, other programs being accessed, compilers, lower-level languages). I started wondering, without trying to be too Barthesian, how much of the code is necessary to put a front and back cover on it and call it an object of study? When do you have enough code or documentation? Or must we, and here I will nod to Barthes, accept that we are always dealing with snippets?

But it also raised a simple historical question about where the missing piece is…

Comment by Federica Frabetti on February 21, 2010 at 6:55am

Stephen, thank you for not arguing against Derrida by proxy. I am unfaithful to deconstruction.

However, there is a difference between Wittgenstein’s unutterable and a deconstructionist point of opacity. Of course what a ‘deconstructionist’ (even an unfaithful one) can say about a certain conceptual system is always said from within the system - therefore it is intelligible. I am perfectly happy with being intelligible to theorists of programming languages. In fact, I believe that there is no outside of the system - no safe point from where to read code that is not already code.

Comment by Dennis G. Jerz on February 21, 2010 at 10:17am

Mark Marino: I believe the IFILE subroutine was highly machine-dependent, carrying on some of the functions that we would probably expect an operating system to handle through a driver, but of course this was in an era where the concepts we understand by those terms were still developing. Was the missing subroutine so well-known that at BBN Crowther would have expected everyone to have a copy? Did Woods recognize it as an ad-hoc routine that he knew wouldn’t work at Stanford, so he didn’t bother to save a copy (either back in the 70s, or thirty years later when he made certain files from his student backup accessible to me)?

So, to answer your questions fully, Mark, we’d need to ask platform-studies questions, rather than strictly CCS questions.

According to retro98se:

.; Adventure performs a CALL IFILE(1,’TEXT’) to read the game database
.; DAT file, but the code doesn’t define IFILE.
.
.; IFILE may have originally been part of a 3rd party IOFIL library.
.; Without the library, we’ll create the file IFILE.F4 with the
.; Fortran code for this function.
.
.; Function argument FNAME is a file name string of length up to 10
.; characters. The required type depends on the Fortran compiler.
.; Fortran 6 expects FNAME to be an array. In later Fortran versions,
.; FNAME needs to be type “double precision” or “character” instead.
.
.sos ifile.f4
Creating IFILE.F4[100,100,ADV0]
00100 SUBROUTINE IFILE(UNUM,FNAME)
00200
00300 IMPLICIT INTEGER(A-Z)
00400 DIMENSION FNAME(2)
00500 C DOUBLE PRECISION FNAME
00600 C CHARACTER FNAME*10
00700
00800 OPEN(UNIT=UNUM,NAME=FNAME,ACCESS=’SEQIN’)
00900 RETURN
01000 END
01100 $
*eu
[DSKB:IFILE.F4[100,100,ADV0]]

.type ifile.f4
SUBROUTINE IFILE(UNUM,FNAME)

IMPLICIT INTEGER(A-Z)
DIMENSION FNAME(2)
C DOUBLE PRECISION FNAME
C CHARACTER FNAME*10

OPEN(UNIT=UNUM,NAME=FNAME,ACCESS=’SEQIN’)
RETURN
END

Comment by Mark Marino on February 21, 2010 at 11:08am

Thank you, Dennis.

Regarding platform studies, I’m not so worried about border control policing that particular seam.

So let’s have some low lying fruit for our Sunday.

I like how your annotation of QUIP offers us a handle for reading the personification of the system as interlocutor with various registers of speech. Are QUIPs quips? What does it mean for software to quip? How are these remarks qualitatively and connotatively different than the other on-screen statements related to the Jsp array (if we can call it that)? Does conversational analysis for speech-related HCI theories speak (or quip) to this? Certainly my chatbot-loving ears (tuned when writing my dissertation) were humming.

Comment by Dennis G. Jerz on February 21, 2010 at 12:49pm

Mark, perhaps an invitation to the Usenet group alt.sys.pdp10 would attract people with the knowledge we seek? And coding geniuses Matthew Russoto and David Kinder (well known for the technical skills they provide to the IF community) would also be good resources, but I would probably learn a lot by spending more time wrestling with the code, before I can formulate the exact questions I’d want help addressing. (I am so glad of this opportunity to share ideas with a group… I had some wonderful insights after working for less than an hour with Doug Reside at Maryland Institute for Technology in the Humanities, as we were trying to figure out some last-minute details for the “staged reading” of the Adventure source code.

http://voices.washingtonpost.com/posttech/2008/05/colossal_cave_adventure_lives.html

Comment by Dennis G. Jerz on February 21, 2010 at 1:32pm

A useful next step… look at all the ways the game can end.

While reading in values from the data file:
PAUSE ‘TOO MANY LINES’
PAUSE ‘TOO MANY WORDS’

After reading in the data
PAUSE ‘INIT DONE’
(I believe the player is instructed to type ‘go’ here - this procedure is not in the Crowther source code)

After being killed by a dwarf (the game SPEAKs “HE GETS YOU!” first).
83 PAUSE ‘GAMES OVER’

After death by snake:
31 PAUSE ‘GAME IS OVER’

From the GETIN procedure, three intriguing errors, with completely unhelpful descriptions. Anyone want to help me sort these out?
PAUSE ‘ERROR 6’
PAUSE ‘NO NO’
PAUSE ‘ERROR 5’

After trying to move in the dark (and falling into a pit, the first of which actually does appear not far from the room where Crowther determined further progress would be impossible without a light) the game first prints “YOU FELL INTO A PIT AND BROKE EVERY BONE IN YOUR BODY!”
PAUSE ‘GAME IS OVER’

Comment by Dennis G. Jerz on February 21, 2010 at 1:56pm

Another project: when does Crowther use exclamation marks?

In the source code, reporting a dwarf attack:
78 FORMAT(’ ‘,I2,’ OF THEM THROW KNIVES AT YOU!’,/)

In the data file, responding to properly formed but impossible requests:
23 YOU CAN’T GO IN THROUGH A LOCKED STEEL GRATE!
24 YOU DON’T FIT DOWN A TWO INCH HOLE!

Calling attention to the snake and treasures
210 THERE IS A LARGE SPARKLING NUGGET OF GOLD HERE!
11 A HUGE GREEN FIERCE SNAKE BARS THE WAY!
112 A CRYSTAL NOW SPANS THE FISSURE.
213 THERE ARE DIAMONDS HERE!
214 THERE ARE BARS OF SILVER HERE!
215 THERE IS PRECIOUS JEWELRY HERE!
216 THERE ARE MANY COINS HERE!

Note that 11, the line mentioning the crystal bridge, lacks an exclamation mark. There’s nothing to DO with this bridge once it appears, so that it seems to become part of the scenery, rather than object to interact with.

Other objects do not get exclamation marks.
19 THERE IS FOOD HERE.
20 THERE IS A BOTTLE OF WATER HERE.
120 THERE IS AN EMPTY BOTTLE HERE.
221 THERE IS A LITTLE AXE HERE

The axe is your only defense against the dwarves; it gets no punctuation at all, perhaps because when the axe is likely to appear, these sorts of things are going on:

4 THERE IS A THREATENING LITTLE DWARF IN THE ROOM WITH YOU!
5 ONE SHARP NASTY KNIFE IS THROWN AT YOU!
6 HE GETS YOU!
7 NONE OF THEM HIT YOU!

The “HOLLOW VOICE” does not speak ‘PLUGH’ with an exclamation mark. But the voice of the parser does express a bit of frustration with the player:
13 I DON’T UNDERSTAND THAT!
[…]
24 YOU ARE ALREADY CARRYING IT!
25 YOU CAN’T BE SERIOUS!
[…]
28 THERE IS NOTHING HERE WITH A LOCK!
29 YOU AREN’T CARRYING IT!
[…]
31 YOU HAVE NO KEYS!

And, after moving in darkness,
23 YOU FELL INTO A PIT AND BROKE EVERY BONE IN YOUR BODY!

The long in-game HELP text includes two exclamation marks (here are excerpts):

51 MORE WORDS. USUALLY PEOPLE TRYING TO MANIPULATE AN
51 OBJECT ARE ATTEMPTING SOMETHING BEYOND THEIR (OR MY!)
51 CAPABILITIES AND SHOULD TRY A COMPLETELY DIFFERENT TACK.
[…]
51 LOST IN THE FOREST. ALSO, NOTE THAT CAVE PASSAGES TURN A
51 LOT, AND THAT LEAVING A ROOM TO THE NORTH DOES NOT GUARANTEE
51 ENTERING THE NEXT FROM THE SOUTH. GOOD LUCK!

Since we’ve already seen “HE GETS YOU!” in string 6, it’s not immediately clear why we also need
52 IT MISSES!
53 IT GETS YOU!
..but the dwarf battle sequence seems to require sequential miss/hit messages, since the random variable STICK seems to determine whether the dwarf attack is successful, and these lines

CALL SPEAK(52+STICK)
GOTO(71,83)(STICK+1)

First print out either message 52 “IT MISSES!” or 53 “IT GETS YOU,” based on whether STICK is 0 or 1. The GOTO statement will check the value of STICK+1 (which is either 1 or 2), and execute 71 if 1, and 83 if 2.

And, of course, when the game begins, we get two exclamation marks:
65 WELCOME TO ADVENTURE!! WOULD YOU LIKE INSTRUCTIONS?

After eating the food ration,
72 EATEN!

After dropping the f-bomb:
87 WATCH IT!

Comment by Evan Buswell on February 21, 2010 at 4:04pm

Stephen Ramsay wrote: I just want to note the interesting relationship that this observation has to Searle’s Chinese Room (and to the Turing test). Shannon says, “Meaning doesn’t occur here,” but are we sure of that? Are we sure that translation is not evidence of meaning or even understanding? What criteria would we use to say that “the compiler does not understand what it’s doing.”

I definitely don’t want to just take Shannon’s word for it. However, as Federica says above, “programming languages have been developed by using Chomskyan grammars etc., therefore ultimately on the basis of structuralist linguistics, and for this reason we cannot do away with the dichotomy signifier/signified (syntax/semantics, etc.) when ‘reading’ code.” I think this goes for a lot of other theoretical linguistic apparatus as well.

There is an aspect of all language–not the whole, but an aspect–where we can’t help but mean in the way we (collectively) intend, where we can’t help but mean according to our theories of meaning. That collective intention is a huge part of what creates the system by which we mean, and it is reflected somehow in the way we speak. The way code is structured, and the way that meaning is generated within code, is thoroughly colored by Shannon’s theory of information and Chomskian grammars. In one sense, then, it does little good to call these “wrong”; they perform work in the language regardless of our opinion of them.

However, that aspect isn’t the whole of language. Theorizing about meaning in the first place would be pointless unless the way meaning is created somehow exceeded our theories. Further, as Stephen points out, there’s a relationship between Shannon’s theory of information and Searle’s Chinese room. Given the mixed reception of Searle’s thought experiment among programmers, we can safely say that the community that surrounds code is not settled on any of these theories; they are not universal.

I think this theoretical aspect is present in all language-though I wouldn’t want to be responsible for proving that statement. But in code at least, it is readily apparent that the theory of code’s working is deeply implicated in how it actually works. That might be the most distinctive thing about codic vs. non-codic languages. I’m probably going to be thinking for the rest of the day about the way the theory of code’s meaning interacts with other factors to produce meaning in code; all that’s clear to me now is that there is an interaction.

These two sides, the theory defining the language and the language defining the theory, are what makes the action of a statement wholly inadequate as its definition, and it’s what makes Federica’s insight that we should be looking at compilation so relevant. If the way a statement acted was what that statement meant, then a compiler could never behave incorrectly. But a compiler can be said to have errors. And so there must be the concept of what code is supposed to do that is distinct from what it does. And if that’s the case, where does this “supposed to” come from if not from an understanding of code that’s not completely dependent on the compilation?

Comment by Evan Buswell on February 21, 2010 at 4:21pm

Mark Marino wrote: What other language or systems could we draw upon? What are the ways of describing these functional signs, these (often) letter-based cues, traces, and strings of intermediaries, transcodings, and interfaces. What methods do you prefer? Or do we need new terms for describing these in particular? Do you think “signs” might not be the best word?

Thanks for the questions! I definitely don’t have the answers yet. Something tells me there might be similar issues that the critical legal studies discipline addresses, but I haven’t even begun to look at that. Mostly though, I don’t think different terms is the answer, but a different way of thinking about the terms, a different way of thinking about language. Hence the idea of allowing code to critique us. Things like “signifier” and “signified” still function, but the way they function is different than in, for example, Roland Barthes. But that being said, I’m not attached to keeping these words if some better tools should come along.

Comment by Jeff Nyhoff on February 21, 2010 at 5:44pm

Performativity: For myself, I have always found Judith Butler’s performativity to be the most useful vis-à-vis the notion of “code” - iterable, normative, compulsory, citational, cultural systems that interpellate us into constructed identities. Moreover, the normative, interpellating subjectivities that are produced by such regulatory structural systems as computer code seem to me to be gendered in that they position the access to, the knowledge of, and the manipulation of that code itself as the phallic signifier that constructs the “programmer/end-user” binary, with the latter (in this context, the “player”) understood first and foremost in terms of the lack of this signifier - the non-programmer, the non-coder.

GOTO: I find it ironic that mention has been made of the fall from favor of the “GOTO” statement, while we annotate this code with footnotes - themselves, “GOTO” statements.

Line Editors: I appreciated Dennis’ mention of line editors early in this thread. It does underscore the need to consider the various technologies of reading implicit in any notion of “reading code.” Indeed, I would suggest that it would be very difficult to understand the process of authoring such code as that before us without ever having coded a program entirely with a line editor. The focus on a single line at a time encouraged a different kind of focus and bracketing of individual statements/actions that matched well to line-oriented languages like BASIC, FORTRAN, and COBOL. I recollect the staccato rhythm and accompanying shifts of perspective when switching back and forth between the “INPUT” and “EDIT” modes when I look at this code. Dennis also mentions the “printer terminals” - i.e “teletypes” - on which programmers worked in this era, with their “roll[s] of continuous paper.” I’m reminded of how much more auditory, tactile, and kinesthetic the process of programming was in the pre-CRT era. Debugging often meant, literally, attempting to “put one’s finger on the problem.” After giving command for compilation, for example, there would often be a delay, when one could walk across the room - e.g., to confer with a colleague. The amount of time that passed before one heard the teletype begin to print, the density of the rhythm and duration of its very audible printing, the amount of paper that (literally) scrolled out of it in response to the entered command - all of this was part of the feedback that one compared to one’s expectations, often enabling one to know whether or not the program had compiled and was executing well before one crossed the room back over to the teletype and read the actual text output. All of these are attributes I find implicit in the materiality of the code we have been examining this week, even as we are able read it its entirety, rather than fragments of lines, and on the screen instead of on paper.

Comment by Max Feinstein on February 22, 2010 at 12:21pm

Mark Marino passed this link my way, which contains extensive commentary on Dennis’s article on both Slashdot and Google boards. I ported some of the relevant discussion into our group annotation document. Much of what I included appears near the top of the source file and pertains to GOTO statements. Although I tried to be thorough, I imagine further investigation would make this commentary-transfer exhaustive. Feel free to peruse the Slashdot and Google discussions for more remarks that would fit into our annotations.

Comment by Rosemarie Coste on February 22, 2010 at 1:19pm

About annotating line-by-line:

I did a bit of that in the GoogleDoc here, recording some memories of playing ADVENTURE when I was an undergrad; it’s fun, but line-by-line examination and annotation is not usual, nor often useful, as a way to develop or debug or teach or otherwise understand code. A program or subroutine or other cohesive chunk of logic (a DO loop, for example) ordinarily begins with a few lines of comments, explaining the thinking behind that chunk; if a single line has a comment explaining it, that’s probably because something odd or unobvious happens there. Programmers believe in and write to future programmers, whom they expect will read and possibly change present code; that means, if we’re responsible people, we leave each other clues at especially difficult turnings in the road. Maybe I modified one line but the rest of the routine matches a widely-used original, in which case I should leave my name and the date and some explanation for my change; maybe it took me forever to get this just right and I know the next reader will think what I previously thought, that this cannot possibly work, and so I leave a comment along the lines of DO NOT TOUCH THIS UNLESS YOU READ MY EXTENSIVE EXPLANATION IN THE TECH SUPPORT DOC.

When code fails, the failure is often stated in terms of a single line: FLOATING POINT OPERATION FAILURE ON LINE 227. In years of working in technical support, though, I found that the people who approached understanding the failure in terms of understanding a single line (I don’t know why Line 227 doesn’t work) were the least able to solve it: something is wrong, and on Line 227 it becomes so wrong that it can no longer be tolerated, but the story begins elsewhere. Even the maligned DO I=1.10 is only wrong in a context: the value of I is never going to be 1.10, which I know because I can see I being initiated to 1 and then incremented by 1; the comparison can never be TRUE, so the logic can never be executed. If it was never meant to be executed (especially in early development, programmers can intentionally create a comparison that can never be true, just to make sure a not-ready section of code stays out of the way), not a problem; if it was meant to be executed 10 times, bad news. The line is wrong because it is wrong in its context, not on its intrinsic merits. (A compiler would catch that more basic kind of error, in which a line of code is just nonsense in any context; such code can’t execute at all and so cannot execute incorrectly.)

I have marked up and debugged my share of code, from FORTRAN in the 1970s to PHP today, and my observation of my own and others’ methods is that it is primarily visual and experiential: big brackets surrounding a DO; a big arrow to the internal destination of a GOTO; more big arrows to the external destination of a CALL; scraps of paper cut up and rearranged and tacked up on the wall to help consider an alternative order of events; code fragments run against a test bed, repeating with variation until a failure-causing pattern becomes clear; visual models generated from the running code compared to hand-drawn models from the user requirements, looking for mismatches. Even with software debugging tools available, even for programming languages that look very much like human languages, programmers still debug with eyes and hands more so than with words: if the project here is to create a critical method for deep understanding of code, as deep as that of the people who create and maintain it, then collaborative footnoting of single lines has to evolve into something closer to collaborative visualization of movement and structure.

Software tools exist for this kind of work. There are customary ways of finding the right tool, and this is the customary way to start that process: work enough without a tool that you develop some clarity about what it ought to do to support the current project. Step 2 is to make a formal list of requirements; that’s a good activity for a committee to begin, using collaborative textual editing tools to collect everyone’s thoughts, then for a writer to finish, assembling the dogpile into a usable list. Step 3 is to investigate whether the requirements, including financial and scheduling requirements, are best met by ready-to-go commercial off-the-shelf software (COTS) or by customizing open-source software or by building something completely new. Step 4 is to try two or three finalists, again a good job for a committee, and report on whether they really will do the job. Step 5 is to pick a winner and have everyone start using it. That’s the traditional method within IT, anyway; brainstorming and experimenting can help, but they help most within a larger process that ends up with a tool.

Comment by Jeremy Douglass on February 22, 2010 at 6:33pm

In a back channel discussion, I got into a short conversation about another version found online:

http://www.network54.com/Forum/190883/thread/1203612801/1203612956/Colossal+Cave+%28FORTRAN+77%29

The question was, what is this version? It doesn’t appear to be (?) one of the major versions from Dalenberg’s Adventure family tree or genealogy.

This looks like a literal update of CROW0000 (the original edition of the Woods code that we are discussing) in order to compile on a contemporary (2008) implementation of Fortran 77. I say this based on the date of the thread and the compilation instructions provided in the third post, but also based on “reading” the full code in comparison to the full code we are discussing here. This was an engaged reading, but not a close reading - it was a distance reading, which is quite common for code. I took the two source files and two data files, then compared each pair to generate a graphical diff - in my case using FileMerge (OS X Developer Tools).

What I found from a brief browse was that the code seemed to mostly be a simple update of the Crowther version we are studying here (CROW0000) to compile on a contemporary (2008) implementation of Fortran 77. The majority of the code changes were minimal, e.g. replacing the TYPE command with PRINT, or the PAUSE command with STOP.


Of course, the word change may reflect that editor’s personal taste, or it may reflect the presence of some other disciplining editor. For example, perhaps the forum where this was posted automatically rejects posts containing “fuck”, or maybe even replaces them with ****? Based on other local changes (like the shift in line numbers), I don’t think so, but it is interesting to think about Crowther’s code being revised by code.

Works Cited

Aho, Alfred V, Monica S. Lam, Ravi Sethi, and Jeffrey D. Ullman. Compilers: Principles, Techniques, and Tools. London and New York: Pearson and Addison Wesley, 2007. Print.

Buckles, Mary Ann. “Interactive Fiction: The Computer Storygame ‘Adventure’.” Ph.D. Thesis. U. Cal at San Diego, 1985

Ceruzzi, Paul. Beyond the Limits: Flight Enters the Computer Age. Cambridge, MA: MIT Press, 1989. Print.

Clocksin, William F., and Christopher S. Mellish. Programming in Prolog. Berlin; New York: Springer-Verlag, 2003. Print.

Derrida, Jacques. Limited Inc. Evanston, IL: Northwestern University Press, 1988. Print.

—.”Structure, Sign and Play in the Discourse of the Human Sciences.” Writing and Difference. Tr. Alan Bass. Chicago, University of Chicago Press, 1978. 278-95.

Hall, Gary. Culture in Bits: The Monstrous Future of Theory. London; New York: Continuum, 2002. Print.

Hopcroft, John E., and Jeffrey D. Ullman. Formal Languages and Their Relation to Automata. Reading, Mass: Addison-Wesley Pub. Co., 1969. Print.

Jerz, Dennis. “Somewhere Nearby is Colossal Cave: Examining Will Crowther’s Original ‘Adventure’ in Code and in Kenucky.” Digital Humanities Quarterly 1.2 (2007). Web.

Levy, Steven. Hackers: Heroes of the Computer Revolution. New York: Penguin Books, 2001. Print.

Leroi-Gourhan, André. Gesture and Speech. Cambridge, MA: MIT Press, 1993. Print.

McCarthy, John, Massachusetts Institute of Technology. Computation Center, and Massachusetts Institute of Technology. Research Laboratory of Electronics. LISP 1.5 Programmer’s Manual. Cambridge, MA: MIT Press, 1965. Print.

Stewart, Susan. On Longing: Narratives of the Miniature, the Gigantic, the Souvenir, the Collection. Durham: Duke University Press, 1993. Print.

Appendix: Code File and Data File

CODE FILE

1

C ADVENTURES2
IMPLICIT INTEGER(A-Z)3 ;4
REAL RAN5
COMMON RTEXT,LLINE

678910
DIMENSION11 IOBJ(300),ICHAIN(100),IPLACE(100)
1 ,12IFIXED(100),COND(300),PROP(100),ABB(300),LLINE(1000,22)
2 ,LTEXT(300),STEXT(300),KEY(300),DEFAULT(300),TRAVEL(1000)
3 ,TK(25),KTAB(1000),ATAB(1000),BTEXT(200),DSEEN(10)
4 ,DLOC(10),O13DLOC(10),DTRAV(20),RTEXT(100),JSPKT(100)
5 ,IPLT(100),IFIXT(100),QUIP(100)

C READ THE PARAMETERS14

IF(SETUP.NE.0) GOTO 115
SETUP=1
KEYS16=117
LAMP18=2
GRATE19=3
RO

20=5
BIRD21=7
NUGGET22=10
SNAKE23=11
FOOD24=19
WATER=20
AXE=21
DATA25(QUIP(I),I=1,9)/50,51,64,66,67,68,69,49,79/
DATA26(JSPKT(I),I=1,16)/24,29,0,31,0,31,38,38,42,42,43,46,77,71
1 ,73,75/
DATA(IPLT(I),I=1,20)/3,3,8,10,11,14,13,9,15,18,19,17,27,28,29
1 ,30,0,0,3,3/
DATA(IFIXT(I),I=1,20)/0,0,1,0,0,1,0,1,1,0,1,1,0,0,0,0,0,0,0,0/
DATA(DTRAV(I),I=1,15)/36,28,19,30,62,60,41,27,17,15,19,28,36
1 ,300,300/
DO 1001 I=1,300
STEXT(I)=0
IF(I.LE.200) BTEXT(I)=0
IF(I.LE.100)RTEXT(I)=0
1001 LTEXT(I)=0
I=1
CALL IFILE2728(1,’TEXT’)
1002 READ(1,1003) IKIND
1003 FORMAT(G)
GOTO(1100,1004,1004,1013,1020,1004,1004)(IKIND+1)293031
1004 READ(1,1005)JKIND,(LLINE(I,J),J=3,22)
1005 FORMAT(1G,20A5)
IF(JKIND.EQ.-1) GOTO 1002
DO 1006 K=1,20
KK=K
IF(LLINE(I,21-K).NE.’ ‘) GOTO 1007
1006 CONTINUE
STOP
1007 LLINE(I,2)=20-KK+1
LLINE(I,1)=0
IF(IKIND.EQ.6)GOTO 1023
IF(IKIND.EQ.5)GOTO 1011
IF(IKIND.EQ.1) GOTO 1008
IF(STEXT(JKIND).NE.0) GOTO 10093233
STEXT(JKIND)=I
GOTO 1010

1008 IF(LTEXT(JKIND).NE.0) GOTO 1009
LTEXT(JKIND)=I
GOTO 1010
1009 LLINE(I-1,1)=I
1010 I=I+1
IF(I.NE.1000)GOTO 1004
PAUSE ‘TOO MANY LINES’

1011 IF(JKIND.LT.200)GOTO 1012
IF(BTEXT(JKIND-100).NE.0)GOTO 1009
BTEXT(JKIND-100)=I
BTEXT(JKIND-200)=I
GOTO 1010
1012 IF(BTEXT(JKIND).NE.0)GOTO 1009
BTEXT(JKIND)=I
GOTO 1010

1023 IF(RTEXT(JKIND).NE.0) GOTO 1009
RTEXT(JKIND)=I
GOTO 1010

1013 I=1
1014 READ(1,1015)JKIND,LKIND,(TK(L),L=1,10)
1015 FORMAT(12G)
IF(JKIND.EQ.-1) GOTO 1002
IF(KEY(JKIND).NE.0) GOTO 1016
KEY(JKIND)=I
GOTO 1017
1016 TRAVEL(I-1)=-TRAVEL(I-1)
1017 DO 1018 L=1,10
IF(TK(L).EQ.0) GOTO 1019
TRAVEL(I)=LKIND*1024+TK(L)
I=I+1
IF(I.EQ.1000) STOP
1018 CONTINUE
1019 TRAVEL(I-1)=-TRAVEL(I-1)
GOTO 1014

1020 DO 1022 IU=1,1000
READ(1,1021) KTAB(IU),ATAB(IU)
1021 FORMAT(G,A5)
IF(KTAB(IU).EQ.-1)GOTO 1002
1022 CONTINUE
PAUSE ‘TOO MANY WORDS’

C TRAVEL = NEG IF LAST THIS SOURCE + DEST*1024 + KEYWORD34

C COND = 1 IF LIGHT, 2 IF DON T ASK QUESTION3536

1100 DO 1101 I=1,100
IPLACE(I)=IPLT(I)
IFIXED(I)=IFIXT(I)
1101 ICHAIN(I)=0

DO 1102 I=1,300
COND(I)=0
ABB(I)=0
1102 IOBJ(I)=0
DO 1103 I=1,10
1103 COND(I)=1
COND(16)=2
COND(20)=2
COND(21)=2
COND(22)=2
COND(23)=2
COND(24)=2
COND(25)=2
COND(26)=2
COND(31)=2
COND(32)=2
COND(79)=2

DO 1107 I=1,100
KTEM=IPLACE(I)
IF(KTEM.EQ.0)GOTO 1107
IF(IOBJ(KTEM).NE.0) GOTO 1104
IOBJ(KTEM)=I
GO TO 1107
1104 KTEM=IOBJ(KTEM)
1105 IF(ICHAIN(KTEM).NE.0) GOTO 1106
ICHAIN(KTEM)=I
GOTO 1107
1106 KTEM=ICHAIN(KTEM)
GOTO 1105
1107 CONTINUE
IDWARF=0
IFIRST=1
IWEST=0
ILONG=1
IDETAL=0
PAUSE ‘INIT DONE’

371 CALL YES(65,1,0,YEA)
L=1
LOC=1
2 DO 73 I=1,3
IF(ODLOC(I).NE.L.OR.DSEEN(I).EQ.0)GOTO 73
L=LOC
CALL SPEAK(2)
GOTO 74
73 CONTINUE
74 LOC=L

C DWARF STUFF38

IF(IDWARF.NE.0) GOTO 60
IF(LOC.EQ.15) IDWARF=1
GOTO 71
60 IF(IDWARF.NE.1)GOTO 63
IF(RAN(QZ).GT.0.05) GOTO 71
IDWARF=2
DO 61 I=1,3
DLOC(I)=0
ODLOC(I)=0
61 DSEEN(I)=0
CALL SPEAK(3)
ICHAIN(AXE)=IOBJ(LOC)
IOBJ(LOC)=AXE
IPLACE(AXE)=LOC
GOTO 71

63 IDWARF=IDWARF+1
ATTACK=0
DTOT=0
STICK=0
DO 66 I=1,3
IF(2*I+IDWARF.LT.8)GOTO 66
IF(2*I+IDWARF.GT.23.AND.DSEEN(I).EQ.0)GOTO 66
ODLOC(I)=DLOC(I)
IF(DSEEN(I).NE.0.AND.LOC.GT.14)GOTO 65
DLOC(I)=DTRAV(I*2+IDWARF-8)
DSEEN(I)=0
IF(DLOC(I).NE.LOC.AND.ODLOC(I).NE.LOC) GOTO 66
65 DSEEN(I)=1
DLOC(I)=LOC
DTOT=DTOT+1
IF(ODLOC(I).NE.DLOC(I)) GOTO 66
ATTACK=ATTACK+1
IF(RAN(QZ).LT.0.1) STICK=STICK+1
66 CONTINUE
IF(DTOT.EQ.0) GOTO 71
IF(DTOT.EQ.1)GOTO 75
TYPE 67,DTOT
67 FORMAT(’ THERE ARE ‘,I2,’ THREATENING LITTLE DWARVES IN THE
1 ROOM WITH YOU.’,/)
GOTO 77
75 CALL SPEAK(4)
77 IF(ATTACK.EQ.0)GOTO 71
IF(ATTACK.EQ.1)GOTO 79
TYPE 78,ATTACK
78 FORMAT(’ ‘,I2,’ OF THEM THROW KNIVES AT YOU!’,/)
GOTO 81
79 CALL SPEAK(5)
CALL SPEAK(52+STICK)
GOTO(71,83)(STICK+1)

81 IF(STICK.EQ.0) GOTO 69
IF(STICK.EQ.1)GOTO 82
TYPE 68,STICK
68 FORMAT(’ ‘,I2,’ OF THEM GET YOU.’,/)
GOTO 83
82 CALL SPEAK(6)
83 PAUSE ‘GAMES OVER’3940
GOTO 71
69 CALL SPEAK(7)

C PLACE DESCRIPTOR

71 KK=STEXT(L)
IF(ABB(L).EQ.0.OR.KK.EQ.0)KK=LTEXT(L)
IF(KK.EQ.0) GOTO 7
4 TYPE 5,(LLINE(KK,JJ),JJ=3,LLINE(KK,2))
5 FORMAT(20A5)
KK=KK+1
IF(LLINE(KK-1,1).NE.0) GOTO 4
TYPE 6
6 FORMAT(/)
7 IF(COND(L).EQ.2)GOTO 8
IF(LOC.EQ.33.AND.RAN(QZ).LT.0.25)CALL SPEAK(8)
J=L
GOTO 2000

C GO GET A NEW LOCATION

8 KK=KEY(LOC)
IF(KK.EQ.0)GOTO 19
IF(K.EQ.57)GOTO 32
IF(K.EQ.67)GOTO 40
IF(K.EQ.8)GOTO 12
LOLD=L
9 LL=TRAVEL(KK)
IF(LL.LT.0) LL=-LL
IF(1.EQ.MOD(LL,1024))GOTO 10
IF(K.EQ.MOD(LL,1024))GOTO 10
IF(TRAVEL(KK).LT.0)GOTO 11
KK=KK+1
GOTO 9
12 TEMP=LOLD
LOLD=L
L=TEMP
GOTO 21
10 L=LL/1024
GOTO 21
11 JSPK=12
IF(K.GE.43.AND.K.LE.46)JSPK=9
IF(K.EQ.29.OR.K.EQ.30)JSPK=9
IF(K.EQ.7.OR.K.EQ.8.OR.K.EQ.36.OR.K.EQ.37.OR.K.EQ.68)
1 JSPK=10
IF(K.EQ.11.OR.K.EQ.19)JSPK=11
IF(JVERB.EQ.1)JSPK=59
IF(K.EQ.48)JSPK=42
IF(K.EQ.17)JSPK=80
CALL SPEAK(JSPK)
GOTO 2
19 CALL SPEAK(13)
L=LOC
IF(IFIRST.EQ.0) CALL SPEAK(14)
21 IF(L.LT.300)GOTO 2
IL=L-300+1
GOTO(22,23,24,25,26,31,27,28,29,30,33,34,36,37)IL
GOTO 2

22 L=6
IF(RAN(QZ).GT.0.5) L=5
GOTO 2
23 L=23
IF(PROP(GRATE).NE.0) L=9
GOTO 2
24 L=9
IF(PROP(GRATE).NE.0)L=8
GOTO 2
25 L=20
IF(IPLACE(NUGGET).NE.-1)L=15
GOTO 2
26 L=22
IF(IPLACE(NUGGET).NE.-1) L=14
GOTO 2
27 L=27
IF(PROP(12).EQ.0)L=31
GOTO 2
28 L=28
IF(PROP(SNAKE).EQ.0)L=32
GOTO 2
29 L=29
IF(PROP(SNAKE).EQ.0) L=32
GOTO 2
30 L=30
IF(PROP(SNAKE).EQ.0) L=32
GOTO 2
31 PAUSE ‘GAME IS OVER’
GOTO 1100
32 IF(IDETAL.LT.3)CALL SPEAK(15)
IDETAL=IDETAL+1
L=LOC
ABB(L)=0
GOTO 2
33 L=8
IF(PROP(GRATE).EQ.0) L=9
GOTO 2
34 IF(RAN(QZ).GT.0.2)GOTO 35
L=68
GOTO 2
35 L=65
38 CALL SPEAK(56)
GOTO 2
36 IF(RAN(QZ).GT.0.2)GOTO 35
L=39
IF(RAN(QZ).GT.0.5)L=70
GOTO 2
37 L=66
IF(RAN(QZ).GT.0.4)GOTO 38
L=71
IF(RAN(QZ).GT.0.25)L=72
GOTO 2
39 L=66
IF(RAN(QZ).GT.0.2)GOTO 38
L=77
GOTO 2
40 IF(LOC.LT.8)CALL SPEAK(57)
IF(LOC.GE.8)CALL SPEAK(58)
L=LOC
GOTO 2

C DO NEXT INPUT

2000 LTRUBL=0
LOC=J
ABB(J)=MOD((ABB(J)+1),5)
IDARK=0
IF(MOD(COND(J),2).EQ.1) GOTO 2003
IF((IPLACE(2).NE.J).AND.(IPLACE(2).NE.-1)) GOTO 2001
IF(PROP(2).EQ.1)GOTO 2003
2001 CALL SPEAK(16)
IDARK=1

2003 I=IOBJ(J)
2004 IF(I.EQ.0) GOTO 2011
IF(((I.EQ.6).OR.(I.EQ.9)).AND.(IPLACE(10).EQ.-1))GOTO 2008
ILK=I
IF(PROP(I).NE.0) ILK=I+100
KK=BTEXT(ILK)
IF(KK.EQ.0) GOTO 2008
2005 TYPE 2006,(LLINE(KK,JJ),JJ=3,LLINE(KK,2))
2006 FORMAT(20A5)
KK=KK+1
IF(LLINE(KK-1,1).NE.0) GOTO 2005
TYPE 2007
2007 FORMAT(/)
2008 I=ICHAIN(I)
GOTO 2004

C K=1 MEANS ANY INPUT

2012 A=B
JTWO=0
GOTO 2021

2010 JSPK=QUIP(K)
GOTO 5200

41422009 JSPK=54
5200 CALL SPEAK(JSPK)

2011 JVERB=0
JOBJ=0
JTWO=0

2020 CALL GETIN(JTWO,A,TWOWD,B)
K=70
IF(A.EQ.’ENTER’.AND.(B.EQ.’STREAM’.OR.B.EQ.’WATER’))GOTO 2010
IF(A.EQ.’ENTER’.AND.JTWO.NE.0)GOTO 2012
2021 IF(A.NE.’WEST’)GOTO 2023
IWEST=IWEST+1
IF(IWEST.NE.10)GOTO 202343
CALL SPEAK(17)
2023 DO 2024 I=1,1000
IF(KTAB(I).EQ.-1)GOTO 3000
IF(ATAB(I).EQ.A)GOTO 2025
2024 CONTINUE
PAUSE ‘ERROR 6’
2025 K=MOD(KTAB(I),1000)
KQ=KTAB(I)/1000+144
GOTO (5014,5000,2026,2010)KQ
PAUSE ‘NO NO’
2026 JVERB=K
JSPK=JSPKT(JVERB)
IF(JTWO.NE.0)GOTO 2028
IF(JOBJ.EQ.0)GOTO 2036
2027 GOTO(9000,5066,3000,5031,2009,5031,9404,9406,5081,5200,
1 5200,5300,5506,5502,5504,5505)JVERB
PAUSE ‘ERROR 5’

2028 A=TWOWD
B=’ ‘
JTWO=0
GOTO 2023

3000 JSPK=60
IF(RAN(QZ).GT.0.8)JSPK=61
IF(RAN(QZ).GT.0.8)JSPK=13
CALL SPEAK(JSPK)
LTRUBL=LTRUBL+1
IF(LTRUBL.NE.3)GOTO 2020
IF(J.NE.13.OR.IPLACE(7).NE.13.OR.IPLACE(5).NE.-1)GOTO 2032
CALL YES(18,19,54,YEA)
GOTO 2033
2032 IF(J.NE.19.OR.PROP(11).NE.0.OR.IPLACE(7).EQ.-1)GOTO 2034
CALL YES(20,21,54,YEA)
GOTO 2033
2034 IF(J.NE.8.OR.PROP(GRATE).NE.0)GOTO 2035
CALL YES(62,63,54,YEA)
2033 IF(YEA.EQ.0)GOTO 2011
GOTO 2020
2035 IF(IPLACE(5).NE.J.AND.IPLACE(5).NE.-1)GOTO 2020
IF(JOBJ.NE.5)GOTO 2020
CALL SPEAK(22)
GOTO 2020

2036 GOTO(2037,5062,5062,9403,2009,9403,9404,9406,5062,5062,
1 5200,5300,5062,5062,5062,5062)JVERB
PAUSE 45‘OOPS’46
203747 IF((IOBJ(J).EQ.0).OR.(ICHAIN(IOBJ(J)).NE.0)) GOTO 5062
DO 5312 I=1,3
IF(DSEEN(I).NE.0)GOTO 5062
5312 CONTINUE
JOBJ=IOBJ(J)
GOTO 2027
5062 IF(B.NE.’ ‘)GOTO 5333
TYPE 5063,A
5063 FORMAT(’ ‘,A5,’ WHAT?’,/)
GOTO 2020

5333 TYPE 5334,A,B
5334 FORMAT(’ ‘,2A5,’ WHAT?’,/)48
GOTO 2020
5014 IF(IDARK.EQ.0) GOTO 8

IF(RAN(QZ).GT.0.25) GOTO 8
5017 CALL SPEAK(23)
PAUSE ‘GAME IS OVER’
GOTO 2011

5000 JOBJ=K
IF(JTWO.NE.0)GOTO 2028
IF((J.EQ.IPLACE(K)).OR.(IPLACE(K).EQ.-1)) GOTO 5004
IF(K.NE.GRATE)GOTO 502
IF((J.EQ.1).OR.(J.EQ.4).OR.(J.EQ.7))GOTO 5098
IF((J.GT.9).AND.(J.LT.15))GOTO 5097
502 IF(B.NE.’ ‘)GOTO 5316
TYPE 5005,A
5005 FORMAT(’ I SEE NO ‘,A5,’ HERE.’,/)
GOTO 2011
5316 TYPE 5317,A,B
5317 FORMAT(’ I SEE NO ‘,2A5,’ HERE.’/)49
GOTO 2011
5098 K=49
GOTO 5014
5097 K=50
GOTO 5014
5004 JOBJ=K
IF(JVERB.NE.0)GOTO 2027

5064 IF(B.NE.’ ‘)GOTO 5314
TYPE 5001,A
5001 FORMAT(’ WHAT DO YOU WANT TO DO WITH THE ‘,A5,’?’,/)
GOTO 2020
5314 TYPE 5315,A,B
5315 FORMAT(’ WHAT DO YOU WANT TO DO WITH THE ‘,2A5,’?’,/)
GOTO 2020

C CARRY

9000 IF(JOBJ.EQ.18)GOTO 2009
IF(IPLACE(JOBJ).NE.J) GOTO 5200
9001 IF(IFIXED(JOBJ).EQ.0)GOTO 9002
CALL SPEAK(25)
GOTO 2011
9002 IF(JOBJ.NE.BIRD)GOTO 9004
IF(IPLACE(ROD).NE.-1)GOTO 9003
CALL SPEAK(26)
GOTO 2011
9003 IF((IPLACE(4).EQ.-1).OR.(IPLACE(4).EQ.J)) GOTO 9004
CALL SPEAK(27)
GOTO 2011
9004 IPLACE(JOBJ)=-1
9005 IF(IOBJ(J).NE.JOBJ) GOTO 9006
IOBJ(J)=ICHAIN(JOBJ)
GOTO 2009
9006 ITEMP=IOBJ(J)
9007 IF(ICHAIN(ITEMP).EQ.(JOBJ)) GOTO 9008
ITEMP=ICHAIN(ITEMP)
GOTO 9007
9008 ICHAIN(ITEMP)=ICHAIN(JOBJ)
GOTO 2009

C LOCK, UNLOCK, NO OBJECT YET

9403 IF((J.EQ.8).OR.(J.EQ.9))GOTO 5105
5032 CALL SPEAK(28)
GOTO 2011
5105 JOBJ=GRATE
GOTO 2027

C DISCARD OBJECT

5066 IF(JOBJ.EQ.18)GOTO 2009
IF(IPLACE(JOBJ).NE.-1) GOTO 5200
5012 IF((JOBJ.NE.BIRD).OR.(J.NE.19).OR.(PROP(11).EQ.1))GOTO 9401
CALL SPEAK(30)
PROP(11)=1
5160 ICHAIN(JOBJ)=IOBJ(J)
IOBJ(J)=JOBJ
IPLACE(JOBJ)=J
GOTO 2011

9401 CALL SPEAK(54)
GOTO 5160

C LOCK,UNLOCK OBJECT

5031 IF(IPLACE(KEYS).NE.-1.AND.IPLACE(KEYS).NE.J)GOTO 5200
IF(JOBJ.NE.4)GOTO 5102
CALL SPEAK(32)
GOTO 2011
5102 IF(JOBJ.NE.KEYS)GOTO 5104
CALL SPEAK(55)
GOTO 2011
5104 IF(JOBJ.EQ.GRATE)GOTO 5107
CALL SPEAK(33)
GOTO 2011
5107 IF(JVERB.EQ.4) GOTO 5033
IF(PROP(GRATE).NE.0)GOTO 5034
CALL SPEAK(34)
GOTO 2011
5034 CALL SPEAK(35)
PROP(GRATE)=0
PROP(8)=0
GOTO 2011
5033 IF(PROP(GRATE).EQ.0)GOTO 5109
CALL SPEAK(36)
GOTO 2011
5109 CALL SPEAK(37)
PROP(GRATE)=1
PROP(8)=1
GOTO 2011

C LIGHT LAMP

9404 IF((IPLACE(2).NE.J).AND.(IPLACE(2).NE.-1))GOTO 5200
PROP(2)=1
IDARK=050
CALL SPEAK(39)
GOTO 2011

C LAMP OFF

9406 IF((IPLACE(2).NE.J).AND.(IPLACE(2).NE.-1)) GOTO 5200
PROP(2)=0
CALL SPEAK(40)
GOTO 2011

C STRIKE

5081 IF(JOBJ.NE.12)GOTO 5200
PROP(12)=1
GOTO 2003

C ATTACK

5300 DO 5313 ID=1,3
IID=ID
IF(DSEEN(ID).NE.0)GOTO 5307
5313 CONTINUE
IF(JOBJ.EQ.0)GOTO 5062
IF(JOBJ.EQ.SNAKE) GOTO 5200
IF(JOBJ.EQ.BIRD) GOTO 5302
CALL SPEAK(44)
GOTO 2011
5302 CALL SPEAK(45)
IPLACE(JOBJ)=300
GOTO 9005

5307 IF(RAN(QZ).GT.0.4) GOTO 5309
DSEEN(IID)=0
ODLOC(IID)=0
DLOC(IID)=0
CALL SPEAK(47)
GOTO 5311
5309 CALL SPEAK(48)
5311 K=21
GOTO 5014

C EAT

5502 IF((IPLACE(FOOD).NE.J.AND.IPLACE(FOOD).NE.-1).OR.PROP(FOOD).NE.0
1 .OR.JOBJ.NE.FOOD)GOTO 5200
PROP(FOOD)=1
5501 JSPK=72
GOTO 5200

C DRINK

5504 IF((IPLACE(WATER).NE.J.AND.IPLACE(WATER).NE.-1)
1 .OR.PROP(WATER).NE.0.OR.JOBJ.NE.WATER) GOTO 520051
PROP(WATER)=1
JSPK=74
GOTO 5200

C RUB

5505 IF(JOBJ.NE.LAMP)JSPK=76
GOTO 5200

C POUR

5506 IF(JOBJ.NE.WATER)JSPK=78
PROP(WATER)=1
GOTO 5200

END

SUBROUTINE SPEAK52(IT)53
IMPLICIT INTEGER(A-Z)
COMMON RTEXT,LLINE
DIMENSION RTEXT(100),LLINE(1000,22)

KKT=RTEXT(IT)
IF(KKT.EQ.0)RETURN
999 TYPE 998, (LLINE(KKT,JJT),JJT=3,LLINE(KKT,2))
998 FORMAT(20A5)
KKT=KKT+1
IF(LLINE(KKT-1,1).NE.0)GOTO 999
997 TYPE 996
996 FORMAT(/)54
RETURN
END

SUBROUTINE GETIN(TWOW,B,C,D)55
IMPLICIT INTEGER(A-Z)
DIMENSION A(5),M2(6)
DATA M2/”4000000000,”20000000,”100000,”400,”2,0/
6 ACCEPT56 1,(A(I), I=1,4)
1 FORMAT(4A5)
TWOW=057
S=0
B=A(1)
DO 2 J=1,4
DO 2 K=1,5
MASK1=”774000000000
IF(K.NE.1) MASK1=”177*M2(K)
IF(((A(J).XOR.”201004020100).AND.MASK1).EQ.0)GOTO 3
IF(S.EQ.0) GOTO 2
TWOW=1
CALL SHIFT(A(J),7*(K-1),XX)
CALL SHIFT(A(J+1),7*(I-6),YY)
MASK=-M2(6-K)58
C=(XX.AND.MASK)+(YY.AND.(-2-MASK))
GOTO 4
3 IF(S.EQ.1) GOTO 2
S=1
IF(J.EQ.1) B=(B.AND.-M2(K)).OR.(“201004020100.AND.
1 (-M2(K).XOR.-1))
2 CONTINUE
4 D=A(2)
RETURN
END

SUBROUTINE YES(X,Y,Z,Y EA)
IMPLICIT INTEGER(A-Z)
CALL SPEAK(X)
CALL GETIN(JUNK,IA1,JUNK,IB1)59
IF(IA1.EQ.’NO’.OR.IA1.EQ.’N’) GOTO 1
YEA=160
IF(Y.NE.0) CALL SPEAK(Y)
RETURN
1 YEA=0
IF(Z.NE.0)CALL SPEAK(Z)61
RETURN
END

notes

1Static page? Google’s “Edit this page” button is way at the bottom. -DGJ

2Code starts here. Note the plural title. In the data file, Table 6, item 65 reads “WELCOME TO ADVENTURE!!” -DGJ

So the readers of the code get to go on adventures, while the players participate in the overall adventure. - MCM

3This line tells the computer that any variable with the name A-Z will be an integer. (Saves the trouble of declaring each variable individually.)To declare a variable is simply to name a blank space in memory

4Note that if not specified, I ,J,K,L,M,& N default to integer for array indexes and all other single letters are reals - RJP

5Declares a variable RAN that will hold a random real number (can be a whole number or a decimal).Will be used later to determine the likelihood of certain random events. (This is the internal die-rolling.) -DGJ

6A lot of the weird logic associated with text in that program is
trying to work with the way strings are stored. A string is an
array of 36-bit integers, each integer holding 5 characters. If
the string isn’t a multiple of 5 characters in length, spaces are
added to the end. All of the long text strings are stored in a
single two-dimensional array called LLINE. The first two integers
in each LLINE string aren’t holding characters; they store an
indication of whether this string is part of a larger paragraph
(LLINE(n,1)), and how long the string is in integers (LLINE(n,2)),
respectively. The actual text for string LLINE(n) starts at
LLINE(n,3).
-From Bruce Stephens’s post on the Google discussion group

7Actually, the problem is not the compiler, it’s the machine. As any machine language programmer knows, you don’t need a character type to manipulate characters -you just need a character-sized unit of storage. The PDP-10 didn’t have one, because it used word addressing.

Word-addressable systems force the programmer to deal with data in a unit (the machine word) that is convenient for the computer as opposed to those that are appropriate for the application. The PDP-10 was a “scientific” computer, so it had a large word size, the better to manipulate large numbers. Crowther and Woods would have been better off with a “business” system, which would have had 8- or 16-bit words, making it unnecessary to pack characters. But then they would have had to write Adventure in COBOL!
-From fm6’s commentary on the Slashdot discussion

8spaghetti GOTO maze which, although messy, was probably the only way to do things in FORTRAN at the time with no structuring capability.

A random example:

IF(K.NE.1) MASK1=”177*M2(K)
IF(((A(J).XOR.”201004020100).AND.MASK1).EQ.0)GOTO 3
IF(S.EQ.0) GOTO 2

That’s not lack of structure, its how text strings were handled before Fortran had character variables. In FORTRAN IV, characters get stuffed into real or integer variables and you have to play games with bit masks and such. The ” prefix indicates an OCTAL literal.
-From Biogobonics’s commentary on Slashdot

9So maybe the inspiration for the “maze of twisty little passages, all alike” wasn’t Mammoth Cave, it was the code itself.
-From Sigmus’s commentary on the Slashdot discussion

10Yeah, Perl has gotos (computed and otherwise) but it also has block structure. Which is why few Perl programmers ever have occasion to write a goto. (I don’t think I ever have.) Perl’s readability problems are exactly the opposite of FORTRAN’s. Where FORTRAN’s designers knew too little about artificial language theory, Perl’s designers know way too much! Indeed, Larry Wall started out as a linguist, and can’t seem to stop dreaming up clever language constructs. The result is a language that has a nasty tendency to bring out the poet in the programmer. Why is that a bad thing? Because, as any English 101 student will tell you, reading poetry is hard work.
-From fm6’s commentary on the Slashdot discussion

11This command indicates that what follows will be named blank lists of numbers, to be populated by the information in the data file.

12This syntax denotes a continuation of the previous line; the next few lines continue to set up blank lists of numbers, to be filled in by values read in from the tables in the data file. -DGJ

13Dar be mo’ go-to’s here dan ho’s on Easy Skreet.

14It’s interesting that one of the first comments in a text adventure, where interactors routinely attempt to command the system, the comment takes the form of a command (>READ PARAMETERS as in >GO EAST), instead of addressing the programmer or offering some first person comment, as in the ClimateGate comments.

15The variable SETUP, which will be set to 1 in the next line, is here checked.”If the variable SETUP is not equal to 0, go to the line marked with the label 1.”

My understanding of FORTAN 77 is that this behavior is handled by the block data statement (a special structure that looks like a subroutine, and can be in any place in the code, but which is run first, and run only once, specifically to load the variables with their startup values). The code that Crowther wrote here leads to that behavior.

16Required to get past the grate. -DGJ

17These are not the only objects in the game; these are constants set up for the convenience of the programmer. -DGJ

Any thoughts on why these object constants, as opposed to any others? Even though this doesn’t change the function, what kind of selective attention does it indicate? My first guesses would be that constants are defined for: the most important objects, and/or the most frequently recurring in code objects, and/or and first objects (the ones initially programmed). So perhaps constants were set up during initial programming, but then not continually added to, or else were only added as objects become referred to widely in the code and thus inconvenient to numerically memorize. Looking at the list of IDs, it seems like the big gap is objects 12-18. - JHD

These are all objects that require special treatment; their behavior is specialized, so they require special code.Using the constant KEYS makes the passage dealing with the keys more legible. (In this document, we can search for KEYS and find specific references to that object.)I’ll add separate notes to each item. -DGJ

Some of the objects are referred to by both name and by the integer assigned.Perhaps this suggests that the constant names were added later as the list of objects grew and it became too difficult to remember the numeric codes.(Didn’t Shakespeare on occasion lose track of some of his minor characters in some of his hastily composed scripts?)I wonder if, during development, there was a separate list of object numbers, on paper or in a separate file.I remember having to maintain such an external list when the length of variable names had to be kept to a minimum because of memory constraints.I remember many early microcomputer programmers w/o a printer composing/keeping their code handwritten in spiral notebooks, etc. - JN

18Required to proceed past the onset of darkness. -DGJ

19Must be open in order to pass through it. -DGJ

20Has two key effects. It scares the bird, which prevents your ability to pick it up.You also need it to trigger the bridge across the chasm. This is a more complex item than the others, and only affects the player’s navigation indirectly, so perhaps this is worth more study. -DGJ

I believe you note its transition to a Wand in the next version.If so, what changes? What does that change do? -MCM

21Another item that indirectly affects the player’s navigation. The bird reacts to the rod and the bird. (Later, Woods will add a reaction to the dragon.) -DGJ

22See Table 1, item 18: “YOU WON’T GET IT UP THE STEPS”. -DGJ

23Prevents the player’s passage, and also interacts with the bird. -DGJ

24These objects seem to exist only be consumed by the verbs “eat” and “drink.”Woods would later create puzzles that used these objects. -DGJ

25In the variable named QUIP, place at positions 1 through 9 the following list of numbers. If I’m reading this right, the QUIP is a textual response (such as the display of a help message) to a command (such as “HELP”) that otherwise doesn’t affect the game world. These are items selected from Table 6. -DGJ

26As we’ve already discussed during our CCS event, analyzing the significance of a variable name is low-hanging fruit. Crowther chose this sequence of letters, but it’s not clear (to me) why. At any rate, JSPKT is filled with the specified lines (some of them duplicates) from Table 6.-DGJ

27Hey, this is strange.I can’t find IFILE in the variables, arrays, functions, or FORTRAN77 specification.Hmm.-MCM

28Aha! Just found this fellow, Andrew retro98se@gmail.com who has tried to implement Jerz’s code and has had to write a new function for IFILE to make it operate. What does that say about this version of the source code….See his patch here:
http://www.asun.net/pdp10/downloads/build-adv0.txt -MCM

But wait, some one else has tried this work around by actually going in and changing the invalid (for FORTRAN 77) or undefined IFILE function to the OPEN function.Two patches with different approaches, interesting. -MCM

This is a function that reads in a file. If I understand this correctly, different machines handled this function different ways, even though otherwise they could handle the same FORTRAN code. Crowther may have been using a library of input/output file routines that he had written for his specific environment. -DGJ

29Ah, GOTO. I don’t really see that as much in code from the last two decades. That kind of headlong execution reminds me of things like print gamebooks, which ran their own simulations on a web of statements like GO TO PAGE 13. - JHD

30Yes, FORTRAN is probably the reason why modern programmers abhor the GOTO statement.Can we usefully discuss the branching code(x)? (As a true humanist, I can hardly miss the opportunity to make a pun that enforces a meme complex, even though it otherwise has little bearing on the immediate argument.) -DGJ

31An example of FORTRAN’s “Computed GOTO,” which provided functionality similar to that of a “case” or “switch” in later languages.Here, the value of IKIND+1 determines which of the line numbers is used. -anonymous

32Brrrr.

…these blocks of GOTO statements are really making me want to use code visualization to “read” this code by visually tracing the jumps in executation logic. Of course, Ben Fry already did this in his “distellamap” rendering of Adventure - it was just a very, very different version of Adventure.http://benfry.com/distellamap/

The distellamaps are beautiful, but I’m having a hard time “reading” them as legible data visualizations. I’m thinking what Christian Swinehart did with some Choose Your Own Adventure books might be more critically useful. -MLS
http://samizdat.cc/cyoa/

Yes, I was thinking that some sort of visual trip through the code

33I have dreams of constructing an interactive variorium of Adventure, with text printing out in different colors based on what version you’re playing, etc. -DGJ

I stopped having dreams after that one dude got shot for it.

34If I read this right, “KEYWORD” is a motion word, from table 4 (in the data file).

Most modern text games navigate primarily by compass directions, but Crowther’s game encouraged people to navigate by typing nearby objects (more like what would eventually become the standard for navigation in MOOs). -DGJ

35This line and the one above it are pseudocode comments (marked at the beginning with “C “, compare the title line). I just deduced this - in the versions of FORTAN I’m familiar with (and the cheat sheets I’ve been able to find) the hash marker is used to comment out lines. At any rate, “DON T ASK QUESTION” is missing the apostrophe because it might interfere with the compiler, I’m guessing…? - JHD

Would an apostrophe cause an error in a comment line, though? It certainly would in the later line 83 where “GAMES OVER” is used instead of “GAME’S OVER” - and “GAME IS OVER” is used after that. - JN

36The “C” denotes “Comment.” -DGJ

Just as “CF” denotes “Cluster Fuck”.

37Program starts here, by calling the “YES” subroutine. (The code for that subroutine is near the end of the program).

Here, the YES subroutine is being called with four parameters, which tell the computer what to do if the answer is yes or no.

38Is this a D&D Dwarf?or a Tolkein-esque Dwarf?What do we see hee that speaks to those models? -MCM

39Apparently a typo for “GAME’S OVER”?Has anyone done scholarship on the origin of the iconic phrase “GAME OVER”? -DGJ

40The term “GAME OVER” originated with Pinball machines: http://www.statemaster.com/encyclopedia/Game-over
-MMF

41Note that the labels 2010 and 2009 are out of order. The labels are simply a convenience for the programmer, marking the targest of the GOTO statements - they do not indicate the order of execution. -DGJ

42Dennis, how does this speak to the order in which this code was likely composed?Where do we take that information?

43Curious that 2022 is missing. Also considering the above labels (2009 and 2010) that appear out of order, it seems like Crowther’s approach was rather haphazard at times.
-MMF

44Ah, the old computed GOTO. In the first line, the value of KQ is used as an index to the list of labels. If KQ=1, GOTO 5014, if KQ=2, GOTO 5000, etc. etc. If KQ is outside the range (0 or greater than 4), then no GOTO is performed, so you’d hit the PAUSE statement. Looks like it’s essentially saying “this shouldn’t happen”.

2027 is similar, there’s just a lot more possible values. That rogue 1 is a continuation indicator, it would have been in column 6 on your punch card.
-From LMacG’s commentary in the Slashdot discussion

45This is my version of the “low lying fruit.”PAUSE ‘OOPS’ prints the message (and hangs the program till input?), but I can’t help but also see how these words could also be performed, the ELIZA effect of the code.

-Similar would be the PAUSE after 1022 CONTINUE.”CONTINUE/PAUSE”Documentation suggests CONTINUE was a functionless formal convention to round out a DO statement.So the meaningless continue, the pause the causes speech. -MCM

46Line 2036 is supposed to send the program to one of the listed labels, depending on the value of JVERB. If I’m reading this right, if JVERB is 1, the program will jump to line 2037.Maybe the first position in this list corresponds to 0… I’d need to look it up. But at any rate, the program should never execute the line after 2036. This is a bug-check, designed to signal the programmer that line 2037 is being executed not because the GOTO statement called it according to the value of JVERB, but simply because the computer is running whatever line comes after the unsuccessful GOTO statement. -DGJ

47Okay, so the numbering is 2037 followed by 5312.Jeremy was commenting about the relationship of these numbers to the code.I’ll let him expand, but these are numbers stripped of their counting in some ways -MCM

That’s right, in FORTRAN code is executed in sequence, and the only reason to label a code (with a number) is if you need to name a target for a GOTO.Line 2036 offers a table of contents of sorts, with a list of numbers that seem to correspond to different verbs (as indexed by the JVERB variable). As you can see, that list is sorted numerically. -DGJ

48The player has typed a transitive verb, such as “DROP”, without supplying an object. Since 5062 checks for the presence of a space character, I gather that section catches the special case where the player has typed “DROP ” - with a final space that may otherwise fool the parser into expecting a second word. -DGJ

49Lines 5005 and 5317 seem to address what happens when the player types a verb the game recognizes, but a noun the game does not.

50I think it’s great here that the essence of the “light lamp” function is to set IDARK, or darkness, to zero. This code-induced relationship between light and dark goes unnoticed to the end-user, and is only accessible to programmers (and CCS-ers).
-MMF

51The signs here are fascinating. First because the evaluators, NE, look like compass points, in a piece of code that engages place or iPlaces and water, or the value of water. (evocative)-MCM

NE here represents the “is not equal to” operator. -DGJ

52In another context, Sherry Turkle named the ELIZA effect for to describe the interactor’s tendency to suture together a person out of the diverse responses.Speak is not a standard FORTRAN instruction, right.If not, by creating the “Speak” subroutine, the code itself seems to be making a direct gesture toward personification in the context of a dialogue. -MCM

Yes, it would seem that SPEAK and QUIP are labels that Crowhter chose to describe actions that are central to a generation’s experience of computer-mediated stories. -DGJ

53Prints out the text message (from Table 6) with the number IT.If there is more than one line of text with that number, each line is printed in order. -DGJ

54Interesting that again we see numbers appearing in strange sequences, this time in reverse order.
-MMF

55This subroutine sets input from the keyboard, determines whether the player has typed one or two words.As I understand it, the FORTRAN Crowther used did not have a dedicated data type for alphanumeric characters. ADVENT recognizes two-word commands, and ignores all but the first five characters in each word. -DGJ

56“ACCEPT” tells the computer to start recording the user’s input. Here, four spaces in the variable A are filled with input from the keyboard. (But Table 4’s list of keywords are up to five letters long, so perhaps I am reading this wrong. This note is not a matter of critical code interpretation, it’s a simple matter of FORTRAN literacy.) At any rate, the user typed in put comes in through this statement. -DGJ

57I gather this means “two words,” but “word” has a specific meaning within computer programming, referring to memory allocation for the storage of numbers. I *want* to read this passage as performing a test on the player’s textual input, determining whether it includes a space, and if so, splitting the player’s first typed word into B, and the player’s second word into D. -DGJ

58[Code can be] grossly messy because PDP-10 Fortran didn’t have a CHARACTER type - instead, you could pack 5 characters to a 36-bit integer, with the low-bit unused. The M2 array contained integer masks with one bit set, the low bit of one of the characters. Multiplying that mask by octal 177 got you a mask which selected a single character, except for the first character where the multiplication would overflow. The octal constant 201004020100 is 5 space characters. The “S” flag indicated whether a space had been found yet.
-From David Librik’s post on the Slashdot discussion

59Apparently the spaces occupied by the parameter “JUNK” aren’t important in this case.This routine accepts player input, and prints message Y if the player type something other than “NO” or “N,” and prints out message Z if the player did type “NO” or “N”.

60Note that in fortran, a variable passed to a subroutine can change the value in the calling code - extra confusion

61the

Data File

DATA FILE.1
12
1 YOU ARE STANDING AT THE END OF A ROAD BEFORE A SMALL BRICK
1 BUILDING 3. AROUND YOU IS A FOREST. A SMALL
1 STREAM FLOWS OUT OF THE BUILDING AND DOWN A GULLY.
2 YOU HAVE WALKED UP A HILL, STILL IN THE FOREST4
2 THE ROAD NOW SLOPES BACK DOWN THE OTHER SIDE OF THE HILL.
2 THERE IS A BUILDING IN THE DISTANCE.
3 YOU ARE INSIDE A BUILDING, A WELL HOUSE FOR A LARGE SPRING.
4 YOU ARE IN A VALLEY IN THE FOREST BESIDE A STREAM TUMBLING
4 ALONG A ROCKY BED.
5 YOU ARE IN OPEN FOREST, WITH A DEEP VALLEY TO ONE SIDE.
6 YOU ARE IN OPEN FOREST NEAR BOTH A VALLEY AND A ROAD.
7 AT YOUR FEET ALL THE WATER OF THE STREAM SPLASHES INTO A
7 2 INCH SLIT IN THE ROCK. DOWNS5TREAM THE STREAMBED IS BARE ROCK.
8 YOU ARE IN A 20 FOOT DEPRESSION FLOORED WITH BARE DIRT. SET INTO
8 THE DIRT IS A STRONG STEEL GRATE MOUNTED IN CONCRETE. A DRY
8 STREAMBED LEADS INTO THE DEPRESSION.
9 YOU ARE IN A SMALL CHAMBER BENEATH A 3X3 STEEL GRATE TO THE
9 SURFACE. A LOW CRAWL OVER COBBLES LEADS INWARD TO THE WEST.
10 YOU ARE CRAWLING OVER COBBLES IN A LOW PASSAGE. THERE IS A
10 DIM LIGHT AT THE EAST END OF THE PASSAGE.
11 YOU ARE IN A DEBRIS ROOM, FILLED WITH STUFF WASHED IN FROM
11 THE SURFACE. A LOW WIDE PASSAGE WITH COBBLES BECOMES
11 PLUGGED WITH MUD AND DEBRIS HERE,BUT AN AWKWARD CANYON
11 LEADS UPWARD AND WEST.
11 A NOTE ON THE WALL SAYS ‘MAGIC WORD XYZZY’.
12 YOU ARE IN AN AWKWARD SLOPING EAST/WEST CANYON.
13 YOU ARE IN A SPLENDID CHAMBER THIRTY FEET HIGH. THE WALLS
13 ARE FROZEN RIVERS OF ORANGE STONE. AN AWKWARD CANYON AND A
13 GOOD PASSAGE EXIT FROM EAST AND WEST SIDES OF THE CHAMBER.
14 AT YOUR FEET IS A SMALL PIT BREATHING TRACES OF WHITE MIST. AN
14 EAST PASSAGE ENDS HERE EXCEPT FOR A SMALL CRACK LEADING ON.
15 YOU ARE AT ONE END OF A VAST HALL STRETCHING FORWARD OUT OF
15 SIGHT TO THE WEST. THERE ARE OPENINGS TO EITHER SIDE. NEARBY, A WIDE
15 STONE STAIRCASE LEADS DOWNWARD. THE HALL IS FILLED WITH
15 WISPS OF WHITE MIST SWAYING TO AND FRO ALMOST AS IF ALIVE.
15 A COLD WIND BLOWS UP THE STAIRCASE. THERE IS A PASSAGE
15 AT THE TOP OF A DOME BEHIND YOU.
16 THE CRACK IS FAR TOO SMALL FOR YOU TO FOLLOW.
17 YOU ARE ON THE EAST BANK OF A FISSURE SLICING CLEAR ACROSS
17 THE HALL. THE MIST IS QUITE THICK HERE, AND THE FISSURE IS
17 TOO WIDE TO JUMP.
18 THIS IS A LOW ROOM WITH A CRUDE NOTE ON THE WALL.
18 IT SAYS ‘YOU WON’T GET IT UP THE STEPS’.
19 YOU ARE IN THE HALL OF THE MOUNTAIN KING6, WITH PASSAGES
19 OFF IN ALL DIRECTIONS.
20 YOU ARE AT THE BOTTOM OF THE PIT WITH A BROKEN NECK.
21 YOU DIDN’T MAKE IT
22 THE DOME IS UNCLIMBABLE
23 YOU CAN’T GO IN THROUGH A LOCKED STEEL GRATE!
24 YOU DON’T FIT DOWN A TWO INCH HOLE!
25 YOU CAN’T GO THROUGH A LOCKED STEEL GRATE.
727 YOU ARE ON THE WEST SIDE OF THE FISSURE IN THE HALL OF MISTS.
28 YOU ARE IN A LOW N/S PASSAGE AT A HOLE IN THE FLOOR.
28 THE HOLE GOES DOWN TO AN E/W PASSAGE.
29 YOU ARE IN THE SOUTH SIDE CHAMBER.
30 YOU ARE IN THE WEST SIDE CHAMBER OF HALL OF MT KING.
30 A PASSAGE CONTINUES WEST AND UP HERE.

31 THERE IS NO WAY ACROSS THE FISSURE.
32 YOU CAN’T GET BY THE SNAKE
33 YOU ARE IN A LARGE ROOM, WITH A PASSAGE TO THE SOUTH,
33 A PASSAGE TO THE WEST, AND A WALL OF BROKEN ROCK TO
33 THE EAST. THERE IS A LARGE ‘Y2’ ON A ROCK IN ROOMS CENTER.
34 YOU ARE IN A JUMBLE OF ROCK, WITH CRACKS EVERYWHERE.
35 YOU ARE AT A WINDOW ON A HUGE PIT, WHICH GOES UP AND
35 DOWN OUT OF SIGHT. A FLOOR IS INDISTINCTLY VISIBLE
35 OVER 50 FEET BELOW. DIRECTLY OPPOSITE YOU AND 25 FEET AWAY
35 THERE IS A SIMILAR WINDOW.
36 YOU ARE IN A DIRTY BROKEN PASSAGE. TO THE EAST IS A CRAWL.
36 TO THE WEST IS A LARGE PASSAGE. ABOVE YOU IS A HOLE TO
36 ANOTHER PASSAGE.
37 YOU ARE ON THE BRINK OF A SMALL CLEAN CLIMBABLE PIT.
37 A CRAWL LEADS WEST.
38 YOU ARE IN THE BOTTOM OF A SMALL PIT WITH A LITTLE
38 STREAM, WHICH ENTERS AND EXITS THROUGH TINY SLITS.
39 YOU ARE IN A LARGE ROOM FULL OF DUSTY ROCKS. THERE IS A
39 BIG HOLE IN THE FLOOR. THERE ARE CRACKS EVERYWHERE, AND
39 A PASSAGE LEADING EAST.
40 YOU HAVE CRAWLED THROUGH A VERY LOW WIDE PASSAGE PARALLEL
40 TO AND NORTH OF THE HALL OF MISTS.
41 YOU ARE AT THE WEST END OF HALL OF MISTS. A LOW WIDE CRAWL
41 CONTINUES WEST AND ANOTHER GOES NORTH. TO THE SOUTH IS A
41 LITTLE PASSAGE 6 FEET OFF THE FLOOR.
42 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.89
43 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
44 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
45 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
46 DEAD END
47 DEAD END
48 DEAD END
49 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
50 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
51 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
52 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
53 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
54 DEAD END
55 YOU ARE IN A MAZE OF TWISTY LITTLE PASSAGES, ALL ALIKE.
56 DEAD END
57 YOU ARE ON THE BRINK OF A THIRTY FOOT PIT WITH A MASSIVE
57 ORANGE COLUMN DOWN ONE WALL. YOU COULD CLIMB DOWN HERE
57 BUT YOU COULD NOT GET BACK UP. THE MAZE CONTINUES AT THIS
57 LEVEL.
58 DEAD END
59 YOU HAVE CRAWLED THROUGH A VERY LOW WIDE PASSAGE PARALLEL
59 TO AND NORTH OF THE HALL OF MISTS.
60 YOU ARE AT THE EAST END OF A VERY LONG HALL APPARENTLY
60 WITHOUT SIDE CHAMBERS. TO THE EAST A LOW WIDE CRAWL SLANTS
60 UP. TO THE NORTH A ROUND TWO FOOT HOLE SLANTS DOWN.
61 YOU ARE AT THE WEST END OF A VERY LONG FEATURELESS HALL.
62 YOU ARE AT A CROSSOVER OF A HIGH N/S PASSAGE AND A LOW E/W ONE.
63 DEAD END
64 YOU ARE AT A COMPLEX JUNCTION. A LOW HANDS AND KNEES
64 PASSAGE FROM THE NORTH JOINS A HIGHER CRAWL
64 FROM THE EAST TO MAKE A WALKING PASSAGE GOING WEST
64 THERE IS ALSO A LARGE ROOM ABOVE. THE AIR IS DAMP HERE.
64 A SIGN IN MIDAIR HERE SAYS ‘CAVE UNDER CONSTRUCTION BEYOND
64 THIS POINT. PROCEED AT OWN RISK.’10
65 YOU ARE IN BEDQUILT, A LONG EAST/WEST PASSAGE WITH HOLES EVERYWHERE.
65 TO EXPLORE AT RANDOM SELECT NORTH, SOUTH, UP, OR DOWN.
66 YOU ARE IN A ROOM WHOSE WALLS RESEMBLE SWISS CHEESE.
66 OBVIOUS PASSAGES GO WEST,EAST,NE, AND
66 NW. PART OF THE ROOM IS OCCUPIED BY A LARGE BEDROCK BLOCK.
67 YOU ARE IN THE TWOPIT ROOM. THE FLOOR
67 HERE IS LITTERED WITH THIN ROCK SLABS, WHICH MAKE IT
67 EASY TO DESCEND THE PITS. THERE IS A PATH HERE BYPASSING
67 THE PITS TO CONNECT PASSAGES FROM EAST AND WEST.THERE
67 ARE HOLES ALL OVER, BUT THE ONLY BIG ONE IS ON THE WALL
67 DIRECTLY OVER THE EAST PIT WHERE YOU CAN’T GET TO IT.
68 YOU ARE IN A LARGE LOW CIRCULAR CHAMBER WHOSE FLOOR IS AN
68 IMMENSE SLAB FALLEN FROM THE CEILING(SLAB ROOM). EAST AND
68 WEST THERE ONCE WERE LARGE PASSAGES, BUT THEY ARE NOW FILLED
68 WITH BOULDERS. LOW SMALL PASSAGES GO NORTH AND SOUTH, AND THE
68 SOUTH ONE QUICKLY BENDS WEST AROUND THE BOULDERS.
69 YOU ARE IN A SECRET NS CANYON ABOVE A LARGE ROOM.
70 YOU ARE IN A SECRET N/S CANYON ABOVE A SIZABLE PASSAGE.
71 YOU ARE IN SECRET CANYON AT A JUNCTION OF THREE CANYONS,
71 BEARING NORTH, SOUTH, AND SE. THE NORTH ONE IS AS TALL
71 AS THE OTHER TWO COMBINED.
72 YOU ARE IN A LARGE LOW ROOM. CRAWLS LEAD N, SE, AND SW.
73 DEAD END CRAWL.
74 YOU ARE IN SECRET CANYON WHICH HERE RUNS E/W. IT CROSSES OVER
74 A VERY TIGHT CANYON 15 FEET BELOW. IF YOU GO DOWN YOU MAY
74 NOT BE ABLE TO GET BACK UP
75 YOU ARE AT A WIDE PLACE IN A VERY TIGHT N/S CANYON.
76 THE CANYON HERE BECOMES TO TIGHT TO GO FURTHER SOUTH.
77 YOU ARE IN A TALL E/W CANYON. A LOW TIGHT CRAWL GOES 3 FEET
77 NORTH AND SEEMS TO OPEN UP.
78 THE CANYON RUNS INTO A MASS OF BOULDERS - DEAD END.
79 THE STREAM FLOWS OUT THROUGH A PAIR OF 1 FOOT DIAMETER SEWER
79 PIPES. IT WOULD BE ADVISABLE TO USE THE DOOR.
-1 END
211
1 YOU’RE AT END OF ROAD AGAIN.
2 YOU’RE AT HILL IN ROAD.
3 YOU’RE INSIDE BUILDING.
4 YOU’RE IN VALLEY
5 YOU’RE IN FOREST
6 YOU’RE IN FOREST
7 YOU’RE AT SLIT IN STREAMBED
8 YOU’RE OUTSIDE GRATE
9 YOU’RE BELOW THE GRATE
10 YOU’RE IN COBBLE CRAWL
11 YOU’RE IN DEBRIS ROOM.
13 YOU’RE IN BIRD CHAMBER.
14 YOU’RE AT TOP OF SMALL PIT.
15 YOU’RE IN HALL OF MISTS.
17 YOU’RE ON EAST BANK OF FISSURE.
18 YOU’RE IN NUGGET OF GOLD ROOM.
19 YOU’RE IN HALL OF MT KING.
33 YOU’RE AT Y2
35 YOU’RE AT WINDOW ON PIT
36 YOU’RE IN DIRTY PASSAGE
39 YOU’RE N DUSTY ROCK ROOM.
41 YOU’RE AT WEST END OF HALL OF MISTS.
57 YOU’RE AT BRINK OF PIT.
60 YOU’RE AT EAST END OF LONG HALL.
66 YOU’RE IN SWISS CHEESE ROOM
67 YOU’RE IN TWOPIT ROOM
68 YOU’RE IN SLAB ROOM
-1
312
1 2 2 44
1 3 3 12 19 43
1 4 4 5 13 14 46 30
1 5 6 45 43
1 8 49
2 1 8 2 12 7 43 45 30
2 5 6 45 46
3 1 3 11 32 44
3 11 48
3 33 65
3 79 5 14
4 1 4 45
4 5 6 43 44 29
4 7 5 46 30
4 8 49
5 4 9 43 30
5 300 6 7 8 45
5 5 44 46
6 1 2 45
6 4 9 43 44 30
6 5 6 46
7 1 12
7 4 4 45
7 5 6 43 44
7 8 5 15 16 46 30
7 24 47 14 30
8 5 6 43 44 46
8 1 12
8 7 4 13 45
8 301 3 5 19 30
9 302 11 12
9 10 17 18 19 44
9 14 31
9 11 51
10 9 11 20 21 43
10 11 19 22 44 51
10 14 31
11 310 49
11 10 17 18 23 24 43
11 12 25 305 19 29 44
11 3 48
11 14 31
12 310 49
12 11 30 43 51
12 13 19 29 44
12 14 31
13 310 49
13 11 51
13 12 25 305 43
13 14 23 31 44
14 310 49
14 11 51
14 13 23 43
14 303 30 31 34
14 16 33 44
15 18 36 46
15 17 7 38 44
15 19 10 30 45
15 304 29 31 34 35 23 43
15 34 55
15 62 69
16 14 1
17 15 8 38 43
17 305 7
17 306 40 41 42 44 19 39
18 15 38 11 8 45
19 15 10 29 43
19 307 45 36
19 308 46 37
19 309 44 7
19 74 66
20 26 1
21 26 1
22 15 1
23 8 1
24 7 1
25 9 1
27 17 8 11 38
27 40 45
27 41 44
28 19 38 11 46
28 33 45
28 36 30 52
29 19 38 11 45
30 19 38 11 43
30 62 44 29
31 17 1
32 19 1
33 3 65
33 28 46
33 34 43 53 54
33 35 44
34 33 30
34 15 29
35 33 43 55
36 37 43 17
36 28 29 52
36 39 44
37 36 44 17
37 38 30 31 56
38 37 56 29
39 36 43
39 64 30 52 58
39 65 70
40 41 1
41 42 46 29 23 56
41 27 43
41 59 45
41 60 44 17
42 41 44
42 43 43
42 44 46
43 42 44
43 44 46
43 45 43
44 42 45
44 43 43
44 48 30
44 50 46
45 43 45
45 46 43
45 47 46
46 45 44 11
47 45 45 11
48 44 29 11
49 50 30 43
49 51 44
50 44 43
50 49 44 29
50 52 46
51 49 44
51 52 43
51 53 46
52 50 45
52 51 44
52 53 29
52 55 43
53 51 44
53 52 45
53 54 46
54 53 43 11
55 52 44
55 56 30
55 57 43
56 55 29 11
57 55 44
57 58 46
57 13 30 56
58 57 44 11
59 27 1
60 41 43 29
60 61 44
60 62 45 30
61 60 43 11
62 60 44
62 63 45
62 30 43
62 15 46
63 62 46 11
64 39 29 56 59
64 65 44
65 64 43
65 66 44
65 68 61
65 311 46
65 312 29
66 313 45
66 65 60
66 67 44
66 77 25
66 314 46
67 66 43
67 72 60
68 66 46
68 69 29
69 68 30
69 74 46
70 71 45
71 39 29
71 65 62
71 70 46
72 67 63
72 73 45
73 72 46
74 19 43
74 69 44
74 75 30
75 76 46
75 77 45
76 75 45
77 75 43
77 78 44
77 66 45
78 77 46
79 3 1
-1
413
2 ROAD
3 ENTER14
3 DOOR
3 GATE
4 UPSTR
5 DOWNS
6 FORES
7 FORWA
7 CONTI
7 ONWAR
8 BACK
8 RETUR
8 RETRE
9 VALLE
10 STAIR
11 OUT
11 OUTSI
11 15EXIT
11 LEAVE
12 BUILD
12 BLD
12 HOUSE
13 GULLY
14 STREA
15 ROCK
16 BED
17 CRAWL
18 COBBL
19 INWAR
19 INSID
19 IN
20 SURFA
21 NULL
21 NOWHE
22 DARK
23 PASSA
24 LOW
25 CANYO
26 AWKWA
29 UPWAR
29 UP
29 U
29 ABOVE
30 D
30 DOWNW
30 DOWN
31 PIT
32 OUTDO
33 CRACK
34 STEPS
35 DOME
36 LEFT
37 RIGHT
38 HALL
39 JUMP
40 MAGIC
41 OVER
42 ACROS
43 EAST
43 E
44 WEST
44 W
45 NORTH
45 N
46 SOUTH
46 S
47 SLIT
48 XYZZY16
49 DEPRE
50 ENTRA
51 DEBRI
52 HOLE
53 WALL
54 BROKE
55 Y2
56 CLIMB
57 LOOK
57 EXAMI
57 TOUCH
57 LOOKA
58 FLOOR
59 ROOM
60 NE
61 SLAB
61 SLABR
62 SE
63 SW
64 NW
65 PLUGH
66 SECRE
67 CAVE
68 TURN
69 CROSS
70 BEDQU
1001 KEYS1718
1001 KEY
1002 LAMP19
1002 HEADL20
1003 GRATE
1004 CAGE
1005 ROD21
1006 STEPS
1007 BIRD
1010 NUGGE
1010 GOLD
1011 SNAKE
1012 FISSU
1013 DIAMO
1014 SILVE
1014 BARS
1015 JEWEL
1016 COINS
1017 DWARV
1017 DWARF
1018 KNIFE
1018 KNIVE
1018 ROCK
1018 WEAPO
1018 BOULD
1019 FOOD
1019 RATIO
1020 WATER
1020 BOTTL
1021 AXE
1022 KNIFE
1023 CHEST
1023 BOX
1023 TREAS
222001 TAKE
2001 CARRY
2001 KEEP
2001 PICKU
2001 PICK
2001 WEAR
2001 CATCH
2001 STEAL
2001 CAPTU
2001 FIND
2001 WHERE
2001 GET
2002 RELEA
2002 FREE
2002 DISCA
2002 DROP
2002 DUMP
2003 DUMMY
2004 UNLOC
2004 OPEN
2004 LIFT
2005 NOTHI
2005 HOLD
2006 LOCK
2006 CLOSE
2007 LIGHT
2007 ON
2008 EXTIN
2008 OFF
2009 STRIK
2010 CALM
2010 WAVE
2010 SHAKE
2010 SING
2010 CLEAV
2011 WALK
2011 RUN
2011 TRAVE
2011 GO
2011 PROCE
2011 CONTI
2011 EXPLO
2011 GOTO
2011 FOLLO
2012 ATTAC
2012 KILL
2012 STAB
2012 FIGHT
2012 HIT
2013 POUR
2014 EAT
2015 DRINK
2016 RUB
300123 OPENS
3002 HELP
3002 ?
3002 WHAT
3003 TREE
3004 DIG
3004 EXCIV24
3005 BLAST25
3006 LOST
3007 MIST
3008 THROW
3009 FUCK26
-1
275
201 THERE ARE SOME KEYS ON THE GROUND HERE.
202 THERE IS A SHINY BRASS LAMP NEARBY.
3 THE GRATE IS LOCKED
103 THE GRATE IS OPEN.
204 THERE IS A SMALL WICKER CAGE DISCARDED NEARBY.
205 A THREE FOOT BLACK ROD WITH A RUSTY STAR ON AN END LIES NEARBY
206 ROUGH STONE STEPS LEAD DOWN THE PIT.
7 A CHEERFUL LITTLE BIRD IS SITTING HERE SINGING.
107 THERE IS A LITTLE BIRD IN THE CAGE.
8 THE GRATE IS LOCKED
108 THE GRATE IS OPEN.
209 ROUGH STONE STEPS LEAD UP THE DOME.
210 THERE IS A LARGE SPARKLING NUGGET OF GOLD HERE!
11 A HUGE GREEN FIERCE SNAKE BARS THE WAY!
112 A CRYSTAL BRIDGE NOW SPANS THE FISSURE.
213 THERE ARE DIAMONDS HERE!
214 THERE ARE BARS OF SILVER HERE!
215 THERE IS PRECIOUS JEWELRY HERE!
216 THERE ARE MANY COINS HERE!
19 THERE IS FOOD HERE.
20 THERE IS A BOTTLE OF WATER HERE.
120 THERE IS AN EMPTY BOTTLE HERE.
221 THERE IS A LITTLE AXE HERE
-1
628
1 SOMEWHERE NEARBY IS COLOSSAL CAVE, WHERE OTHERS HAVE FOUND
1 FORTUNES IN TREASURE AND GOLD, THOUGH IT IS RUMORED
1 THAT SOME WHO ENTER ARE NEVER SEEN AGAIN. MAGIC IS SAID
1 TO WORK IN THE CAVE. I WILL BE YOUR EYES AND HANDS. DIRECT
1 ME WITH COMMANDS OF 1 OR 2 WORDS.
1 (ERRORS, SUGGESTIONS, COMPLAINTS TO CROWTHER)
1 (IF STUCK TYPE HELP FOR SOME HINTS)
2 A LITTLE DWARF WITH A BIG KNIFE BLOCKS YOUR WAY.
3 A LITTLE DWARF JUST WALKED AROUND A CORNER,SAW YOU, THREW
3 A LITTLE AXE AT YOU WHICH MISSED, CURSED, AND RAN AWAY.
4 THERE IS A THREATENING LITTLE DWARF IN THE ROOM WITH YOU!
5 ONE SHARP NASTY KNIFE IS THROWN AT YOU!
6 HE GETS YOU!
7 NONE OF THEM HIT YOU!
8 A HOLLOW VOICE SAYS ‘PLUGH29
9 THERE IS NO WAY TO GO THAT DIRECTION.
10 I AM UNSURE HOW YOU ARE FACING. USE COMPASS POINTS OR
10 NEARBY OBJECTS.
11 I DON’T KNOW IN FROM OUT HERE. USE COMPASS POINTS OR NAME
11 SOMETHING IN THE GENERAL DIRECTION YOU WANT TO GO.
12 I DON’T KNOW HOW TO APPLY THAT WORD HERE.
13 I DON’T UNDERSTAND THAT!
14 I ALWAYS UNDERSTAND COMPASS DIRECTIONS, OR YOU CAN NAME
14 A NEARBY THING TO HEAD THAT WAY.
15 SORRY, BUT I AM NOT ALLOWED TO GIVE MORE DETAIL. I WILL
15 REPEAT THE LONG DESCRIPTION OF YOUR LOCATION.
16 IT IS NOW PITCH BLACK. IF YOU PROCEED YOU WILL LIKELY
16 FALL INTO A PIT.30
17 IF YOU PREFER, SIMPLY TYPE W RATHER THAN WEST.
18 ARE YOU TRYING TO CATCH THE BIRD?
19 THE BIRD IS FRIGHTENED RIGHT NOW AND YOU CANNOT CATCH IT
19 NO MATTER WHAT YOU TRY. PERHAPS YOU MIGHT TRY LATER.
20 ARE YOU TRYING TO ATTACK OR AVOID THE SNAKE?
21 YOU CAN’T KILL THE SNAKE, OR DRIVE IT AWAY, OR AVOID IT,
21 OR ANYTHING LIKE THAT. THERE IS A WAY TO GET BY, BUT YOU
21 DON’T HAVE THE NECESSARY RESOURCES RIGHT NOW.
22 MY WORD FOR31 HITTING SOMETHING WITH THE ROD IS ‘STRIKE’.
23 YOU FELL INTO A PIT AND BROKE EVERY BONE IN YOUR BODY!
24 YOU ARE ALREADY CARRYING IT!
25 YOU CAN’T BE SERIOUS!
26 THE BIRD WAS UNAFRAID WHEN YOU ENTERED, BUT AS YOU APPROACH
26 IT BECOMES DISTURBED AND YOU CANNOT CATCH IT.
27 YOU CAN CATCH THE BIRD, BUT YOU CANNOT CARRY IT.
28 THERE IS NOTHING HERE WITH A LOCK!
29 YOU AREN’T CARRYING IT!
30 THE LITTLE BIRD ATTACKS THE GREEN SNAKE, AND IN AN
30 ASTOUNDING FLURRY DRIVES THE SNAKE AWAY.
31 YOU HAVE NO KEYS!
32 IT HAS NO LOCK.
33 I DON’T KNOW HOW TO LOCK OR UNLOCK SUCH A THING.
34 THE GRATE WAS ALREADY LOCKED.
35 THE GRATE IS NOW LOCKED.
36 THE GRATE WAS ALREADY UNLOCKED.
37 THE GRATE IS NOW UNLOCKED.
38 YOU HAVE NO SOURCE OF LIGHT.
39 YOUR LAMP IS NOW ON.
40 YOUR LAMP IS NOW OFF.
41 STRIKE WHAT?
42 NOTHING HAPPENS.
43 WHERE?
44 THERE IS NOTHING HERE TO ATTACK.
45 THE LITTLE BIRD IS NOW DEAD. ITS BODY DISAPPEARS.
46 ATTACKING THE SNAKE BOTH DOESN’T WORK AND IS VERY DANGEROUS.
47 YOU KILLED A LITTLE DWARF.
48 YOU ATTACK A LITTLE DWARF, BUT HE DODGES OUT OF THE WAY.
49 I HAVE TROUBLE WITH THE WORD ‘THROW’ BECAUSE YOU CAN THROW
49 A THING OR THROW AT A THING. PLEASE USE DROP OR ATTACK INSTEAD.
50 GOOD TRY, BUT THAT IS AN OLD WORN-OUT MAGIC WORD.
51 I KNOW OF PLACES, ACTIONS, AND THINGS. MOST OF MY VOCABULARY
51 DESCRIBES PLACES AND IS USED TO MOVE YOU THERE. TO MOVE TRY
51 WORDS LIKE FOREST, BUILDING, DOWNSTREAM, ENTER, EAST, WEST
51 NORTH, SOUTH, UP, OR DOWN. I KNOW ABOUT A FEW SPECIAL OBJECTS,
51 LIKE A BLACK ROD HIDDEN IN THE CAVE. THESE OBJECTS CAN BE
51 MANIPULATED USING ONE OF THE ACTION WORDS THAT I KNOW. USUALLY
51 YOU WILL NEED TO GIVE BOTH THE OBJECT AND ACTION WORDS
51 (IN EITHER ORDER), BUT SOMETIMES I CAN INFER THE OBJECT FROM
51 THE VERB ALONE. THE OBJECTS HAVE SIDE EFFECTS - FOR
51 INSTANCE, THE ROD SCARES THE BIRD.
51 USUALLY PEOPLE HAVING TROUBLE MOVING JUST NEED TO TRY A FEW
51 MORE WORDS. USUALLY PEOPLE TRYING TO MANIPULATE AN
51 OBJECT ARE ATTEMPTING SOMETHING BEYOND THEIR (OR MY!)
51 CAPABILITIES AND SHOULD TRY A COMPLETELY DIFFERENT TACK.
51 TO SPEED THE GAME YOU CAN SOMETIMES MOVE LONG DISTANCES
51 WITH A SINGLE WORD. FOR EXAMPLE, ‘BUILDING’ USUALLY GETS
51 YOU TO THE BUILDING FROM ANYWHERE ABOVE GROUND EXCEPT WHEN
51 LOST IN THE FOREST. ALSO, NOTE THAT CAVE PASSAGES TURN A
51 LOT, AND THAT LEAVING A ROOM TO THE NORTH DOES NOT GUARANTEE
51 ENTERING THE NEXT FROM THE SOUTH. GOOD LUCK!
52 IT MISSES!
53 IT GETS YOU!
54 OK
55 YOU CAN’T UNLOCK THE KEYS.
56 YOU HAVE CRAWLED AROUND IN SOME LITTLE HOLES AND WOUND UP
56 BACK IN THE MAIN PASSAGE.
57 I DON’T KNOW WHERE THE CAVE IS, BUT HEREABOUTS NO STREAM
57 CAN RUN ON THE SURFACE FOR LONG. I WOULD TRY THE STREAM.
58 I NEED MORE DETAILED INSTRUCTIONS TO DO THAT.
59 I CAN ONLY TELL YOU WHAT YOU SEE AS YOU MOVE ABOUT
59 AND MANIPULATE THINGS. I CANNOT TELL YOU WHERE REMOTE THINGS
59 ARE.
60 I DON’T KNOW THAT WORD.
61 WHAT?
62 ARE YOU TRYING TO GET INTO THE CAVE?32
63 THE GRATE IS VERY SOLID AND HAS A HARDENED STEEL LOCK. YOU
63 CANNOT ENTER WITHOUT A KEY, AND THERE ARE NO KEYS NEARBY.
63 I WOULD RECOMMEND LOOKING ELSEWHERE FOR THE KEYS.
64 THE TREES OF THE FOREST ARE LARGE HARDWOOD OAK AND MAPLE,
64 WITH AN OCCASIONAL GROVE OF PINE OR SPRUCE. THERE IS QUITE
64 A BIT OF UNDERGROWTH, LARGELY BIRCH AND ASH SAPLINGS PLUS
64 NONDESCRITPT BUSHES OF VARIOUS SORTS. THIS TIME OF YEAR
64 VISIBILITY IS QUITE RESTRICTED BY ALL THE LEAVES, BUT TRAVEL
64 IS QUITE EASY IF YOU DETOUR AROUND THE SPRUCE AND BERRY BUSHES.
65 WELCOME TO ADVENTURE!! WOULD YOU LIKE INSTRUCTIONS?33
66 DIGGING WITHOUT A SHOVEL IS QUITE IMPRACTICAL: EVEN WITH A
66 SHOVEL PROGRESS IS UNLIKELY.
67 BLASTING REQUIRES DYNAMITE.
68 I’M AS CONFUSED AS YOU ARE.
69 MIST IS A WHITE VAPOR, USUALLY WATER34, SEEN FROM TIME TO TIME
69 IN CAVERNS. IT CAN BE FOUND ANYWHERE BUT IS FREQUENTLY A SIGN
69 OF A DEEP PIT LEADING DOWN TO WATER.
70 YOUR FEET ARE NOW WET.
71 THERE IS NOTHING HERE TO EAT.
72 EATEN!
73 THERE IS NO DRINKABLE WATER HERE.
74 THE BOTTLE OF WATER IS NOW EMPTY.
75 RUBBING THE ELECTRIC LAMP IS NOT PARTICULARLY REWARDING.
75 ANYWAY, NOTHING EXCITING HAPPENS.
76 PECULIAR. NOTHING UNEXPECTED HAPPENS.
77 YOUR BOTTLE IS EMPTY AND THE GROUND IS WET.
78 YOU CAN’T POUR THAT.
79 WATCH IT!
80 WHICH WAY?
-1
0

notes

1Static page? Google’s “Edit this page” button is way at the bottom. -DGJ

2Table 1. Long descriptions of rooms. (See my DHQ article, sections 22-23). -DGJ

3The original data file has some minor typos, such as this extra space before the period. -DGJ

4No period here, but the end-of-line break makes the meaning clear. -DGJ

5One of the keywords the parser recognizes. -DGJ

6
Patricia Wilcox (formerly Patricia Crowther) wrote on
alt.folklore.computers in 1990:

> Yep, Colossal Cave, the spring house, the gate, the Hall of the Mountain
> King, the maze of twisty little passages… They’re all real. We typed
> in all that survey data from muddy little books on a 110-baud teletype
> to a PDP-1 (the survey code took advantage of an undocumented side-effect
> of a custom-wired instruction that was only on that one machine, he he he).
> Then generated plotting commands on huge rolls of paper tape, which we
> carried over and plotted using a salvaged Calcomp drum plotter attached
> to a Honeywell 316 that was destined to become an ARPAnet IMP. (Will
> Crowther did a lot of the original ARPAnet code, too, when he wasn’t
> busy writing Adventure.)

-Quote source Dennis, via MCM

7What happened to 26? -DGJ

8What’s to be made of these repeated responses? Why not just call the same one multiple times? -MCM

They are different locations, with different connections between rooms, and capable of holding different objects at the same time. To re-use the title of a room would have required creating new code, for no clear benefit. I suppose this is like what happens when we need two copies of something; it’s easier to push the “print” button twice, than it is to go to the extra effort to use the photocopier for what it’s optimized to do. -DGJ

9Multiple identical messages can also be a sign that someone copied from an original (“maze of twisty little”), thinking to go back later and create some variations (“twisty maze of little”, “little twisty maze of”, “mazy twist of little”) but never did get back to do it. I haven’t played this game in MANY years, but I remember some places in which the description of a room given before entering it (“you are standing in front of”) doesn’t exactly match the description of a room given after entering it (“you are in”). I always figured somebody just dropped a stitch.
-rose

10Note that this version of the game does not include “Spelunker Today.” -DGJ

11Table 2, Short Room Labels.
(See my DHQ article, section 24) -DGJ

12First column: current room.
Second column: move player to this room….
Remaining columns: …when the player types a keyword marked with these numbers.
(See my DHQ article, 25-29) -DGJ

Perfect example of a place where “reading” the code / data is not the order of the day. A nodemap data structure calls for generating an infovisualization. Perhaps I’ll make one up in Graphviz and post it in the forum comment area. - JD

13Table 4. Vocabulary keywords. (See DHQ article, 30-36) -DGJ

14Items with the same number are flagged as synonyms. -DGJ

15I played this game when it was new, as a CompSci undergrad (1978-1981). I remember we treated learning how to talk to Adventure just like learning how to talk to a new editor or other tool: maybe it wants End or Quit or Stop or Cancel or Terminate or Exit or Escape…I clearly remember somebody in the lab guessing “Leave” and cracking us all up when it worked, really, what kind of software accepts “Leave” as a command? It didn’t seem funny for Adventure to recognize any kind of noun (“gully”), but verbs carried the expectation of behaving like a command language, so it was hilarious when they were closer to human language. After “Leave” worked, I remember some hours spent trying to find even less command-like commands that would work (“Boogie” did not work, and now I see why!)…the fun was trying to guess Adventure’s language, since there was no way to teach it ours.
- rose

16A FORTRAN compiler or translator would work on that code, but only
for the main “logic” of the game - i.e. lines 1100 to the END of
the main program, excluding anything having to do with printing
or comparing strings. When you see something like
INTEGER A
… get input into A …
IF (A .EQ. ‘XYZZY’)
you are sunk, because the assumption is that ‘XYZZY’ is a single
number and can be manipulated like one
-From Bruce Stephens’s post on the Google discussion group

17Items with the same number are flagged as synonyms. -DGJ

18These are all flagged as objects that require special treatment. -DGJ

19Note - the synonym “LANTERN” would not work (it was later added by Woods). -DGJ

20Short for “headlamp”. -DGJ

21Note that “WAND” is not part of Crowther’s original game. It’s just a rod. -DGJ

22I believe these are all verbs that require nouns. -DGJ

23These are all verbs recognize by the game, but the only reaction is printing a short message (usually explaining why the verb won’t work). -DGJ

24Typo for “excavate”. -DGJ

25In this game, this is a dummy verb that doesn’t do anything, but Don Woods used this as a hook - blasting is part of the endgame in the Crowther/Woods version. -DGJ

26Circumstantial evidence that Crowther didn’t create this game entirely for his young daughters. -DGJ

When I play the game online I get the clever “Real adventurers do not use such language,” which suggests that the word is in coded into the data file in order to provide some moral instruction. Yet, I can’t find that response line anywhere in the code. I’m assuming then, that it was added later, after this 77.03.11 version of the file? -MLS

-Llikewise, I don’t find FUCK or 3009 cited elsewhere in the program or data - looks like this is an unimplemented stub verb? Or does being a stub change the behavior, so that you get “I don’t know how to do that” rather than “I don’t know what that means?” - JD

27These messages report on the status of game states… in the DHQ article I called them “static game states” in the sense that they aren’t controlled by an independent process, such as the one that moves the dwarves, but but that seems rather silly now, since they are clearly variable states. -DGJ

28The DHQ article calls these “hints and events”. (section 39-40) -DGJ

29I’ve found no support for the notion that this is a caver term for “plughole.” -DGJ

In a posting to rec.games.int-fiction in 1997, Woods says that Crowther randomly generated “plugh”. See the Google Groups archive of Usenet -MLS: http://groups.google.com/group/rec.games.int-fiction/msg/12a87b3bea296fd…

I recently asked Crowther about PLUGH. At first he said the word was added by Woods. When I pointed out the recovered source code includes PLUGH, Crowther joked that it must have been the dwarves. Crowther has confessed to me and to other interviewers that his memory is fuzzy, so we can take this anecdote as evidence that whatever origin story was behind PLUGH was not important enough for Crowther to remember. Since I’ve found no evidence from the caving commiunity that “PLUGH” has any significance, we can safely assume that it was a random series of letters. Crowther explained XYZZY was supposed to look somewhat pronounceable. I suspect that the uncertainty of the “right” pronunciation is probably part of the appeal of the words he chose. -DGJ

30It’s hardly a stretch to see this as inspiration for the Infocom “grue.” -DGJ

31Playing this, we spent a lot of time giving it bad commands on purpose hoping to get more “My word for” teaching from the game…most of the time, the game does not try to teach its vocabulary.
- rose

32Other than the initial offer to print instructions, this seems to be the only other time the game asks as yes/no question. (Woods will add a few more instances.) -DGJ

33Contrast this with the first line of MUD1:
Welcome! By what name shall I call you?

Also, again, what does it mean for the intro line to come so late in this list - with the first line coming even later (further down) in the code section? -anonymous

The subroutine that handles yes/no questions comes near the end of the code file, which at least loosely implies it was added late. Further supporting the idea that the Y/N code was added late is the fact that in both cases, the questions being asked (does the player want instructions, and is the player trying to get past the snake) presume there’s enough of a game in place for the programmer to be able to provide help, and perhaps even that Crowther has observed enough people playing the game that he has concluded that players want/need different levels of help. So here we see echoes of user experience with earlier versions, affecting the development of ADVENTURE. -DGJ

34I’ve often wondered… what else could it possibly be? -DGJ