3D Monster Maze Disassembly
This page presents a commented disassembly of the classic 16K ZX81 game 3D Monster Maze written by Malcolm Evans and orginally published by J. K. Greye Software Ltd in 1981 and subsequently by New Generation Software Ltd. The two versions are identical except for the copyright message.
3D Monster Maze is primarily written in machine code but uses BASIC to control the operations of the Ringmaster, construction of the maze, the characters to display in the Exit pattern, and for reading the keyboard during the actual game play. The decision to drop back to BASIC to read the keyboard seems a strange one given that system variable LAST_K could easily have been monitored from machine code. BASIC is also used to regulate the speed of the game using a FOR loop, and the inlay instructions describe how the loop limit can be modified to adjust the speed.
The maze always consists of 18 rows by 16 columns, cleverly positioned so that the inner 16 rows align on a 256 byte page boundary. The top and bottom rows are only present to form an enclosing boundary to prevent the player moving above (north) or below (south) the inner 16 rows. The left most column is used for a similar purpose and will never contain a passageway. It provides an enclosing boundary to prevent the player moving outside the maze to the west, but also prevents movement too far to the east due to the way the rows are stored back-to-back in memory, i.e. the left most column also in effect appears to the right of column 16. The player can therefore only ever move within the inner 16 rows and for all of these locations the high byte of the address will have the same value. This means that the game need only check the low byte when examining the maze in order to draw it or when determining how to move Rex. Further to this, it is the upper nibble of the low byte that defines the row index for the location and the lower nibble that defines the column index. This carefully crafted arrangement means that the lesser used Z80 instruction RRD could be put to good effect to efficiently extract the two nibbles, i.e. row and column values.
The maze is constructed starting from the player's initial position (which is always the far south-east location of the maze) by randomly selecting a passageway direction and length. The passageway is inserted into the maze and the process repeated starting from the end position of the passageway just inserted. Each passageway is inserted one location at a time along the desired length but will terminate early should a location be reached that contains a wall but does not have a wall either side of it perpendicular to the direction of the passageway. This mechanism allows passageway to cross each other but not to lie side by side with each other.
Rex always moves at a slower pace than the player. When the player is moving, Rex moves at a half the player's speed. When the player is stationary, Rex moves at a quarter of the player's movement speed. Rex always tries to move towards the player. The difference in position between Rex and the player is computed in both the north-south axis and the west-east axis. An attempt is made to move Rex along the axis that has the larger of the two differences, but if Rex cannot be moved in this direction then an attempt is made to move him along the other axis. Since Rex is always trying to move towards the player, he can only ever be seen face on.
The 3D view is divided into 6 depths and is constructed in a number of stages. The first stage is to render the sides of the passageway, starting next to the player and progressing away to the furthest visible distance. At each depth, either a wall side is drawn or a gap is drawn where a perpendicular passageway runs. The next stage is to draw the facing walls of any perpendicular passageways. These are drawn starting with the further distance and progressing towards the player. The last stage is to render Rex into the view by superimposing him on top of the passageway image. The view of the passageway is only redrawn once the player moves, but if Rex is visible and moving towards the player then he will simply be redrawn on top of the existing view. There is no need to remove the previous image of Rex since each larger one always completely obscures the previous one.
The messages that appear at the bottom of the view depend upon the proximity of Rex and whether he has direct line of sight with the player. The list of messages that can be displayed are:
- REX LIES IN WAIT - Rex is not visible and could not move.
- HE IS HUNTING YOU - Rex is more than 8 positions from the player.
- FOOTSTEPS APPROACHING - Rex is 7 or 8 positions from the player.
- REX HAS SEEN YOU - Rex is between 3 and 6 positions of the player and in line of sight.
- RUN REX IS BEHIND YOU - Rex is less than 3 positions behind the player and in line of sight.
- RUN REX IS BESIDE YOU - Rex is less than 3 positions to the side of the player and in line of sight.
The game includes a number of checks to make sure the copyright notice has not be modified. One test is made from within the machine code and two from BASIC. The checks directly examine the memory expected to contain the copyright notice within the display file. This means that adjusting the program such that it changes size by even one byte will result in it crashing.
|Click here to download the commented disassembly of 3D Monster Maze (dated 29th November 2016).|
|Click here to access the program file for 3D Monster Maze by New Generation Software on Simon Holdsworth's excellent ZX81 archive website. The version published by J. K. Greye Software can also be found on Simon's website.|
Using the disassembly, I've also created a conversion of 3D Monster Maze for the Spectrum.