Dungeons
J Chalmers,
West Sussex
from Your Computer August, 1982 page 74.

Much has been written about the speed and memory efficiency of ZX-81 machine 
code, although not many, long, solid machine-code programs have been published.
Dungeons sets out to remedy this situation by providing an easily expandable, 
relatively lengthy maze game. The program occupies less than 2K, but more than 
1K of RAM, and is expandable to occupy much more if you so wish. 

It produces, a maze of rooms, each with up to four doors. There are a total of
100 rooms on a 10-by-10 grid and the player must decide which room to move to
by selecting either up, down, left, or right. He can only move in this direc-
tion, however, if there is a door. The aim is to reach what is known as the 
Zero Room - the top left-hand room on the square grid.

The program is constructed using program modules, each module performing a 
specific task and being called when needed by a command routine. Using this 
modular approach eases program design and allows for unlimited expansion pos-
sibilities. The various modules must perform the following tasks:

-Construct the maze
-Display to the player, a plan view of the room he is in
-Perform the player's commands, up, down, etc.
-Keep a score

In the maze program, only the lower nybble of each byte within the maze area is
used. This nybble describes the room; how many doors it has and where they are,
in the format shown by figure 1, where a 1 represents a wall, and a 0 repre-
sents a door. If the nybble were to have the value 7, or 0111 binary, for ex-
ample, this would indicate a wall in every direction except up, where there is
a door.

Figure 1 Goes here.

Using this system of coding a maze can be set up simply by allocating each byte
in the area of memory reserved for thc maze, with a number between O and 15 - 
O to F. If these values are allocated randomly, a random arrangement of rooms
can be constructed.

When the program is run, first the maze is set up. The random values for each 
room are chosen. As there is no easy way of producing random numbers in machine
code this is done using the Basic RND function. The values obtained are Poked 
into RAM between 16514 and  16614, the area reserved for the maze.

When all the values have been stored, the program jumps into machine code. The 
first routine to be executed is called "perimeter", and makes sure that a wall 
exists all around the maze so that the player keeps within its confines.

The second routine is called "legalise", and is the real maze producer. Its job
is to look at each room in turn, and make sure that if a player goes, say, 
through a door on the right, he comes into the next room through a door on the 
left. When this routine has been completed, the maze is set up and ready to be 
wandered through.

The next routine to consider is the "print-room" routine which prints a plan 
view of the room which the player is in. The variable which holds the address 
of the player's position, is the system variable Seed at 4032. The room that 
the player starts in is chosen randomly by line 80 of the Basic program, which
uses Rand to store the selected address in Seed. The data needed to print the 
walls and doors which make up a room, is stored between 4151 and 41AE.

The print-room routine decides which strings it should print by looking at the
byte specified by Seed, and testing it using the bit instructions. It then 
calls a subroutine called "print data", which picks up each item of data from 
the chosen string, and prints it using the RST 10 instruction. A string is 
terminated by the presence of a 1B character.

Now that a plan of the room has been displayed, the next thing to do is print 
the scores. This is done by calling the print-scores routine at 424E. Data for
this routine is stored between 41AF and 41CO, while the actual scores are 
stored in system variables; Spare 1 at 4021 is the number of moves made; Spare 
2a at 407B is the bombs left, and Spare 2b at 407C is the tries made. The 
actual mechanics of printing the scores involve first loading the b register
with 00, and then loading the c register with the actual score. When this has
been done, the bc register pair contains the score, and a call is made to a ROM
subroutine which conveniently prints the contents of this register pair as a
decimal.

A player can move up, down, to the left, or to the right, using the arrowed 
cursor keys, 5, 6, 7, and 8, providing there is a door to move through. If 
there is no door, he has the option of using force and can blow a hole into a 
wall using a bomb. He does this by first pressing the A key and then the arrow
key indicating the direction of blast required.

Only four bombs are available, and the number remaining is printed as part of 
the score.  If a player thinks he is in the Zero Room, he can press the Newline
key and have a try. If he is correct, a message will appear indicating such, 
otherwise the game continues and the tries score is incremented.

The perform-keypress  module  starts at location 4297, and is the longest rou-
tine of them all. Its job is to determine which key has been pressed, and act 
on it. Its operation is straightforward in that the accumulator is loaded with 
the value of the key which has been pressed, or if no key has been pressed, it
waits for one, and the program works its way through the various commands
available until it finds the one which matches the key press; it then executes
the command and returns to the command subroutine. If it cannot find a command
which matches the key press, a jump is made back to 4297, and the routine waits
for another keypress before trying again.

The command subroutine calls all the program modules in sequence and increments
the moves made counter. By having this routine at the end of the program, it 
can be seen that the game can be easily expanded by adding a few subroutines 
of your own. Using the upper nybble of each maze element, it would be possible,
for example, to put various items of treasure, or terrible beasties, into var-
ious rooms and thus create an Adventure-style game.

To add your own subroutines, place them in the space indicated on the listing
and move the command routine to a position in RAM above them. The call instruc-
tions for these routines are placed in the space indicted on the listing within
the  command  routine. When  adding calls in this manner, make sure that the 
jump relative byte is correctly adjusted so that it still jumps to the second
call instruction, indicated by the label #31.

To add commands is just as easy and is achieved by changing the instruction at
#32 to 20 XX 00 where XX is the number of byte needed to jump forward to reach
the beginning of your new command test. When your test is finished you must 
either perform a return or a jump instruction. If the key test proved positive,
i.e., the player pressed the key you were checking for, and you therefore per-
form the required function, a return should be used to get back to the command 
routine.

If, however, the key test proved negative, you should use a jump instruction to
return to 4297. If you are unsure of how to add a command I suggest that you 
study the commands which the program already uses such as up, bomb, or try, and
follow a similar pattern of construction.

[Instructions on entering the program omitted-GCH]

When you have the program working properly here are a few tips on play: avoid 
using too many bombs, you may need them to break into the zero room; if a bomb
does not destroy a wall, the wall must be one of the outer ones.

To increase difficulty, change line 50 to read POKE I,INT(RND*6)+10.

===============================================================================
This is another program I found somewhere on the Internet, I just produced  
this text file.  The program already uses the increased difficulty mentioned
above, the original line was 50 POKE I,INT (RND*16). The number of bombs was 
also increased to 6 instead of 4 (100 POKE 16507,6).  Some brief instructions
are presented on start-up, I didn't see any reason to change these mods back 
as the basic game is the same. I added a redefine keys sub-routine starting at 
LINE 2000, because I hate using the cursor keys to move around. RUN 2000 to re-
define the keys then RUN 1000 to save your changes. Dungeons (ZXMK) uses the
Z, X, M and K keys for movement.
                                                              Greg Harder, 2017
===============================================================================
