That is correct. The thief traverses indoor rooms in the order they appear in the (offscreen) ROOMS container. This is approximately the (reversed) order they appear in the source code. It’s not necessarily adjacent rooms; he jumps around the map a lot.
As it turns out, giving a treasure to the thief evidently is intended to have a special effect—it just doesn’t work. There is code in the game to temporarily reduce the thief’s battle strength (making the thief’s attacks less effective and the player’s attacks more effective) when you give him a treasure. It’s in the “the thief is taken aback by your unexpected generosity” code path. But due to a bug, or oversight, it doesn’t work as intended. See:
We’re going to be looking at this in some detail soon, when we get to the source code episodes. It was a big surprise to me to find that the thief in Zork teleports through rooms in a fixed order—I was convinced, while playing, that he had to use the same passages that were available to the player. On the other hand, in Adventure, the pirate is a special case of the dwarves, and uses much the same logic. The pirate/dwarf movement uses the ordinary cave passages, and is essentially a random walk with some restrictions (like never returning to the room they just came from, unless there is no other option). If you want a sneak preview of the dwarf/pirate logic, see §§159–176 (“Dwarf stuff”) in the source code.
Episode A11
We resumed attempts at the Perfect Run.
Attempt 3
We followed the same approximate plan as before, hoping for better luck. We decided to try carrying around at least one treasure while making our rounds, to give the pirate more opportunity to attack.
First trip: spices, chain, silver, diamonds, trident, magazine. (Depositing the trident was a mistake, as it is needed later for the pearl.)
Second trip: vase, eggs, emerald, rug.
Third trip: pyramid. We picked up the trident again to take back into the cave.
Fourth trip: trident, pearl, gold, jewelry, coins. But we held on to the coins, to give the pirate something to steal.
Fifth trip: we went out in search of the pirate. We checked the past game transcripts to see in what rooms we’ve encountered the pirate before:
| Count | Room |
|---|---|
| 5 | maze of twisty little passages, all alike |
| 3 | Hall of the Mountain King |
| 2 | unknown |
| 1 | N/S passage |
| 1 | soft room |
| 1 | south side chamber |
| 1 | steep incline above large room |
| 1 | Swiss cheese room |
This time, we found the pirate in his maze, just one room away from the dead end where he hides the chest. We delivered the coins and the chest to the house. Our score was 276 points after delivering all the treasures and leaving the magazine at Witt’s End.
While waiting for the cave to close, we experimented more with the random exits from Bedquilt. Going north from Bedquilt has a chance to take you to a junction of three secret canyons, exiting to the north, south, and SE. North from the junction is a “window on pit”: the same one we’ve visited so often before? No—it’s the other side of the mirror canyon, at last! Southeast from the junction took us back to Bedquilt. We didn’t get a chance to try the south exit from the junction, as the cave closed and we were whisked to the endgame.
In the repository, we took the dynamite (the rod with the rusty mark) from the southwest end and dropped it there, at the southwest end. Then we moved to the northeast end and blasted. The result: the wall broke open and flooded the room with lava.
New personal best: 335/350 points, Master Adventurer Class A.
- a11.txt game transcript
Topics mentioned:
- Colossal Cave Adventure
- Friday the 13th
- Whitsun
- Galatea
- Hüsker Dü
- John Milton
- Zork
- gambler’s fallacy
There is one more minor bit of geography you haven’t seen, and this one isn’t wholely randomized like the Bedquilt thing. It does however, as you now know, have no real purpose in the game.
Episode Z12
Job one of this episode was to figure out what to do with the thief. We finally engaged in the scurrilous practice of save scumming, saving and reloading at a point just before the battle in order to try out different tactics.
As a side quest, we needed to find out how to open the jeweled egg. Our hunch was that we had to turn it over to an NPC (because we, the player, have “neither the tools nor the expertise”). But what NPC? The troll? The cyclops? The thief? The bat?
- Give the egg to the troll: the troll eats it.
- Give the rusty knife to the troll: the troll eats it.
- Drop the rusty knife in front of a disarmed troll: nothing happens.
- Give the egg to the cyclops: “The cyclops is not so stupid as to eat THAT!”
We staged every weapon imaginable in the Cyclops Room adjacent to the thief’s hideout. (We were missing the rusty knife, however.)
- elven sword
- bloody axe
- nasty knife
- crystal trident
During this setup, the thief stole the egg from us. Then commenced a sequence of battles:
- Battle #1
-
"Trying to attack the thief with a crystal trident is suicidal."
Throw axe: the thief just accepts it.
Attack with sword: thief wins. - Battle #2
-
Automatically parry a turn-zero attack, losing knife.
Attack with axe, draw blood once, but eventually get disarmed.
Attack with sword, miss, thief wins. - Battle #3
-
Attack ineffectually with axe, get stunned and can't fight.
Retreat, give up. - Battle #4
-
Attack repeatedly with axe, lightly injure the thief once.
Automatically parry an attack with the nasty knife, losing it in the process.
Attack once more with axe, thief wins. - Battle #5
-
Attack with knife, temporarily disarm thief.
Attack with knife, miss, get knocked out.
Attack with knife, knock the thief unconscious!
Try to take the stiletto while he's out, but "the stiletto seems white-hot".
Then:>dispatch thief with knife The unconscious thief cannot defend himself: He dies.
Left behind were a chalice, a stiletto, and "a jewel-encrusted egg, with a golden clockwork canary".
The long-hoped-for victory stirs ambiguous emotions. Was fighting with the knife the key? In any case, the thief is the means by which you open the jeweled egg. You give the egg to the thief (or let it be stolen), the thief opens the egg offstage, and after you kill the thief you recover the now-open egg and the golden clockwork canary it contains.
The experience versus the thief was unsatisfying. It had really felt like it was meant to be a puzzle to solve, not brute-force randomness. The odds of victory in each attempt must be less than 50%. Are you meant to just go after the thief first thing every time, and keep restarting until you win by chance, before getting on with the rest of the game? It doesn’t jibe with our intuition about game design.
We fiddled with the granite wall in the treasure room to no effect. We attacked the sleeping cyclops; it just wakes him up. With the thief out of commission, the trap door in the living room no longer locks shut behind us.
We spent the rest of the run going around collecting and depositing treasure, to see how high we could get our score after defeating the thief. Nothing happens when you put the canary in the nest in the tree. But winding the canary, in the forest, summons the songbird, which drops off a minor treasure, a brass bauble. We took the canary, now free of its egg, to the coal mine, but it still doesn’t do anything.
Using the torch as a light source, we went off to try combining the Egyptian scarab with the Egyptian coffin. We had reached the conclusion, in the last episode, that it was not possible to get to the top of the waterfall, collect the scarab, and get back down, without first getting the sceptre (and therefore opening the coffin). But that was mistaken—it is possible, using the boat. From the buoy, go east to the sandy cave, get the scarab, return to the buoy, and land west to White Cliffs Beach south, from where you can re-enter the cave. We got the scarab, took it back to the undisturbed coffin, and abracadabra! it doesn’t do anything. But we learned that the golden coffin itself is a treasure, which requires a special move to get out of the underground.
New personal best: 251/350 points, rank of Adventurer.
Our modest proposal for improving Zork I:
- Giving an enemy the rusty knife should work to defeat them.
- The clockwork canary should do something in the coal mine.
- You should be able to go through the drafty passage as a ghost.
- z12.txt transcript
- z12-livingroom.qzl save game
- z12-pretroll.qzl save game
- z12-posttroll.qzl save game
- z12-premaze.qzl save game
- z12-cyclops.qzl save game
- z12-trident.qzl save game
- z12-prebattle.qzl save game
- z12-subdued.qzl save game
- z12-dependency.dot item dependency chart at episode start, Graphviz input
- z12-dependency.png item dependency chart at episode start
- z12-dependency-after.dot item dependency chart at episode end, Graphviz input
- z12-dependency-after.png item dependency chart at episode end
Topics mentioned:
- Zork
- save scumming
- Internet Archive
- plasma rifle
- Colossal Cave Adventure
- NetHack
- The Odyssey
- Galatea
- Graphviz
- Super Mario Maker
- Rock Lords
- Dungeons & Dragons
Partially.
Your odds of beating the thief are merely bad with the knife, as opposed to catastrophic with any other weapon.
However, the higher your score, the higher your combat bonus. (Points are “experience points” in some vague D&D sense.) So the correct answer is to attack the thief last.
With the thief out of commission, the trap door in the living room no longer locks shut behind us.
The trap door code does not check the thief status – in any version, as far as I know.
There’s a not-entirely-clear check for the TOUCHBIT flag, but I don’t think that’s related to the thief either.
I believe the logic is:
- TOUCHBIT is set when the trapdoor is locked behind you
- TOUCHBIT is cleared when you get back aboveground via the chimney in the studio or via resurrection
- The trapdoor doesn’t get locked behind you if TOUCHBIT is set
So if you get back aboveground via any “unlimited” means (not the chimney with limited carrying capacity, or resurrection with limited uses), then the trapdoor no longer locks behind you. But because of the way it’s tracked, you can make it lock again if you use the chimney or resurrection, even if you’ve already opened the grate in the forest (etc).
Episode A12
We resumed attempts at the Perfect Run.
This time, we were not going to worry about trying to carry around a piece of treasure to be stolen by the pirate. Going into the pirate’s maze, as we did in the previous episode A11, had probably been a good idea, for reasons that will become more clear when we look at the source code.
Attempt 4
First trip: trident, spices, chain. We entered Witt’s End, having forgotten to first pick up the magazine. After trying many times to get out by going west, the game gave a hint: “Don’t go west.” We abandoned the run and restarted.
66/350 points, novice class adventurer.
Attempt 5
First trip: we dropped the magazine at Witt’s End. Getting out of Witt’s End took an amazing 43 attempts. Then we got the trident, spices, and chain, but lost them to the pirate in the Oriental Room. We pivoted to the emerald, vase, eggs, and silver. To conserve battery, we turned off the lamp while doing FEE FIE FOE FOO and while dropping treasures.
Second trip: we fended off a dwarf attack. We collected the diamonds, then lost them to the pirate again. Then we died to a two-dwarf pincer attack and had to restart.
122/350 points, “Experienced Adventurer”.
Attempt 6
First trip: trident, spices, chain, pearl, silver. We survived two dwarf attacks.
Second trip: magazine, emerald, then a pirate attack. We got the vase and eggs on the way to the pirate’s maze. We survived two dwarf attacks. The pirate got us once more, en route to the secret dead end. There we recovered the vase, eggs, chest, and emerald and took them to the building.
Third trip: pyramid, gold nugget, diamonds, jewelry, rug.
Fourth trip: coins.
While waiting for the cave to close, we re-entered the secret junction north of Bedquilt to explore the south exit. Descending the stalactite drops you into the all-alike maze.
In the last episode, in the repository, we dropped the dynamite at the SW end, moved to the NE end, then blasted. This time, we did the opposite: dropped the dynamite at the NE end, moved to the SW end, then blasted.
There is a loud explosion, and a twenty-foot hole appears in the far wall, burying the dwarves in the rubble. You march through the hole and find yourself in the main office, where a cheering band of friendly elves carry the conquering adventurer off into the sunset. You scored 350 points out of a possible 350, using 369 turns. All of Adventuredom gives tribute to you, Adventure Grandmaster! To achieve the next higher rating would be a neat trick! Congratulations!!
New personal best: 350/350 points, Adventure Grandmaster!
- a12.txt game transcript
Topics mentioned:
- Colossal Cave Adventure
- dead man walking
- The Hitchhiker’s Guide to the Galaxy
- Zork
- Fremont Troll
- Metal Gear Solid 3
- speedrunning
- bivalve
- Virginia Is for Lovers
Episode Z13
To begin we looked at a short “fastest eaten by a grue” tool-assisted speedrun we had developed. The speedrun shows that you can stack multiple commands in one line, by separating them with periods. The input to get eaten by a grue is s.e.open.in.u.u.
It felt like we had solved all the game’s essential mysteries—in isolation. Now it was time to put together the Perfect Run for Zork. We made a dependency chart showing which items must be collected before other items. With that, we drafted a rough and untested plan for collecting all the treasures. We scheduled the thief fight, with its high degree of randomness, early in the run, so we could restart without losing much progress every time the battle didn’t go our way.
Plan
* get egg
in house
take lunch and bottle
take lamp and sword
take rope and knife
down
fight troll with sword
drop sword and rope
maze to Cyclops
offer lunch
offer water
drop bottle
offer egg to thief
fight thief with knife
drop knife
* take egg
* take canary
* take chalice
maze to room S
* get coins
get key
maze to grating
unlock grating
up
wind canary
* get bauble
in house
deliver
_ egg
_ coins
_ chalice
_ canary
_ bauble
down
to dam
get matchbook
get wrench
get screwdriver
push yellow
turn bolt with wrench
drop wrench
get pump
inflate boat
launch boat
get buoy
land sandy beach
get shovel
go to cave
dig
* get scarab
launch boat
west
open buoy
* get emerald
drop buoy
go to loud room
echo
* get platinum
go to cellar
up
deliver
_ emerald
_ scarab
_ platinum
down
get rope
go to round room
se
tie rope to railing
down
* take torch
lamp off
go to egyptian room
open coffin
* take sceptre
* take coffin
pray
in house
deliver
_ coffin
go to rainbow
wave sceptre
* take pot of gold
in house
deliver
_ sceptre
_ pot of gold
down
to temple
take bell
s
take book and candles
down
ring bell
light match
light candles with match
read book
drop candles
drop book
in
* take skull
go to mirror room
touch mirror
* get trunk
* get trident
touch mirror
go to gallery
take painting
up
deliver
_ crystal skull
_ painting
_ trunk
_ trident
get garlic
down
go to mirror room
touch mirror
go to bat room
* get figurine
go to shaft room
light lamp
put torch and screwdriver in basket
get coal
put coal in basket
lower basket
go to drafty room
drop all
w
get torch and screwdriver and coal
put coal in machine
turn switch with screwdriver
* get diamond
* get bracelet
go to slide room
down
up
deliver
_ torch
_ bracelet
_ figurine
_ diamond
Attempt 1
Defeated the troll.
Died to the thief.
We wondered if you have to leave the thief alone with the egg for a while to get him to unlock it, or if it happens instantly when you give it to him.
Attempt 2
Defeated the troll.
Died to the thief.
Attempt 3
Counted the leaves.
Defeated the troll.
Died to the thief.
Attempt 4
Counted the leaves.
Defeated the troll.
Died to the thief (turn zero).
Attempt 5
Counted the leaves.
Got a light injury from the troll, and waited for it to heal.
Defeated the thief. The egg was open immediately after the battle—so the thief doesn’t need simulated time to work on it.
First trip: canary, coins, chalice, bauble, egg.
Second trip: scarab, emerald.
We died at the waterfall, unexpectedly, after trying to go west after taking the buoy.
We didn’t restart immediately, but instead went looking for our gear. (We didn’t know, at the time, that the points penalty from dying would prevent us from finishing the game. It doesn’t in Adventure.) But we couldn’t find the scarab again, so we restarted.
Attempt 6
Received a light injury from the troll, and waited it out.
Defeated the thief (in just three attacks).
Counted the leaves.
First trip: canary, coins, chalice, bauble, egg.
Second trip: emerald, scarab, platinum. This time, we took the buoy (containing the emerald) the first time entering the room on the river, not during the return crossing, and didn’t go over the falls.
Third trip: sceptre, pot of gold. We picked up the torch, but held on to it as a light source. We grabbed the sceptre from the Egyptian Room. The coffin is too heavy to carry at the same time as our other items, so we’d come back for it. PRAY works even if you’re not carrying the coffin; we arrived back in the forest. Delivered the sceptre and pot of gold to the trophy case.
Fourth trip: coffin.
Fifth trip: skull, trident, trunk. We tried also for the painting but didn’t have room.
Sixth trip: painting.
Seventh trip: figurine, bracelet, torch, diamond. The lamp started to dim on this trip.
As we placed the final treasure in the trophy case and earned the 350th point, a voice whispered: “Look to your treasures for the final secret.” There appeared in the trophy case a parchment map. The map showed a stone barrow SW of a clearing in the forest. Going outside, there was a new secret path leading SW from the front of the house. We followed the new path, stepped inside the stone barrow, and won!
As you enter the barrow, the door closes inexorably behind you. Around you it is dark, but ahead is an enormous cavern, brightly lit. Through its center runs a wide stream. Spanning the stream is a small wooden footbridge, and beyond a path leads into a dark tunnel. Above the bridge, floating in the air, is a large sign. It reads: All ye who stand before this bridge have completed a great and perilous adventure which has tested your wit and courage. You have mastered the first part of the ZORK trilogy. Those who pass over this bridge must be prepared to undertake an even greater adventure that will severely test your skill and bravery!
New personal best: 350/350 points, rank of Master Adventurer.
We brainstormed things to look at in the next, source code episode. We commented on how, in the making of the tool-assisted speedrun, it seems that grue attacks in the dark are not certain but are slightly randomized, and that the random number generator can be influenced (in the Apple II version, at least) by frame-granularity delays.
Finally we tried the alternative strategy for the cyclops that had been mentioned in a previous episode. Saying ODYSSEUS causes the cyclops to flee in terror and carve a passage to the living room.
- z13.txt transcript
- z13-dependency.dot item dependency chart, Graphviz input
- z13-dependency.png item dependency chart
- z13-map.jpg map of the path to the stone barrow
- z13-cyclops.qzl save game just before the cyclops
Topics mentioned:
- Zork
- Colossal Cave Adventure
- speedrunning
- TASVideos
- Apple II
- grue
- Robin Hood Daffy
- Bushido Blade
- Tutankhamun
- mainframe Zork
- Outer Wilds
- NetHack
- The Visible Zorker
- RNG manipulation
The mainframe version of Zork, unlike Zork I, does have a designated “last lousy point”. It’s obscure (but IMO not as obscure as Adventure’s) and also kinda funny in a meta sort of way. I’ll happily spoil it here if you want.
Zork II does, in fact, pick up right where Zork I left off. You get your lamp back (magically recharged, of course). Some areas of Zorks II and III were from the mainframe original, and some aren’t. (And even some of the bits from Zork I play differently in Zork mainframe.)
Episode AS
In this XL 3-hour episode we explore the source code of Adventure. The version of Adventure we have been playing is special: it is a literate program, meaning that it has been specially arranged to promote appreciation and understanding. The source code is divided into numbered and linked sections that are grouped thematically and accompanied by essay-like commentary.
The CWEB source code produces both C source code to be compiled and a TeX document meant to be read by a person. Follow along in the PDF as we go section by section.
The typeset program appears in the book Selected Papers on Fun & Games. The printed book version has something the online version does not, this cave map:
Video timestamps and section references:
- 0:00:33
- Literate programming background.
- 0:04:06
- Literate programming demo.
- 0:16:10
- Game map.
- 0:19:30 §1
- Introduction.
- 0:25:25 §2
-
Running the program and
mainfunction. - 0:26:46 §4
-
The vocabulary.
enum wordtype, hash table. - 0:29:20 §9–10
- Motion words. N, S, E, W, ENTER, GRATE, XYZZY, etc.
- 0:34:48 §11–12
- Object words. LAMP, ROD, BIRD, BRIDGE, BRIDGE_, GOLD, PEARL, etc.
- 0:40:31 §13–14
- Action words. TAKE, DROP, GO, TOSS, BLAST, INVENTORY, SCORE, QUIT, etc.
- 0:48:33 §16
- Message words. HELP, INFO, ABRACADABRA, MIST, etc.
- 0:51:49 §18–21
-
Cave data.
enum location.struct instructionand connection logic table. Cave connections.make_loc,make_inst,ditto. - 1:05:19 §23
- End of road.
- 1:06:35 §25
- Inside building. XYZZY, PLUGH, clip of Don Woods pronouncing the magic words.
- 1:10:54 §26
- Valley. Index.
- 1:11:45 §27
- Forest, random room connections.
- 1:14:32 §29
- Depression, unlocking the grate.
- 1:15:44 §30
- Chamber below the grate. "If you've come this far, you're probably hooked."
- 1:16:00 §31
- Cobble crawl to top of small pit, gold/stairs puzzle, the pseudo-location neck.
- 1:17:23 §32
-
Hall of Mists. Possibly erroneous connection to jumble via the motion word Y2.
At your feet is a small pit breathing traces of white mist. An east passage ends here except for a small crack leading on. Rough stone steps lead down the pit. * d You are at one end of a vast hall stretching forward out of sight to the west. There are openings to either side. Nearby, a wide stone staircase leads downward. The hall is filled with wisps of white mist swaying to and fro almost as if alive. A cold wind blows up the staircase. There is a passage at the top of a dome behind you. Rough stone steps lead up the dome. * y2 A little dwarf just walked around a corner, saw you, threw a little axe at you, cursed, and ran away. (The axe missed.) You are in a jumble of rock, with cracks everywhere. There is a little axe here. - 1:18:48 §34
- East bank of fissure, crystal bridge.
- 1:19:18 §36–37
- Maze of twisty little passages, all alike.
- 1:21:52 §39
- Maze of twisty little passages, all different. Dwarf-proof passages.
- 1:23:30 §40
-
Hall of the Mountain King. Huge green fierce snake, SECRET motion.
You are in the Hall of the Mountain King, with passages off in all directions. A huge green fierce snake bars the way! * secret You are in a secret canyon, which here runs E/W. It crosses over a very tight canyon 15 feet below. If you go down you may not be able to get back up. - 1:27:42 §41
- Y2. "Somewhere Nearby is Colossal Cave", window on pit (east).
- 1:31:56 §43
- Clam/oyster.
- 1:32:33 §44
- Witt's End.
- 1:34:30 §45–46
- Bedquilt, Swiss cheese room, ORIENTAL motion, twopit room.
- 1:39:59 §47
- Giant room.
- 1:40:24 §48
- Secret canyon at junction of three canyons, stalactite down to the all-alike maze.
- 1:41:59 §49
- Window on pit (west).
- 1:44:07 §52
- Mirror canyon.
- 1:45:02 §55
- Bridge troll.
- 1:45:42 §56
- Dead ends, pirate logic.
- 1:46:56 §58
- Repository rooms.
- 1:47:27 §59–62
- Pseudo-locations. crack, neck, snaked, pdrop, etc.
- 1:48:54 §63–68
- Data structures for objects.
- 1:49:37 §69–70
- Object data.
- 1:50:53 §74–75
- The main control loop.
- 1:51:36 §76–87
- Command parser, action dispatcher, special cases in parsing.
- 1:52:57 §88
- Room descriptions, gold/stairs puzzle.
- 1:53:56 §90
- Using objects, TAKE KNIFE.
- 1:54:32 §92–95
- Simple verbs. TAKE, EAT, OPEN, CLOSE, READ, INVENTORY, BRIEF, SCORE, QUIT.
- 1:55:50 §97
- SAY, reward check.
- 2:02:19 §98
- EAT.
- 2:02:39 §99
- WAVE, BLAST, RUB, game end obfuscation, bonus points.
- 2:05:32 §100–101
- FIND, BREAK, WAKE.
- 2:06:17 §102–103
- Lighting and extinguishing the lamp, lamp power.
- 2:06:37 §104–111
- Liquid assets. Containers, watering the plant, oiling the door, filling the vase.
- 2:09:47 §112–115
- TAKE special cases, bird logic.
- 2:10:35 §116–127
-
The other actions. DROP, vending machine, bear vs. troll. bird vs. snake, TOSS, combat.
lost_treasures. - 2:14:04 §128
- Dragon combat, main loop impersonation.
- 2:15:39 §129
- FEED.
- 2:17:22 §130–133
- OPEN and CLOSE special cases.
- 2:17:41 §135
- READ.
- 2:17:45 §136–139
- FEE FIE FOE FOO.
- 2:18:47 §149–150
- Motions. Alcove, tight tunnel, pdrop.
- 2:19:11 §154–158
- Random numbers.
- 2:19:43 §159–171
-
Dwarf stuff. Pirate as dwarf 0. Movement and combat,
dflag. - 2:25:58 §172–176
- The pirate. Stealing and hiding booty.
- 2:29:19 §177–180
-
Closing the cave.
clock1,clock2. - 2:31:58 §181–182
- Endgame. Repository.
- 2:33:53 §183–192
-
Death and resurrection. Running out of lamp, replacing batteries.
dwarves_upset. - 2:36:05 §193–200
-
Scoring. Hints, hints extending lamp life. Launching the program.
Correction to what was stated in the video: you get the Adventure Grandmaster rank even with 349 points, you don't need the full 350.
- advent.w.gz CWEB source code
- advent.pdf PDF output of cweave
- as-map.jpg scan of cave map from Selected Papers on Fun & Games
- as-index.jpg scan of the index of Selected Papers on Fun & Games showing Emerson, Ralph Waldo
- as-thanks.jpg scan of §97 with signature
- as-check.jpg scan of Knuth reward check #648
Topics mentioned:
- Colossal Cave Adventure
- Fortran
- Donald Knuth
- literate programming
- TeX
- WEB
- Pascal
- CWEB
- C
- Selected Papers on Fun & Games
- MetaPost
- Will Crowther
- Don Woods
- John McCarthy
- goto
- MIX
- The Art of Computer Programming
- xyzzy
- plugh
- hurricane lantern
- Get Lamp
- Jason Scott
- Ravenous Bugblatter Beast of Traal
- Zork
- NetHack
- Steven Levy
- Hackers
- Latin square
- Y2
- Colossal Cave
- Diablo
- Knuth reward check
- Stanford University
- speedrunning
Episode ZS
This is the first of two Zork source code episodes. Our primary instrument for exploring the source code is the remarkable Visible Zorker. It lets you play the game, and at the same time see the function call stack and inspect the world state.
You can also see the source code in a browseable online repository. See the post Zork 1/2/3 are officially and legally released under the MIT license.
Neither of us was already acquainted with the code. In this video we’re learning as we go. This episode saw us generally exploring and following the thread of whatever struck our fancy. We looked at the general game engine (rooms, objects, variables, ADVENTURER, action functions), the parser (PRSA, PRSI, PRSO variables), timers (songbird, injury, thief, sword), and combat—with numerous digressions. We found answers to some questions we had:
- “Hello sailor” has no effect. It gives different messages if you say it enough times. Besides “sailor”, you can also say “aviator” or “footpad”.
- It is possible to defeat the thief without the knife, just less likely.
- ULYSSES is another word that works to scare the cyclops. But the internal name of the verb is
V-ODYSSEUS.
There’s a lot more to see, so we’ll be back.
- 0:03:40
- ZIL, MDL, The Visible Zorker.
- 0:06:49
- "Activity" tab.
- 0:07:46
- "World" tab.
- 0:09:54
-
Action functions.
WHITE-HOUSE-F. - 0:13:12
- Visible Zorker commentaries (green eyeballs). Rooms and items, scenery and global objects.
- 0:14:56
-
ADVENTURER,ME,WINNER,HERE. - 0:16:19
-
"State" tab.
BEACH-DIG,COFFIN-CURE,YUKS. - 0:17:01
-
Parser variables
PRSA,PRSI,PRSO(action, indirect object, and direct object respectively).PUTandPUT-ONactions. Compound commands (PUT SWORD AND LEAFLET IN MAILBOX). - 0:20:09
- "Timers" tab.
- 0:21:08
- "Files" tab. Super-brief mode.
- 0:21:37
- "?" tab. Release history.
- 0:22:56
-
Timers and daemons. Integer underflow.
C-TABLE,C-DEMONS. - 0:25:55
-
DIAGNOSE and
I-CURE.STRENGTHand carrying capacity.STRENGTH-MAX,STRENGTH-MIN. Local and global variables. - 0:31:06
-
I-FOREST-ROOM, random chirping of songbird. - 0:34:04
-
I-LANTERN,LAMP-TABLE. - 0:35:50
-
BLACK-BOOK.INTNUM.JIGS-UP.LIVING-ROOM-FCN,RUG-FCN.IT. - 0:42:35
-
Object attributes (
TURNBIT,READBIT, etc.). - 0:44:23
-
Troll room.
FIGHT-STRENGTH,HERO-MELEE. Cyclops combat?CYCLOPS-MELEE.THIEF-MELEE. Combat results and the structure of melee result tables. - 0:53:47
-
VILLAINStable. Weapon weaknesses. The troll is weak to the sword, the thief to the knife. - 0:56:02
-
Began walking through a round of troll combat.
THIS-IS-IT.TVALUE,I-SWORD,INFESTED?.I-FIGHT.DEAD.VILLAIN-STRENGTH,THIEF-ENGROSSED(see also).PROB. Points contributing to combat effectiveness. - 1:28:47
-
TROLL-FCN.TROLL-FLAG. - 1:33:53
-
CYCLOPS-FLAG,LLD-FLAG,MAGIC-FLAG,WON-FLAG.COFFIN-CURE,SOUTH-TEMPLE. - 1:37:35
- Back to analyzing troll combat. Possibility of killing the troll by getting him to eat something sharp. MUNG.
- 1:45:42
-
V-ODYSSEUS. ULYSSES is recognized as a synonym of ODYSSEUS, but ODYSSEUS is canon, for several reasons. One of the reasons is that Commandment #12592 in the black book is an acrostic. The first letters of each line spell out ODYSSEUS:Oh ye who go about saying unto each: "Hello sailor":
Dost thou know the magnitude of thy sin before the gods?
Yea, verily, thou shalt be ground between two stones.
Shall the angry gods cast thy body into the whirlpool?
Surely, thy eye shall be put out with a sharp stick!
Even unto the ends of the earth shalt thou wander and
Unto the land of the dead shalt thou be sent at last.
Surely thou shalt repent of thy cunning. - 1:57:06
-
Code that is unused in Zork I.
V-HELLO. "Hello sailor" does… nothing! In Zork I, at least.
Topics mentioned:
Episode ZS′
This is the second and final episode of Zork source code exploration. Again we are using The Visible Zorker to see the source code alongside the game.
We spent the majority of the time looking at the thief: how he moves, stealing things, and combat. We also browsed the properties of various rooms and items, including weights and container capacities. (And finally settled the mystery of the set of teeth.) We uncovered a few deep secrets, like a magical connection between the treasure room and the temple, a different solution for the loud room puzzle, and the fact that death by grue is not an absolute certainty when you take a step in the dark.
- 0:02:48
-
We looked up the "set of teeth" that had bedeviled us since episode Z3. The
TEETHobject is a global object (accessible from any room) that exists only so that the parser has something called "teeth" to refer to when you try to BRUSH TEETH WITH GUNK. (Otherwise it would say "I don't know the word 'teeth'.") The strange phrase "set of teeth" is an artifact of how objects are defined, like "quantity of water" or "pair of hands". - 0:09:10
-
We looked at the function
JIGS-UP, which is called whenever the player does something to gets them killed. (Like brushing their teeth with the gunk, say.) The condition that decides whether you respawn alive in the forest or as a ghost at the Gates of Hades is whether you've been to the south temple or not. TheRANDOMIZE-OBJECTSfunction is what scatters your inventory when you die. There's a failsafe inJIGS-UPfor when you die when you're already a ghost. (Which takes some doing, but it can happen!) - 0:14:34
- 0:16:19
-
The songbird and the clockwork canary. The songbird is not a live, moving object like the dwarves and pirate in Adventure; but rather one of those that you can refer to from many rooms that doesn't really exist in any of them. While you're in a forest room, there's a uniform probability that you'll hear the chirping of the songbird. (In that way, the songbird is like the first dwarf encounter in Adventure, but not the subsequent ones.)
- 0:19:54
-
The thief and thief movement. The thief doesn't follow the same room connections that are available to the player. Instead, he starts in the Round Room and then warps from room to room on a predefined circuit. The thief's
STRENGTHis 5, which is why he is so strong in battle. (Compare to the troll'sSTRENGTHof 2.) There are some random interactions in combat with the thief that we did not see. If you throw the knife at him while not engaged in combat, there is a small chance that he will flee and leave his items behind. The point at which the jeweled egg is opened is when the thief deposits the egg in his lair (either in his wanderings or after he dies).It seems like you could take the thief's chalice without killing him, if he is unconscious in the treasure room. That, combined with the random chance of making him drop items, might make possible a run where you do not kill the thief.
- 0:50:31
- 0:52:31
-
I-THIEF, the thief "demon" routine that runs on every turn. The order in which the thief visits rooms is defined by theROOMSlist. But he doesn't enter rooms that haveSACREDBITset, nor rooms that are not solid land (RLANDBITbit).The thief may pick up and drop items as he moves around. He'll never take something from a room you haven't been to yet (
TOUCHBITis not set). Otherwise he has a chance of stealing any treasures that are present (ROBfunction). He may take non-treasures as well, but how this works differs depending on whether he and the player are in the maze. If the thief and the player are inside the maze (MAZEBITis set), he callsROB-MAZE, in which he has a chance to remark "My, I wonder what this fine item is doing here" and possibly to pick up the item. Otherwise, he callsSTEAL-JUNK, where he has a chance of picking up each non-treasure in the room.Correction to what was stated at 1:04:08: it looks like the thief can steal the rope in
STEAL-JUNK, and in so doing also setsDOME-FLAGto false. - 1:11:06
-
V-LEAP. You will die if you try jumping in the kitchen, because there's a (never usable) down exit from there. But you can jump down from the tree safely. - 1:17:08
-
Perusing the rooms in
ROOMS. Seeing which ones are considered sacred. The "Granite Wall" mystery: the strange engraving in the slide room that had baffled us is an oblique hint that there is a connection between the granite wall on the east side of the treasure room and the the granite wall on the west side of north temple. We had dimly guessed that some kind of connection existed, but were unable to make use of it. What it means is that you can say TREASURE or TEMPLE to warp between the two rooms. - 1:31:48
-
Looking at the commentary on various items and rooms. The broken timber in the timber room was used for a puzzle in the original MDL version of Zork. It has no use in Zork I.
RAISED-BASKETandLOWERED-BASKET.BAT,DAM-ROOM,GARLIC,BONES,BUBBLE,COFFIN. - 1:37:59
-
Object size/weight and the capacity of containers. The
WEIGHTfunction.The
ALTAR, too, acts like a container, albeit one you cannot pick up.The magic boat is a container as well, having capacity 100. We talked about the "boat of holding" glitch, where you fill the boat with items and then deflate it. The deflated boat is considered a different item, with a lower weight than the inflated boat and the items it contains. Re-inflating the boat brings the items back.
- 1:46:33
-
More items and their properties.
MATCH,PAINTING,CANDLES,GUNK,LEAVES. The buttons in the dam maintenance room. - 1:49:58
-
An alternative solution for the loud room.
I-RFILL.The rushing sound in the loud room is the sound of flowing water. If you turn the bolt once to drain the reservoir, then turn the bolt again to start to refill it, and hurry to the loud room before it completely refills, the loud room will be quiet and you will be able to take the platinum bar.
The implementation of the loud room is really elaborate. Just like the sneaky extra-loop input that secretly accepts "yes" when you fight the dragon in Adventure, the loud room outputs a fake command prompt, reads input outside the main input loop, and handles the input itself without giving it to the main game engine for processing. This is how the echoing effect is achieved.
- 1:59:23
-
Syntax definitions. The $VERIFY command. BLAST.
- 2:00:15
-
There is only about an 80% probability that you will be eaten by a grue when taking a step from a dark place.
We had the impression that in the case you are not eaten by a grue, you stay in place and cannot actually make progress in the dark, but the part we were looking at is for when you take a step in the dark in a direction where there is no exit. There is another code path (with a separate about 80% chance) for when you follow a valid exit from one dark room to another. (There's a difference in the death message in each case: the former is "You have walked into the slavering fangs" and the latter is "A lurking grue slithered into the room".)
- 2:03:59
-
Combat. The
THIEF-VS-ADVENTURERfunction.HERO-BLOWandVILLAIN-BLOW. The player's combat strength (FIGHT-STRENGTH) goes from 2 (STRENGTH-MIN) to 7 (STRENGTH-MAX), increasing by 1 point for every 70 points of score. The player's strength can be adjusted by theirSTRENGTHproperty, which is normally 0, except when injured.The result of any given blow in combat is a random variable that depends mainly on the absolute strength of the defender, and the difference in strength between the defender and the attacker. These numbers are used to index tables of combat results. There are 9 possible outcomes of any attack. Not all of them are encoded directly in the tables, but use special-case logic, such as the defender having a random chance of losing their weapon when staggered.
Topics mentioned:
- Zork
- Zork III
- The Visible Zorker
- ZIL
- acrostic
- Grim Fandango
- speedrunning
- Lisp
- Heart of Darkness
- Lua
- Colossal Cave Adventure
- Zork Playground
- mainframe Zork
- Sorcerer
- Hunt the Wumpus
- Trinity
- New York City Subway
- Massachusetts Institute of Technology
- MDL
The thing with teeth being synonymed as “overboard” is a known thing that’s technically a bug. the developers wanted to allow THROW [objec] OVERBOARD while you’re in the boat. So they needed to treat “overboard” as an object. Presumably they chose to synonym it to teeth as some kind of memory-saving trick to avoid creating another object?
But this also leads to probably my favorite zork bug. The overboard code forgets to check if you’re actually holding the thing you’re throwing. Which allows this to happen:
>throw grue overboard
Ahoy – lurking grue overboard!
>look
Frigid River, in the magic boat
You are on the Frigid River in the vicinity of the Dam. The river flows quietly here. There is a landing on the west shore.
There is a lurking grue here. (outside the magic boat)
The magic boat contains:
A tan label
This gets the grue object in a state it’s not supposed to be in: it now is only in that room. You can no longer get the grue description (or do anything else that refers to the grue) unless you’re in that specific room. If you try, you get “You can’t see any grue here!”, which is technically correct (my favorite kind of correct!) but not supposed to happen.
This works for any other global object. The funniest is that you can “throw me overboard”, which from then on gets it to say that “there is a you here” and stops any commands that refer to yourself from working. (There might be some other side effects, if it’s checking the location of “you” anywhere, but I think there’s a difference from what it’s checking in most places versus the “me” object commands use.)
Oh, and remember how the game synonymed overboard with teeth? Because the teeth are a global object, you can throw the teeth overboard, as I just discovered. This doesn’t cause a line about the teeth to appear in the room description, unlike with other objects. What it DOES do is stops you from being able to throw stuff overboard aside from the spot you did it. When you try, it says “You can’t see any overboard here!” because it made the teeth (ie, the overboard object) no longer global!
One more note: yes, they did recycle some code for all 3 Zorks. This also applies in the other games. For instance, Zork II still understands the verb “odysseus” even though there is no cyclops in Zork II (I hope you don’t mind me spoiling that). Except, it doesn’t respond with anything, presumably because they did clear The section of code that actually handles the command, but not the part defining the vocabulary. It just gives no output and goes right to the next command prompt.
They could also have created a new grammar line with OVERBOARD as (approximately) a preposition. But, again, that takes more memory.
It looks like they wanted the generic response to be “Wasn’t he a sailor?” But they screwed up the indentation, maybe, so that message is never reached.
EDIT: Or else the compiler screwed up. It looks like the line <TELL "Wasn't he a sailor?" CR>)> is executed, but the inline string has been wrongly optimized out. The CR remains, which is why the response to ODYSSEUS is two blank lines.

