1984 · Melbourne House

Classic Adventure

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/classic-adventure with me to Gold.

Melbourne House's 1984 version of Crowther and Woods' Adventure keeps the whole cave as data: 140 rooms spelled from a 305-word dictionary, and 452 rules that decide everything a command can do. One of those rules makes the cave's last puzzle impossible to solve.

01 · The game, rule by rule

Every command, traced through the game's rules

Type into the game, and the panel beside it shows what the game made of the line: the words it knew, the exit it took or the rules it tried, each rule's conditions, and the actions that ran.

Loading the game's bytes…

Try

The game's screen, printed by a port of its interpreter from the bytes in listing.json, the same bytes the Source code tab shows. Type as on the C64, where lower case is the unshifted keyboard. The port was run beside the game's own code in a 6502 simulator for 504 sessions and 137,126 typed lines, and printed the same text and left the same variables after every line. The Play tab has the game on its own.

Almost none of the game is code. The program is an interpreter of about 3 KB, from $0F99 to $1BA9, and the rest of the file is tables: the dictionary, the rooms, the vocabulary, each room's exits, the rules, the messages, and the objects. A command is matched against those tables in a fixed order. When the first word is one of the room's exits, the player moves at once. Otherwise the 422 command rules are tried in order, and the first one with the right words whose conditions all hold runs its actions. Then the 30 status rules run, which have no words at all: they are how the cave acts on its own.

The cave is Crowther and Woods' Adventure, with its rooms, treasures, and puzzles, fitted into one program for the 64. The title screen credits Abersoft and the inlay John Jones-Steele.

02 · The end of the cave

Bug: the game cannot be won

The cave closes when exactly fifteen objects lie in the building, and the player is moved to the repository at its far end. Blasting the wall there wins the game, but only when the rod with the rusty mark is not in the room, and that rod can never be put down anywhere else.

The rules spell out the win. BLAST at the south-west end runs rule 406 when rod 10 is carried or lies there, and rule 407, the win, otherwise. The closing puts rod 10 at the south-west end, so the rod has to be carried to the north-east end and left there. From the north-east end, where the closing leaves the player, that takes six commands:

CommandMeant toWhat the game does
SWgo to the south-west end, where rod 10 liesthe same
GET RODpick up rod 10the same, by rule 211
NEcarry rod 10 back to the north-east endthe same
DROP RODleave rod 10 there"You have it already": rule 263 takes the rod instead of dropping it
SWgo back to the south-west end without the rodgoes back with the rod still in hand
BLASTblow a hole into the main office and win, message 133"you are suddenly splashed across the walls of the room": rule 406, message 135
Loading the game's bytes…

A game set up as a player would leave it, with the fifteen treasures in the building and the lamp, keys, food, and bottle carried; the button then types the commands. The screen is the game's own rules and messages from there on.

Five rules touch the rod with the rusty mark, object 10. Status rules 11 and 12 close the cave on the next arrival in the hall of mists, and both put rod 10 at the south-west end, where the blast has to be set off. Rule 406 is that blast: with rod 10 carried or in the room, the explosion ends the game. Rule 211 is GET ROD. DROP ROD tries rule 262 first, which drops the other rod if it is carried, and then rule 263, whose action is take where drop belongs, so DROP ROD with rod 10 in hand answers "You have it already".

Rod 10 cannot leave the south-west end by any other way. The repository's two rooms lead only to each other, and none of the rules that kill the player can run there, so dying cannot carry it out. The winning text, message 133, is in the game: "…a cheering band of friendly elves carry the conquering adventurer off into the sunset." It shows only with the player poked into the south-west end in a game that never put rod 10 there.

03 · The text

Every text is spelled from one dictionary of 305 words

Room descriptions, messages and object names are ASCII with the words taken out: any byte below 4 starts a two-byte reference to a word in a dictionary of 305, and the printer puts the spaces back.


    

Left, the record as stored: each dictionary reference shown as the word it stands for (hover for its two bytes), and each line break as ↵. Right, the same record as print_record lays it out, run by the port, justified to 40 columns.

The dictionary at $1D4C stores each word once and ends it with a byte that has bit 7 set. A reference is the word's number, counted from 1, in two bytes, the first below 4. All 305 words are used; "the" is referenced 282 times and "a" 240. Across every text, 3,796 references stand in for words, and after paying for the dictionary the texts take 7,150 fewer bytes than plain ASCII would.

TextsCharacters printedBytes stored
140 rooms, 200 messages and 78 objects25,98817,307
The dictionary at $1D4C1,531
Saved7,150

The writers laid each text out in lines of up to 40 characters, with a line break stored at the end of each. justify ($114B) then widens the gaps between words, starting from the right, until the 40th column is no longer a space, which gives the descriptions their uneven gaps and straight right edge. The last line of a text is left ragged, and so is any line with a % in it, which is not printed: the welcome screen uses it to keep its centred lines as they are.

