Micro Adventurer, August 1984

Thanks to arrays for the memory

Stephen Robinson's adventure explains how to use arrays in adventure
programming.


ALL OVER THE world programmers are retiring their joysticks and entering into
the realms of puzzle solving fantasy. You, the user, can become lord and
ruler of any world you care to create, where the only limitations are those
of your own imagination, be it a world of dark sorcery and barbaric lore or
far into the future where the endless stretches of the galaxy are yours to
roam in search of your fortune. There are no rules or regulations to follow
when writing an adventure as you are the creator and absolutely anything goes.

    Writing an adventure can be very satisfying as you watch your friends
trying to overcome the problems that you have set. As adventure games consist
mainly of problems and puzzles to be solved great care must be taken in their
planning stages. If the problems are too easy then the adventure becomes
boring, the challenge no longer exists and the adventure is soon completed.
Likewise, if the problems are too difficult the player may soon lose interest
or will still be trying to cross the dark foreboding abyss months later. It
is therefore very important to plan the various puzzles carefully, trying to
strike a happy medium between the two. A good idea is to invite a friend to
try the problems; this will give you some idea of the responses as it is very
hard to judge them when you know the answers.

    Many styles and techniques can be adopted when writing adventure
programs. Adventure programmers are constantly searching for new techniques
to use in their adventures, to simplify and shorten the various routines that
are used. The most efficient that I have found so far is to base the complete
system on a data array. By doing this memory is saved and the general
structure of the program is far simpler and a good deal less tedious. The
structure is formed mainly around variables that are constantly changing and
must equal certain values before the game can be completed. The Spectrum's
standard variables can be used but these are very limited unless you are
prepared to take the long approach, though I must add that this method is
very memory consuming and in an adventure program saving as much memory as
possible is the key factor. In general such a program would take two or three
times as much memory as one based on a data array.

Subscripts

    An array consists of a set of variables given the same name. In the
demonstration adventure with this article the array L() is used. This bears
no significance to the actual structure of the program as any single letter
array can be used. The variables are distinguished by a number enclosed in
brackets immediately following the array name. This is called a subscript.
The array system uses a single subscript in the form L(1), L(2), etc.

    There are various ways of using an array in adventure programs. A
separate array could be used for each section of the variables, for example
the objects could be held in the array O(), creatures or monsters in the
array M(), and so on for each of the categories. An area of memory would have
to be set aside at the start of the program by dimensioning each of the
arrays used. Using arrays in this way is fine, although if a save feature is
to be included the program would have to save each array in turn. As many
arrays could be used in the program, saving would appear clumsy and prolonged
as each array would be saved and loaded separately, with the program stopping
and starting to save each one. It would therefore be more efficient to use a
single array for the whole of the program. By combining each of the arrays
together as one, the save routine would be simplified and its presentation
greatly improved.

Reduction

    To show how using an array is better than other methods we will look at
the instruction that is used to pick up any objects that you may find. An
early system that I used would take the first three letters of the object as
the variable name for that object, the variable being equal to the location
at which the object can be found, eg. Lan would be the name given to the
variable that represents the lantern. The number stored in this variable
holds the location at which the lantern can be found. The program line to
pick up an object using this method would therefore take the form: If N$ (1
to 3) = "lan" and lan = ln then let lan = mv where ln is the variable that
holds your current location number and all objects, once they are taken, are
made to equal the value held in the variable mv.

    Although the program line itself is not really that long one must bear in
mind that the line must be used once for each object in the adventure. If the
program uses 50 objects the line will have to be entered 50 times and that
will only cater for the take routine. The same must be used for dropping
objects, printing the objects found at the various locations and to print all
of the objects that you are carrying. So using this method would be very time
consuming and a great deal heavier on the all important memory.

    With the introduction of an array in which to store the objects, all of
this can be reduced to a mere few lines. The length of the routine will
remain the same whether the adventure uses 10 or 1,000 objects. The key to
doing this is to store all of the objects in data statements somewhere within
the program and to read them into an array when and where they are needed. To
take an object using this method the program line would look like this: If
O$(1 to 3) = N$(1 to 3) and L(o)=L(ln) then let L(o) = mv The only other
lines needed in the routine are those to restore the object data and to set
up the for-next loop. The program line above is repeated in the loop once for
every object - in all, a far more efficient way of achieving the very same
result.

    To explain further the use of an array and exactly how they are used in
the program, a detailed look at the structure of one of the routines is
needed.

    Staying with the subject of manipulating the objects, the routine that
allows the player to pick the objects up starts at line 1500 of the
demonstration adventure. At this stage the program jumps to line 9600 where a
check is made to ensure that a noun has been input, in this case to see that
an object to be taken has been specified. If no object has been entered then
C$ remains blank and the response "take what" is printed to the screen.
Following this control jumps back to the start of the main loop at line 100.

    Line 1510 checks that you are not already carrying too much. In this case
the maximum number of objects allowed to be carried at any one time is set to
3. The array variable L(14) is used to store the number of objects currently
being carried. Providing this is equal to a value of less than 3 the program
is allowed to continue, otherwise a suitable response is printed and control
again jumps to the main program loop.

    Providing that you have passed this stage the program will now be at line
1515. This line firstly checks that you are inside the castle (L(25) =5) and
that you have taken the giant's golden egg. If so the giant is awoken (by
letting L(16) = 1) and there's no time to hang around for fear of being
devoured by the overweight monster.

    The following lines form the heart of the take routine. Starting at line
