Zork Source Code Is A Master Class In Game Developer Trolling

Zork Source Code Is A Master Class In Game Developer Trolling
Image: Digital Games Museum

When I think about retro games, forget Mario, Sonic or even Tetris. I think Zork. The quirky text adventure, published by Personal Software (and then Infocom) back in 1980, screwed with players in many, many ways (when it wasn’t sending grues after them). I thought I knew its best secrets — that is until prominent developer Ryan C. Gordon‏ revealed the granddaddy of them all… and the most underhanded use of randomness I’ve seen in a game for a while.

According to Gordon, while Zork checks the player’s item count to determine if they’re carrying too much, it also uses a random roll just to mess with the player. The roll used a number between 0 and 100, forcing players to keep trying to pick things up until it finally worked.

I was sceptical at first — surely a system as important as inventory wouldn’t be so cavalier with capacity? My scepticism grew when searches of Zork‘s MDL code from MIT and the public domain source from Infocom came up empty.

But, after checking various sources of decompiled code from Zork, it does indeed appear the game would fire out an overburdened message based solely on randomness.

Here are the relevant lines from the decompiled Zork assembly:

L0007: JE              G78,#5d [FALSE] L0008
       CALL            R0240 (G6f) -> L01
       JG              L01,G3b [FALSE] L0008
       MUL             L01,G3a -> L03
       RANDOM          #64 -> -(SP)
       JG              L03,(SP)+ [FALSE] L0008
       PRINT           "You're holding too many things already!"
L0008: INSERT_OBJ      G76,G6f
       SET_ATTR        G76,#03
       CALL            R0013 -> -(SP)
       CALL            R0235 (G76) -> -(SP)

The random call uses “64”, a hexadecimal (base 16) value, which converts to 100 in decimal (base 10).

And here’s the disassembled code Gordon found on the Wayback Machine, which includes comments:

     if( Verb ~= ##Take ) ?label8;
     num_items = CCount(player);
     if( num_items if( weight 
     move noun to player;
     give noun visited;

I knew Zork didn’t play fair sometimes, but this is next level.

Zork 1 ASM [GitHub, via Twitter]


  • And this is why our rose coloured glasses simply don’t match the shitty reality of actually playing these painfull games nowadays.

    • Agree. Fun at the time but no one wants to play them now. Tedious and awful.
      NES is about as far back as I’ll go but even then, those games are primitive and tedious too.
      I’m willing to put money on 90% of people who bought NES classics don’t even play it. Just a lame status symbol which says “I’m cool because I have a retro machine and you don’t” drinking the Nintendo kool aid

      • You’d probably be right about those people, but that doesn’t invalidate the NES Classic line up. I mean say what you want about NES games, but these NES games are all still well and truly playable. Donkey Kong, Ice Climber, Ballon Fight and Pac-Man are the lowest points. The rest are still fun.

      • “Because I abhor Nintendo (the #1 pastime of edgelords all over the world), I believe everything they do is objectively godawful, and so, any joy reported by their fans and customers is fake and product of fanboyish pretentiousness!”

        • “Because I adore Nintendo (the #1 pastime of [epithet of your choice] all over the world), I believe everything they do is objectively good, and so, any disdain reported by their fans and customers is fake and product of fanboyish pretentiousness!”

          You’re getting just as bad as those you complain so vocally about.

          • Oh yeah. I have no excuse nor pretensions of righteousness. Better people than I just ignore trolly commenters like that one. Sadly, it is not in my nature.

          • Never said anything Nintendo does is bad. Their fanboys are the worst though. And so are people who buy shit for reasons of FOMO or perceived ‘coolness’. And that’s exactly why the majority of people frothed at the mouth over the mini NES. Sure, I can’t prove it but it’s pretty fucking obvious.

    • It really depends on the game. Something like Final Fantasy 7 dates a lot slower because the bulk of its gameplay is menu based (I still replay it every few years and enjoy it just as much). You compare that to Goldeneye or Perfect Dark which as soon as a single generation after had already revealed its insufferable control scheme didn’t hold up. The rose-tinted glasses thing is definitely real there.

    • No rose coloured glasses required for Infocom games, just a love of reading (which I’m told is too hard by younger generations)

      Now the Ultima games on the other hand… I marathoned all of them including the spinoffs a couple of years back and the rose coloured glasses are not only shattered but ground to dust.

  • I love everything Zork, so thanks for the link to some source repositories.

    I think you are misunderstanding the code here though. It is actually rolling a random number to allow you to pick up extra items beyond your normal capacity up to an upper limit (when weight > 99*, you can not pick up anything else). Since Max_held_mult = 8 in the source, you can potentially carry 13 items, instead of the normal maximum of 8.

    * Assuming random(100) gives a number between 0 and 99.

  • OMGOMGOMG that way-back link goes to the horrible decompiler I wrote about 15 years ago, when I was at my mom’s house for the holidays and she had no Internet connection. It was originally going to be a rewritten TXD (the zcode disassembler) with a configuration file to label all the variables and functions, but I got more ambitious as the days passed in boredom. I can’t believe stuff linked to it still exists. It was written in Pike, a language used by about 9 people in the world, total.

    Another guy, Ben Rudiak-Gould, saw my work and then went on to create a VASTLY better decompiler in Haskell. I never manged to reduce branching into proper loops and if blocks (his code is limited too–it targets the Inform language, and the Inform language can’t reproduce some of the branching generating by the lisp-like internal Infocom compiler easily). I learned some Haskell, had my mind blown, and extended his code a little.

    I modified a bunch of Infocom binaries later, to tweak the variables to make them more friendly (the holding code, the limited lamp fuel in the Zorks, plus the annoying hunger daemons in Enchanter/Planetfall, plus removed a lot of copy protection code that required consulting the physical documentation).

    An interesting thing about those games is apparently Infocom didn’t use libraries–they copied previous libraries from other games in every new game. So there are some code sections that are completely unused in some games (plus unreachable segments, and other stuff). I guess they didn’t have an optimizer at that point. You can use some of those to do fun stuff by modifying the binaries. Later games bounced against the addressing limits, and they took out every unnecessary part–I assume it was a lengthy manual process.

Show more comments

Log in to comment on this story!