04 · The parser

The parser reads the first four letters of each word

A command is cut into words, and each word to its first four letters, which are looked up among 226 vocabulary entries. Words the game does not know are skipped. The first word it knows is the verb and the second is the noun.

The game's own parse ($11D1), run by the port on the line typed above.

So PLEASE TAKE THE SHINY LAMP is TAKE LAMP, and LANTERN is LAMP too, because only LANT is compared. Synonyms share a number: GET, TAKE, CARRY, PICK, KEEP, CATCH, and STEAL are all word 201. Bit 7 of every character is cleared first, so shifted letters match as well. A third known word is kept at $0C8E, and no instruction reads it.

The magic word is spelled XYZY throughout this version, in the vocabulary and on the note in the debris room, so XYZZY gets "I dont understand!". No vocabulary entry carries word 5, so the exits written for it, DOWNSTREAM in room 38 among them, can never be taken. Every line typed counts as a turn, the ones the game does not understand included.

The vocabulary: 226 entries, 165 words
WordSpellings

05 · Command rules

422 command rules decide what a command does

The command rules are tried in the order they are stored. A rule applies when its verb is the first word and its noun is the second, or any noun at all; the first one that applies and whose conditions all hold runs its actions, and the scan stops there.

The rules for one verb, decoded from the tables at $5209, $5BF3 and $5FD9. The verbs are listed by how many rules each has.

A rule is six bytes: the verb, the noun or $FF for any, and two 16-bit offsets into the lists of conditions and actions, which end where the next rule's begin. Each condition is a code and an argument. The code for each kind of condition and action is a handler, reached through a table of addresses at $0CF0 and $0CC8:

CodeCondition
0the player is in room n
1the object is carried or here
2chance: the jiffy clock's low seven bits are below n
3the object is neither carried nor here
4flag n is set
5flag n is clear
6the object is carried
7the object is here
8the object is not here
9the object is not carried
10the object's location or flags are not 0
CodeAction
0list what is carried
1take the object
2drop the object
3print message n
4describe the room
5end the turn
6go to room n
7set flag n
8clear flag n
9offer another game (no rule uses it)
10say "Okay"
11ask "Are you sure?" and quit
12put the object here
13remove the object from play
14set flag n to 4 (no rule uses it)
15show the score
16remember room n
17put the object in the remembered room
18SAVE
19RESTORE

The engine reads actions two bytes at a time, code and argument, but the actions that take no argument all leave the rule, so the lists store them as one byte: 322 of the 452 lists end in one. When no rule runs, the game says "I cant", or "I cant go that way" when the first word is numbered 43 to 54, which are the eight compass points and then DEBRIS, HOLE, WALL, and BROKEN.

06 · Status rules

30 status rules run the cave between commands

The status rules have no words. They run in order after each room description and after every command that does not end the turn, and each one whose conditions hold runs its actions.

Thirteen of them, rules 0 to 10, 23 and 29, move the player straight on from a room that is only a sentence. "The crack is far too small for you to follow." sends the player back, and "You didn't make it." goes to room 0, which is death. Room 31 has no text at all, and rules 5 and 6 send the player on from it to one of two rooms, depending on whether the plant has grown. The rest give the cave its life: rule 21 is the pit that kills a player in the dark, rule 22 the dwarf who throws his axe, rules 24 to 27 the bird attacking the snake and the dragon, rule 28 the bear chasing off the troll, and rules 11 and 12 the closing of the cave.

07 · Darkness and death

Secret: lighting the lamp gives no dark moves back

Each description of a dark room takes one from a count that starts at 4, and status rule 21 throws the player into a pit when it reaches 0. The count is never refilled while the player lives: lighting the lamp only stops it falling.

Loading the game's bytes…

A new game. The player takes the lamp, goes through to the dark debris room without lighting it, looks, lights the lamp, looks, puts it out, and looks twice more.

The count is flag 5, $0C99. describe_room ($1503) takes one from it each time it prints "It is now pitch dark", on arriving and on every LOOK, and a move that a status rule turns into a second description takes two. Rooms 1 to 9, 100, 115, 116, and 126 are lit, and any other only while the lit lamp is carried or lies there. Nothing sets the count but a new game, which sets 4, and a death, which sets 3, so four dark descriptions in one life are the limit however far apart they come.

Dying

Room 0 is death. death ($1B35) prints the reincarnation text with the lives left in it, puts a carried lamp back on the road, drops everything else carried in the room the player came from, and wakes the player in the building with the darkness count at 3. The fifth death ends the game with the score, which dying does not reduce.

08 · The score

Bug: the score promises 210 and stops at 150

