A-MAZEING WE WILL GO (16K ZX81)
by Nick Godwin
from Home Computing Weekly 36 (8 November 1983) pages 60-62

Most random maze programs are too random, with the result either that the
maze is ridiculously easy, or otherwise completely impossible to get through.

This program, however, produces mazes that are both a delight to behold and
taxing to solve. Working on a completely different principle from most ZX81
mazes, it uses the UNPLOT function to maximise the available display area.

To initialise the program, RUN 100. The running time is very long - it may
take two hours in FAST mode to produce a maze - so I advise setting it off
then going away to have dinner while it gets on with its work.

When it has produced a maze, if a ZX printer is attached it will LPRINT a
copy (which serves also as an audible signal).

A flashing cursor can then be manipulated through the winding passages by
means of unshifted keys 5 through 8.

You may want to have a look and see how things are going while the maze is
being made. It is not necessary to STOP the program to do this - just put
your finger on key "M" (PAUSE) and hold it there until you get a display (you
may have to wait a few seconds).

Should you decide that the maze is sufficiently complicated for your
purposes, press shifted "A" (STOP) to continue onto the play routine.

You can STOP the program if you wish, but do not use BREAK as this could
cause problems. Simply put your finger on (unshifted) "A" and hold it there
until the program stops with report code 9/346. To re-start from where it
left off, GOTO 1.

It is not necessary to STOP the program in order to SAVE it.

Put your finger on the key "S" and wait until a string input cursor appears.
Type a program name, turn on your tape recorder, then press NEWLINE. When the
program is re-LOADed it will carry on working from where it left off.

SAVE also works once the maze has been completed and the program is in the
"play" routine. The present cursor position  will be held on the SAVEd
program, so you can continue trying to solve the maze from the point where
you left off.

Having produced a maze, you may well want to apply it, possibly to some game.
This will entail transferring it to some other program, or to a blank BASIC
area. There are machine-code ways of doing this, but for most purposes BASIC
will suffice, and that is the method I describe here.

First, SAVE the program with maze intact - press key "S" and follow the
procedure described above. Next, press shifted A to STOP the program, and do
the following commands:

   POKE 16388,64
   POKE 16389,125
   NEW

LOAD the program again, and press key "A" to STOP it. Now add the following
lines:

   9000 LET R=32063
   9010 FOR J=1 TO 704
   9020 POKE R+J,CODE Z$(I)
   9030 NEXT J
   9040
STOP

GOTO 9000 (not RUN) and when it stops (with report code 9/9040) either enter
NEW or LOAD the program to which you want to transfer the maze. Write the
following lines:

   9000 LET Z$=""
   9010 LET R=32063
   9020 FOR J=1 TO 704
   9030 LET Z$=Z$+CHR$ PEEK (R+J)
   9040 NEXT J
   9050 PRINT Z$
   9060 STOP

RUN 9000 (or GOTO 9000 if you have data to preserve). When the program stops
with report code 9/9060, there is your maze displayed on the screen and
stored in z$.

To make use of it (ie. to be able to push a flashing cursor through it) you
will need to write in lines 6 through 69, and 1161 through 1300 from the maze
routine, with the following alterations:

   1170 LET XM=30
   Delete line 1221


BONUS 1

This maze routine can double as a labyrinth making routine (for minotaurs,
etc). To do this, I suggest changing the DIM statement at line 103 to DIM
C$(1000) or less, and then touching-up the resulting sparse maze by means of
a simple UNPLOT routine (to add caves, connecting passages, etc).


BONUS 2

Quite apart from the aesthetic considerations, the maze program includes a
great deal of interest to ambitious home program-writers.

For example, lines 10 through 69 consist of a subroutine which performs a
potentially very useful operation which I believe to be something of a
breakthrough in  terms of ZX81 software, and which will interest anyone who
likes to use PLOT and UNPLOT.

Assuming X and Y as PLOT co-ordinates, the subroutine returns the following
variables:

L line and C column of the character in which X,Y co-ord pair is situated.
Z the character code at that L,C location.
P 1 if that X,Y location is already PLOTted, otherwise P=0 (ie., if
UNPLOTted or some other character).
Q is returned with a value (0 through 3) indicating the location of the X,Y
co-ord pair within that L,C location, as defined by:

+-+-+
|1|0|
+-+-+
|3|2|
+-+-+

Anyone who is involved in serious work with PLOT and UNPLOT will recognise
the value of this routine, and it is well worth the trouble to isolate and
SAVE it separately for use in other programs.

Another routine that is likely to prove of interest to serious programmers
starts at line 670. This relates to the economic storage of two-byte values
in a string.

Input to the routine is the variable R (a random number generated at line
660). The routine scans D$, looking for the two-byte code as translated into
x$ (line 670).

The scanning process is by the bisection method, which is much quicker than
searching through the string from beginning to end. Starting at approximately
the middle of the string, it bisects upwards if X$ (variable R) is greater
than the value found, or downwards if it is lower, and repeats the process
until it wither finds the identical value, or finds two successive numbers,
one lower and one higher than X$ (variable R).

In the former case, it jumps out of the routine at either line 780 or 885, in
this case returning to line 660 to find another random number. If it does not
find the number, it inserts it into the correct place in the string, and
jumps to line 900.
