The Cabinet of Curios

The Z-Machine and how it runs stories

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.

Loading…
Where to find story files
Built in:

Station 1

One story file, many machines

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

The header

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 $.

Header fields

Faded bytes are left for the interpreter to fill in when it starts: its own name, the screen size, and so on.

Station 3

Three kinds of memory

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

Three letters in two bytes

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.

The three alphabets

The abbreviations

Station 5

The dictionary

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

Rooms and things: the object tree

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

    The map, as best the file can tell

    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.

    Every room, with its exits
    RoomExits

    Station 8

    Every string in the file

    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

      Routines: the code itself

      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

        From the first byte to the first prompt

        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.

        Where to find story files

        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:

        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.

        Things to notice

        A little history

        Sources