Every object in the building with its treasure bit set scores 10, and the score message says "out of a possible 210". Only fifteen treasures can be carried, so the score tops out at 150.


    

Tick the objects that lie in the building; the score is act_score ($19E4) run by the port. Objects 1, 2, 28 and 29 start there.

Eighteen objects have the treasure bit, bit 4 of their flags, and fifteen of them can be carried home. Of the other three, 67 is the vase resting on the pillow, which takes the vase's place and scores instead of it; 76 is the chain on the bear's wall, which no rule moves; and 78, "Underneath the body is a small flute.", is placed by no rule.

The score is kept as three ASCII digits inside the message and counted there. A carry out of the tens writes a 1 into the hundreds instead of adding one, so 200 would read 100. No game reaches 200, but objects 1 to 20 poked into the building as treasures show the fault.

The same pass decides when the cave closes. act_score counts every object in the building, treasure or not, and a SCORE that finds exactly fifteen sets flag 12 ($1A27). The next arrival in the hall of mists then closes the cave (section 02). With the treasures and the lamp in the building there are sixteen, and the cave stays open.

09 · The bear

Bug: the chained bear can be led away

Feeding the bear makes it gentle, and GET BEAR should then answer "The bear is still chained to the wall." until the chain is unlocked. The rule that says so tests the wrong object.

Loading the game's bytes…

The player poked into the bear's room with the lit lamp and the food.

Rule 190 ($567D) needs the gentle bear and object 78, "Underneath the body is a small flute.", which no rule ever places; object 76, the bear locked to the wall with a golden chain, is the one that makes sense there. With rule 190 never running, GET BEAR falls through to the rule that takes the bear, and the bear follows the player while the chain stays on the wall.

10 · The troll

Bug: FEE FIE never brings the troll back

Throwing a treasure to the troll at the bridge makes him leave. FEE FIE brings the golden eggs back to the giant room, and a second FEE FIE rule would bring the troll back as well, but the first rule always runs.

Loading the game's bytes…

The player poked onto the troll's side of the bridge with the lit lamp and the eggs.

Rule 395 ($5B4B) runs when the eggs have a location or flags, and the eggs keep their treasure bit after the troll has them, so the condition always holds. Rule 396 ($5B51), which also puts the troll back at the bridge, is never reached.

11 · Empty answers

Bug: two answers are blank lines

KILL CLAM, and OVER at the fissure before the bridge exists, each print a message, and both messages are empty.

Loading the game's bytes…

The player poked into the clam's room with the lit lamp.

Rule 328 ($59B9) prints message 15 and rule 36 ($52E1) message 87. Both have equal offsets in the message table, so print_record prints only the line break that ends every text. 105 of the 200 messages are empty, and these are the only two a rule prints.

12 · The turn counter

Bug: the 10,000th command rewrites the printer

The turns are counted as four ASCII digits inside the score message. On the 10,000th command the carry runs off the front of the digits and adds one to a byte of the printing code.

Loading the game's bytes…

The turn digits poked to 9998, then SCORE and LOOK. The port stops where the patched code would run.

The digits are at $0F68 to $0F6B. get_command ($13BD) adds one to the last and carries to the left with the X register. After 9999 the carry out of the thousands leaves X at $FF, and the store indexed by X lands on $1067, inside print_record. That byte is the opcode of STA $61, $85, and it becomes $86, STX $61. From then on print_record takes the length of each text from X, which its callers mostly leave at 0, so every room and message comes out as a blank line, and the turns read 0000. The game also keeps a 16-bit count of the turns at $0CA1, which nothing reads.

The C64 screen after the 10,000th command: blank, with only the typed word score and the cursor
The same moment in VICE, 8 October 2026: after the 10,000th command, LOOK and SCORE print only blank lines.

13 · Rules that never run

Secret: the dwarf can never be hit

THROW AXE at the dwarf needs flag 11, and no rule sets flag 11. The dwarf cannot be hit, and status rule 22 puts his axe back in the canyon each time the player comes without it.

Other parts of the tables are written for things the game never does:

14 · SAVE and another game

SAVE writes the whole game to tape in two files

SAVE ($1A5D) writes two files to tape with no name: the objects' locations and flags, $8AA2 to $8B3C, and the block from $0BBB to $0F97, which holds the starting copy of the objects, the line buffer, every variable, the handler tables, and the built-in messages, with the lives, score, and turn digits inside them. RESTORE loads both back where they came from, and neither checks for an error. On the Play tab the tape is kept in the browser.

The end of a game asks "Another game (y or n)?". An unshifted N jumps through the reset vector, and the C64 restarts into BASIC; anything else, a shifted N included, starts again from the starting copy. QUIT asks "Are you sure?", and only an unshifted Y quits.