1520, the object data is restored. The data for the objects is held at line
9150 taking the form: DATA "object name",object number By assigning a number
to each of the objects it is far easier to manipulate them when checking that
they are at your present location. Line 1530 starts the main loop that checks
which of the objects is to be taken. In this case the value of 8 is used, as
there are 8 objects used in the adventure. This of course, would vary
according to the number of objects that you use in your own programs. The
object's name is read into O$ and its number is read into the variable O.

Matching

    The next line (1540) is where it all really happens. Firstly the program
matches the first three letters of the player's object input with the first
three letters of the contents of O$. If a match is found and the object L(o)
is equal to the player's current location number, the value L(o) is changed
to equal 10 showing that you are carrying the object. If after taking an
object you type "look" you will find that the object is no longer displayed
at that location as its value is now 10 and you are carrying it. The
inventory count is increased by 1 (ie. L(14)=L(14)+1) and the program jumps
to line 9500 where the message "OK" is printed and the program returns to
line 100 to repeat the process over again. If no match for C$ is found or the
object is not found at the current location, line 1560 responds with the
message "I don't see it here" and yes, it's back to the start of the main
loop again.

    As you can see, by applying a simple single dimension array to the
program the routines are far shorter and save much of that all important
memory for more detailed descriptions or more locations.

    When using an array it is important to remember that an area of memory
must be set aside at the start of the program. This is achieved with the DIM
statement. In the demonstration adventure the array L() is DIMensioned to 25
as only this number of variables are used in the program.

    An inventory routine is held at line 2200. This follows a similar pattern
to that of the take routine, where line 2240 prints a list of all of the
objects that are held by the player (all objects with a value equal to 10).
The variable FL is a flag that is set to zero in line 2220. If nothing is
being carried at this stage the program does not pass the if statement at
line 2240 and FL remains unchanged, in which case line 2260 prints "nothing".
If an object is equal to 10 then its corresponding string is printed and FL
is changed to 1.

Flagging

	The following shows the array L() and what each array number represents:
L(1) - Spade
L(2) - Gold piece
L(3) - Bucket
L(4) - Golden egg
L(5) - Silver key
L(6) - Golden key
L(7) - Axe
L(8) - Bean
L(13) - Equals 1 when bean is planted
L(14) - Inventory count
L(15) - Equals 1 when beanstalk has grown
L(16) - ditto when giant awakes
L(17) - ditto when hole is dug
L(18) - ditto when bean is watered
L(19) - ditto when game is opened
L(20) - ditto when tree 1 is chopped down
L(21) - ditto when tree 2 is chopped down
L(23) - ditto when gate is unlocked
L(24) - ditto when bucket is full
L(25) - Holds player's current location number

    L(1) to L(8) hold the location numbers for all of the eight objects. If
L(3) was to equal 9 then the bucket would appear at location 9, the meadow.
At the start of the program the object locations are read from the data
statement at line 9000. This scatters the various objects at different
locations according to the numbers held in the data statement. If you wanted
to make things easier in the adventure you could change all of these values
to 10. On typing inventory you will find that you are carrying every object
in the adventure, but that's cheating.

    L(13) through to L(24) are general flags used throughout the adventure to
check that various conditions have been met before  the  adventurer  may
progress through certain stages in the program. At initialisation these are
all set to zero. When a condition has been met the value of that particular
flag is changed to equal 1.

    As an example, L(23) is the flag for the castle gate. If this is locked
then L(23)=0. Once unlocked, however, the value changes to 1, showing that
the gate has been unlocked. All that now remains is for the gate to be
opened. The flag for this is held in L(19) which, having entered "open gate",
changes its value to 1 allowing you a safe passage east and into the cold
draughty castle. If at this stage the gate has not yet been unlocked the
program jumps to line 3520 where a suitable reply is printed and it's back
down the beanstalk to find the right key.

    The inventory count at L(14) keeps a record of how many objects you are
carrying (as described earlier).

    Though using an array has many advantages to adventure games writers, one
routine that is particularly improved is the ability to save an adventure at
any part during the game and then to load it back, taking up from exactly
where you left off. On any adventure of considerable size this is an
essential feature. Otherwise players would have to start the game from the
beginning every time they played.


    Fortunately the Spectrum has a save function that will save a complete
array in the form:
SAVE "file name" DATA L()
where L is the name given to that particular array. Various other features
can be added to the routine to enhance the program, such as the ability to
verify the saved array. This would give players far greater assurance,
knowing that their previous month's adventuring had not been spent in vain.

    The routine that performs this function starts at line 6500. This is the
main line in the routine as it saves the array. Really this is all that is
needed in the save routine but adding a few extra lines makes the routine far
more useful to the player. Once the array has been saved line 6510 prompts
the player to rewind the tape and prepare for verification. All prompts
printed during the save and load routines are printed to the input window at
the lower part of the screen. This is done so that they do not interfere with
the screen layout, leaving the screen clear for communication between the
player and his puppet. This is achieved by inserting "hash 1" after each
print statement. The ink colour is changed in line 6520 to the same colour as
the paper so that the filename does not appear on the screen. Line 6530
simply verifies the array.

    Once this is completed another prompt for the player is printed and
control jumps to line 500 where a description of your present location is
printed. Obviously if a save feature is used then provision must be made to
load the array back into the computer. The routine that performs this starts
at line 7000 and is achieved in a similar fashion to that of the save routine.

Completing

    I hope that this article brings many of you budding adventure writers out
of that dark uncharted forest you've been wandering around in for weeks,
looking for the answer that will solve some of your adventure writing
problems.

