In 1979, two of the people bringing Zork to home computers invented a computer that didn't exist, so their story games could run on all the computers that did. Their games became story files: programs for that imaginary machine. This page opens one and takes it apart, from its header to its dictionary to its tree of rooms and things, draws a map of its rooms, reads out every string, decodes its code, and runs it up to the first prompt.
The page starts with After Hours at the Cabinet, a small game written for this page and short enough to read through. Press Zork I, Zork II, or Zork III to switch to one of Infocom's real games, built from its own source. You can also open a story file of your own, or drop one anywhere on the page, and every station will analyze that one instead. Buttons show their keys, like N for next and B for back, and the keys work on whichever station you're looking at.
All analysis is done locally in your browser. Your file never leaves your computer. To play a story instead of taking it apart, open it in the Z-Machine Interpreter.
Station 1
Zork was written at MIT in MDL, a language a lot like Lisp, on a DECsystem-10 mainframe, and it took up most of the memory a program could have there. Its authors wanted to sell it for home computers with far less memory than that, and there were many kinds of home computer, none of which could run another's programs.
First they cut MDL down to the parts Zork used and called the result ZIL, the Zork Implementation Language. That wasn't enough: compiled straight into any home computer's machine code, Zork would still have been too big. So in 1979 Joel Berez and Marc Blank designed a computer of their own, made for adventure games and nothing else: the Z-machine. It has its own compact machine code, Z-code. A game becomes a story file of Z-code, and each real computer gets a small program, an interpreter, that pretends to be a Z-machine and runs it. Infocom called theirs ZIP.
That paid off twice. Z-code is small: Zork's parser, the part that reads your sentences, took 10K 36-bit words on the mainframe and only 3K bytes as Z-code, and it did more. And a new computer needed only a new interpreter. After the first two, for the TRS-80 Model I and the Apple II, Infocom wrote interpreters for nearly twenty more computers and systems between 1982 and 1985, and a game written once could ship for all of them.
The interpreter also does the things that differ from screen to screen. The story file stores this description as one long line, and the interpreter folds it to fit whatever screen it's running on. Drag the width and watch it fold.
Station 2
An interpreter starts by reading the first 64 bytes, the header. It says which version of the Z-machine the game needs, where each of the game's tables begins, and how to check the file isn't damaged. Pick a row to light up its bytes, or press N and B for the next and previous field. Addresses and bytes are in hexadecimal, written with a $.
Faded bytes are left for the interpreter to fill in when it starts: its own name, the screen size, and so on.
Station 3
The header splits the file three ways. Dynamic memory holds everything that changes as you play: where each thing is, what's open, the score. Static memory holds tables the game reads but never changes. High memory holds the game's routines and most of its text. An interpreter has to keep dynamic and static memory in RAM, but high memory can stay on the disk and be read a page at a time. Pick a part to see where it sits, or press N and B to go through them in order.
Station 4
Text is most of a story file, so it's packed. Each pair of bytes holds three 5-bit Z-characters, and the top bit marks the last pair. Five bits only count to 31, so three alphabets share them: lower case, capitals, and punctuation. A shift character switches alphabet for one letter, and a pair of Z-characters can stand for a whole abbreviation, a common run of text stored once. Step through a string and watch it come out.
Station 5
Every word the game understands is listed here, packed the same way as text and sorted. When you type a command, the interpreter splits it into words, packs each one, and looks it up. The rest of the parser is the game's own Z-code. Version 3 keeps only six Z-characters of a word, so the first six letters are all that count. Press F to find a word.
Station 6
Every room, thing, and person is an object, and objects nest. Each one records its parent, its next sibling, and its first child, so the whole world is one tree. Picking up the lantern is a single instruction that moves it from the room to you. Each object also has 32 on-off attributes (48 from Version 4) and a list of properties: its description, the words that name it, its exits, and anything else the game needs. Station 7 follows the exits from room to room.
Press N and B for the next and previous object, and P for the one holding it.
Station 7
An exit is just a property. A room's north exit holds the room you reach by going north, a message saying you can't, or a routine that decides. Follow every exit and you have the map. Where a routine decides, the page reads it for the rooms it can send you to. Nothing in the file says where a room sits on the page, though. So this map is a guess: each room goes one step in the direction of the exit that reaches it, or to the nearest free spot when that one's taken. Games bend space, with passages that curve and mazes that loop, so expect some lines to cross.
Pick a room on the map or from the list below it. Press N, S, E, W, U, D, I, or O to walk, as you'd type in the game. With the map focused, the arrow keys walk too.
| Room | Exits |
|---|
Station 8
Text sits in two places. Most of it is inside the code: a print instruction carries its text packed right after it, so reading a game's prose means reading its routines. The rest is packed one string after another in the strings area after the code, where a routine or a property points at it by address. This station reads every routine and every packed string, so you can search them all.
Type a few words to find text, even misspelled. ↑ and ↓ move through the matches, reading each one as you go. Back and Next read the whole file in order, and F jumps to the search.
Station 9
The game is a set of routines. Each starts with a byte saying how many local variables it has, 0 to 15, then its instructions. An instruction is an opcode saying what to do, its operands, and sometimes a variable to keep the answer in, or where to go next depending on whether the answer was yes. This station decodes them a routine at a time, starting with the one the game starts in. Station 10 runs them.
Follow a call to read that routine, and Back B to come back. Next N and Previous P read the routines in the order they sit in the file, Start S returns to where the game begins, and G goes to an address.
Station 10
Everything the earlier stations took apart, an interpreter puts to work in a moment when you open a game. Step through it: the version, the memory, the header bytes the interpreter fills in, then the game's own instructions, one at a time, until the game stops and waits for you to type.
Step N goes forward a stage, then an instruction. Next text T runs until the game prints something, and To the prompt E runs until it waits for you. Back B and Start over S go back.
People still write games for the Z-machine, and hundreds are free to download. The IF Archive keeps them.
Files ending .z1 to .z8 open here; .z3, .z5 and .z8 are the usual ones. A .zblorb wraps a story file with its cover art or sounds, and this page takes the story file out. Files ending .ulx or .gblorb are for Glulx, a different machine.
A few to start with, all on the IF Archive:
Tangle.z5.Most of Infocom's games are still under copyright, so this page doesn't link to copies. If you have the files from a copy you own, they open here like any other. Zork I, II, and III are the exception: their source is free under the MIT License, at historicalsource/zork1, zork2, and zork3.
FRONT-STEPS and the lantern is lit with ONBIT. In the file they're object 26 and attribute 7. The names on this page come from the listings the compiler wrote while building After Hours and the three Zorks. Most other files show numbers, which is all an interpreter needs. Games built with Inform 6 are the exception: they carry their property and attribute names, so they can print them in error messages, and Station 6 reads them.odomet. Type examine odometry in the game and it examines the odometer.gparser.zil, which Infocom copied from game to game and changed as it went: Zork II's and Zork III's are the same file line for line, and Zork I's differs from them in a few dozen lines.found_in property 1,080 times across its 535 objects before the game prints a word, checking which things are found in more than one place.ROOMS, and a room is an object found there.DREARY-ROOM-FCN, a bracket closes a COND one line early, so its last clause, (T <PCHECK> <RFALSE>), falls outside it. ZILF stops there. Infocom's ZILCH kept going, and the assembly it wrote, kept beside the source, shows it compiled the stray clause as two plain steps: call PCHECK, then return false. That's just what the routine does with the bracket where it belongs, so the Zork II here was built with that one bracket moved, in a copy. The source shown here is as Microsoft released it.zork1.zip) and its README on where the files came from. MIT License, © 2025 Microsoft. github.com/historicalsource/zork1.2actions.zap holds DREARY-ROOM-FCN). MIT License, © 2025 Microsoft. github.com/historicalsource/zork2.