Points come only from killing
ADD_SCORE has two callers. The kill of a small creature (KILL_MONSTER) adds 155, whether it was shot, walked into or caught by the player's death; killing Frankenstein's monster with the spanner (MOVE_FRANKENSTEIN) adds 1000 more. Nothing else scores: not keys, objects, rooms or escaping, and the other four of the big five cannot be killed at all -- none of them tests for the weapon (CHECK_SHOT_HIT is called only by the small creatures' movers), so the axe, the spell and the sword pass through them. Watched in the emulator: a game won by walking straight to the door, with the three pieces staged in the inventory, ended with a score of 0.
Dying is worth 155 a head
While the player sinks or rises, every small creature in the room is killed on its next move (STEP_ACTOR, the tail of MOVE_ACTOR), with the 155 points of any other kill. The big five are exempt. Watched in the emulator: with three creatures just materialising in the first room, starving the player took the score from 0 to 465 and emptied all three slots.
The humpback eats treasure
Eight of the collectables -- $82 to $89 -- have no use: nothing asks whether they are carried. Nothing, that is, except the humpback (MOVE_HUMPBACK), which looks for one of them in its room (SCAN_COLLECTABLES), walks to it and empties its record, so the object is gone for the game. It does this whether the player is there or not. Watched in the emulator: object $82 put in the humpback's room, room $56, was gone 40 frames later, the humpback standing where it had been.
Dracula fears the crucifix
MOVE_DRACULA asks FIND_CARRIED whether the yellow crucifix is carried; if it is, Dracula reverses whatever HOME_IN would have him do, and runs from the player instead of towards him. Watched in the emulator: Dracula put 12 pixels from the player in the first room closed in and had the life force down to 4 in 80 frames; with the crucifix in the inventory he backed away, 13 pixels to 48, and the player lost only hunger's 4.
The spanner kills Frankenstein's monster
Touched while the cyan spanner is carried, Frankenstein's monster (MOVE_FRANKENSTEIN) scores 1000, is killed like any small creature, for 155 more, and never comes back -- his slot is not refilled. Without the spanner he costs 8 a pass like the others. Watched in the emulator: put on the player, he took the life force from 240 to 46 in 40 frames; with the spanner in the inventory, the score went to 1155 at once and his record was emptied.
The mummy has an errand
Object $80, a red leaf-like thing, starts in room $09. If it is ever in the mummy's room, MOVE_MUMMY abandons patrol and pursuit alike, walks to it, and on reaching it moves it to room $6B, leaving it at the same x and y; then it takes up its business again. Room $09 is one of the eight rooms the mummy can be put in (with the red key), so in those games it does this at once. Watched in the emulator: the object put in the mummy's room reached by the mummy in 148 frames, and its room byte became $6B.
Never 100 per cent
The third figure on the end screens is a percentage of the castle seen (DRAW_SUMMARY): COUNT_ROOMS_EXPLORED counts the rooms marked in the visited map, scores 2 for each complete three and adds 1. All 149 rooms give 99; the starting room alone gives 1. Watched in the emulator: a game won by walking from the first room straight through the A.C.G. door, having seen two rooms, showed 01.
Food grows back
Eaten food is not gone for good. Once every 512 passes, REGROW_FOOD moves on to the next of the eighty food records, and if it is empty and not in the player's room it is filled again, in the same place, with one of the eight kinds chosen from FRAMES -- not necessarily the kind that was eaten. A whole round of the eighty takes about half an hour of play. Watched in the emulator: an emptied record came back as food $56 when the cursor reached it. (Except the very first record: see the bugs.)
Doors timed by the ROM
About half the plain doors in each game open and shut by themselves. At the start, CHOOSE_TIMED_DOORS walks the doors reading a byte of the ROM for each -- the Spectrum's own code used as random numbers -- and a byte below $70 makes that door a timed one, shut to begin with. In play they share one countdown of 94 steps, taken on every other pass by whichever timed door is in the player's room, so a room with two of them toggles twice as often. They move only while the player is in their room: their handlers are run from the room's list and nowhere else. (Read from the code. The first game converts 68 of the 125 plain door halves, counted in the simulator.)
One door, four walls
There is one picture of a door, not four. The top three bits of a door's +$05 choose one of eight drawing routines (PIXEL_DRAWERS), and the eight are the eight ways to lay a rectangle down -- as stored, mirrored, turned either way, upside down, a half turn, and mirrored across either diagonal -- each with a matching routine for the colours (COLOUR_DRAWERS). A door's mode is its wall. The four locked doors are the same picture again with four colour tables, and the furniture uses the same eight modes: see the architecture page.
A crowded room slows the monsters, not the player
MAIN_LOOP runs flat out, moving every monster once a pass, and calls FRAME_TICK -- the player, the weapon, the sound and the clock -- each time the ROM's frame counter has moved. So the player always moves at 50 frames a second, while everything else moves once a pass, and a pass is longer in a room with more furniture and creatures (about 1.7 frames in the empty first room, measured in the simulator). Hunger is counted in passes too (PLAYER_TICK drains on every sixteenth), so the roast lasts longer in a busy room.
The eight NOPs are not padding
Every one is a hole the game pokes an instruction into. Each has a LD (nn),A a few bytes earlier that writes the AND, OR or XOR combining a sprite with what is already on the screen. Remove them and sprite drawing breaks.
Two sprites share four bytes
Sprite $54 at GFX_54 says eighteen rows, which runs four bytes past GFX_58 where sprite $58 begins. Neither is wrong. Drawing $54 reads all eighteen rows and the seventeenth continues the taper of the sixteenth exactly; the byte they share, $0C, is the last row's left half and also $58's row count. Three bytes saved by a coincidence someone noticed.
A sprite that is entirely zero
$31 draws nothing at all. It is what DRAW_INVENTORY draws for an empty slot, and the type of the drop controller at $EE58, a record that follows the player from room to room so that the main loop runs PUT_DOWN on every pass.
Shape $0C is the trapdoor fall
Twelve nested rectangles, appearing in no room's entry -- if you read the first 149 entries of ROOM_TABLE. The table has 151, and the last is not a room but the fall. Drawn with the walk limits closing in, concentric squares read as dropping down a shaft. This one caught the author of these pages, which is why it is written down.
What was checked and found sound
Every branch in the game -- 4823 instructions' worth of JP, JR, CALL and DJNZ -- lands on an instruction boundary. None jumps into the middle of another, which is worth knowing in a game that patches its own code in eight places and enters routines part-way through in a dozen more. Nothing writes to an address below $4000, so no write is silently thrown away against the ROM. And the disassembly reassembles to the same 30208 bytes the tape produces, so nothing on these pages describes a byte that is not there.
Two graphics formats, chosen by sprite code
A creature or object is two bytes wide with a single byte of row count. The pieces the rooms are furnished with -- the clock, the bookcase, the barrel, the skeleton in chains -- are drawn by different code and carry a width as well. Nothing in the bytes says which is which: the rule is the sprite code, and codes above $A1 are furniture. Reading the furniture as sprites makes each one nine or eleven bytes long instead of a hundred and thirty, and leaves the rest of every one of them looking like artwork nothing points at. That is exactly what this disassembly said until it was compared against pobtastic's, whose graphics macro reads a width where this one had assumed a row count. And the rows are stored bottom up. Every picture here is flipped vertically to match what the game draws.
Code and data that nothing reaches
Two routines are complete, correct and called from nowhere: NEXT_PIXEL_ROW, which steps a screen address down one pixel row, and SETUP_BOTH_BANKS. Neither address appears anywhere in the game as a call, a jump or a table entry. Shapes $06 and $07 are two of the four orientations of the staircase, sharing their edge list with $05 and $08 and differing only in their corners; the game uses the other two. With the 251 bytes of padding at the top of the image that comes to 444 bytes, one and a half per cent, removable without changing anything a player would see. An earlier version of this page claimed 556 bytes of unreferenced artwork on top of that. There is none: those bytes were the tails of the room furniture, read in the sprite format instead of their own and so cut to a fraction of their real length. See the note beside GFX_FIRST.