Moneygrabber
by J. Dave Rogers
from ZX Computing April 1985, page 10

Moneygrabber

J. Dave Rogers appeals to your instincts, Liverpool's answer to Scrooge?

Generating a random maze with a 'guaranteed' path through it is usually
a slow job given present day Basic speed (one program I saw took two
hours, and that was in FAST mode). This program however, manages to
continuously develop (as it scrolls) a random yet reasonably structured-
looking maze, including guaranteed paths, and it does this in the time
left between moving the player's man around, doing various collision
checks and printing a frequently updated two-layer Bar graph. Now, knowing
languid, laid back ZX81 Basic for what it is, you may be thinking by now
that there will be time for a cup of tea between moves, possibly a shower
as well, but player movement is, if anything, faster than in most ZX81
all-Basic written games, How is it done! -- read the program description!

Playing the game

You are trapped in a maze which is slowly but inexorably creeping upwards,
In it are scattered pounds and dollars which you must manage to grab enough
of to keep your 'Bank Balance' in credit, because, as the maze moves over-
head you lose money ('overheads'!), Your current bank balance is shown by a
double-layer Bar graph along the bottom of the screen, This also features
'riding indicators' to make it clear what's being credited or debited,

After a few screenfuls of maze there is a 'chopper' section, and if you can
negotiate this you receive a bonus. Having been given this bonus you are
then liable to pay tax, so next comes Tax Dodgers Tunnel, where, if you
are careful you need pay little, though, on the other hand, you could lose
a lot!

The object of the game is simply to avoid bankruptcy and so survive to as
high a level as possible. Of course, like anyone who thinks money is the
most important thing in life, you will still lose in the end (a program
with a moral!?). Your 'man' can be either a pound or a dollar sign and
you can only profit by picking up currency to match. There are, however,
Exchangers in the maze which you can use to convert yourself from sterling
to dollars and vice versa. Money can occur singly or in 'runs', and while
the latter are obviously much more profitable, if you are to reach high
levels and avoid a fiscal fiasco every single one you can grab counts.

Each correct sign gives one point, each incorrect one deducts two points,
as does blundering into walls of the maze. If you reach anything that is
grey you are instantly transported back to near the top of the screen,
and this can be bad news if it happens in the chopper section!

Program Operation

Although I have said that the program is all Basic, there is one brief
excursion into Machine Code in line 2010, but this is just a standard
Scroll routine and is only necessary because the program Pokes to the
display file, which the normal Sinclair scroll command Would have
disrupted rather badly. Old hands at ZX81-ing will also not need to be
reminded that this Poking of the display file makes possible some nasty
crashes if typing-in errors are made, so please Save a few copies before
you run the program.

A sacrificial line?

The rather weird line 9999 is also associated with Poking to the screen.
If the player ever tried to move off the top of the screen then addresses
less than the start of the display file would be poked, and since these
lie at the end of the program area (refer to Sinclair memory map),
simply playing the game could overwrite parts of your carefully typed-in
program! Extra lines could have been added in the main man-move loop to
check against this happening but would have slowed it down. So instead,
characters in line 9999 are used as an unseen barrier line that can be
Poked-at without doing any harm. Being numbered 9999 ensures that this line
remains, by definition, the final item in the program area.

The Sinclair command PRINT AT is a particularly slow one, so to avoid its
repeated use the next line of the maze and the bar graph are produced by
assigning-to and generally juggling-with strings, which are all eventually
concatenated into a single universal string U$. Everything can now be put
at the bottom of the screen using just one PRINT AT. Note also that U$ and
M$ are dimensioned, so that no matter how much juggling is done with them
they will automatically remain the correct length without needing any extra
checks (Sinclair dimensioned strings remain fixed length once declared).

Some super-slicing

A useful saver of both time and typing (for computer and user respectively)
is direct slicing, ie, rather than first assigning characters to a string
variable and then slicing that, as is often done, the slicer is placed
directly after the quotes. The program for the person trying to decipher
the program!) does not have to search for the string in a different area
-- it's right there in the line being executed. What is more, it is quite
legal on the ZX81 (or the Spectrum) to directly cascade two slicers, or
more if required, to operate on the same string, and as long as they are
enclosed in separate brackets they will be executed one after the other.
All you need to remember is that each successive slicer uses as it subject
the resulting string of all previous slicers. For example, in line 730 the
first slicer selects random-content/random-length substrings and a 'post
slicer' then trims the overall length of this to a constant thirty characters,
thereby replacing about four separate lines or more typical Basic.

Any of the 'Mid$' operations of other computers can also be easily simulated
in this way, eg.

S$=Mid$(S$,7,4)
becomes:
LET S$=S$(7 TO)(TO 4)
This is obviously NOT the same as:
S$(7 TO 4)! It also works for assigning to strings e.g.,
Mid$(A$,12,14)=B$
becomes:
LET A$=(12 TO)(TO l4)=B$

The Sinclair versions are, to my mind, logically clearer than the originals
since the figures are 'just figures' in the latter whereas the Sinclair
figures are annotated as to their actual purpose. Direct slicing is also
used in line 440 to give the ZX81 near-equivalent an ON-GOSUB function,
which is, of course, much faster than the six IF-THEN-GOSUB lines that it
replaced. Other uses of direct slicing can be seen in lines 155, 175,250,
540.

When slicing, any operations that yield non-integer results (e.g. RND) may
as well be performed without the usual INT, because during slicing the computer
will treat the numbers as integers anyway. The only difference to bear
in mind is that the numbers will effectively be rounded up or down either
side of point five whereas INT always round downwards.

Overall structure

The final shape of the mazes is determined by random choice but is tempered
by a loose statistical influence in favour of more pleasing and interesting-
looking outcomes, the actual algorithm used was evolved over quite a long
period, and being somewhat baroque in style would take almost as long for
me to describe in plain English! The number of possible different screens
is over 65 thousand, because even though a typical screenful of maze uses 100
consecutive numbers from the ZX81's 65-thousand-long sequence of pseudo-
random numbers, it could have started on any one of them, producing entirely
different results.

From line 300 to line 995 the main program flows straight through, using
only FOR-NEXT loops and frequent GOSUB cal's to the man-move subroutine,
thereby avoiding the dreaded 'tangled GOTO' style of non-structured programming.
The actual positions of these GOSUB calls had to be carefully spaced
out so that the execution time of lines between them was approximately equal
(isochronal) otherwise man-movement would have been uneven.

Note that when a GOSUB 10 is executed, the program carries through to the
exit point at line 90 before returning, but in between there is a GOSUB 50,
which means that this subroutine calls a part of itself i.e. it is recursive.
In this particular case it provides two passes through the man-move routine
for each single call to the maze-move routine.

Since the run-move routine is being called very frequently, it pays to keep
it as short as possible, so I have included only one check within it, which
looks at the man's next intended position and if it is not a clear space
then, and only then, are more detailed checks made to actually see what the
character is and what to do about it!

An array system is used for the INKEY$ check, and although somewhat wasteful
of memory (320 bytes for the array 'M'), it is by far the best method in ZX81
Basic. It is much faster than separate checks for each key and it allows
absolute freedom to designate several groups of keys all of which are usable
at any time.


