REALMS OF INTERACTION
part 5 of 5
by Alan Davis
from ZX Computing, September 1986

NOTE: I've included the correction from page 7 of the same issue. JimG.

Part 5: Alan Davis explains how to get your adventure characters on
the move.

This month we'll be putting the finishing touches to our miniature
world by dealing with independent movement of the computer-controlled
characters. If you've been building up the routines from all the
previous articles you'll have noticed that so far Merlin's companions
remain stubbornly rooted to the spot (unless indulging in a bit of
thievery). The new routines for this month should get them flexing
their leg muscles ...

Actually, independent movement does pose certain problems in a general
series of articles like these, since the way you want your characters
to move will depend very much on the plot of the particular adventure
you're writing. If all you're looking for is a general background
atmosphere of bustle and vitality then random movement may be all that
you need, and in fact this is all we can sensibly deal with here. This
is the kind of movement which seems to predominate in games such as
Kim Topley's Fantasia Diamond (Hewson's) - an adventure which
positively bristles with activity. Of course this does fall short of
the pseudo- intelligent wanderings of Lestrade, in Sherlock, or of the
orc hunters in Runestone - but then we have to start somewhere!


Merlin in motion

Listing 1 gives the assembly language program you'll need to set
Merlin's chums into motion - or if you prefer use the BASIC program in
Listing 2 which will POKE the code into memory and save it. To get the
whole show on the road, load in last month's program as usual and
BREAK, load in this month's block of code, and finally add the lines
of BASIC from Listing 3. GOTO 9998 will save the whole lot in its
updated form to tape (notice that line 9998 in listing 3 replaces an
existing line in the previous program). Once everything is saved, GOTO
8010 should get the action started, and as you move Merlin around
you'll notice several new things. Timbril, for instance, will tend to
follow Merlin around - while other characters will wander about more
or less as they like, doing whatever takes their fancy.

Well, you can safely leave them to look after things while we take a
look at a few details of the programming. Whenever the machine code
routine is called (LET m = USR 65000), each character is given the
option of movement (with the exception of Merlin whose movements are
entirely under your control of course). As the program stands, there's
a 1 in 4 chance that any given character will decide to move. You can
make movement more (or less) likely by changing line 90 in the
assembler program: AND 1, for example, will increase the chance of
movement to 1 in 2. Alternatively, try POKEing different values into
65016 if you want to do the job from BASIC (POKE 65016,0 will make
them all rush around the place like mad things!)

If you want to modify the routine so that it can deal with more
characters you'll need to change the instructions at lines 60 and 200
in the assembler program. If you have X characters altogether
(including Merlin) then change line 60 to LD B,X-1 and line 200 to LD
A, X+1. Or you could POKE 65008,X-1 and POKE 65039,X+1 directly from
BASIC. If you require some characters to be kept stationary - perhaps
to do some specific task task such as guarding a route or a treasure -
no problem. When you set up your list of characters, just make sure
that all the 'mobile' ones come at the beginning of the list with the
stationary ones at the end - and then modify the machine code as above
with 'X' taking the number of mobile characters. It will then ignore
the others when it runs.

While the machine code routine is in operation, movement may be
occurring 'behind the scenes' which the player knows nothing of; but
if a character leaves or enters Merlin's current location then
obviously a text message has to be printed up announcing this.
Whenever this situation arises the routine does an immediate return to
BASIC with the variable m containing the numeric code of the character
who has just arrived or left. We need more information than this,
however, and to get it we need to PEEK 65220 which will hold one of
five possible values as follows:

1) A value of 5 indicates that a character has just arrived, in which
case a message of the type "So-and-so arrives" needs to be printed.

2) Values of 1, 2, 3 or 4 indicate that a character has just left,
moving north, south, east, or west respectively. Line 2030 of Listing
3 shows how the necessary text is generated.

Of course it's possible that no character will either enter or leave
Merlin's location during any one 'turn'. In this event the variable m
will be assigned the value zero when the return to BASIC is made, and
no text printing is required (see the conditional jump at line 2010 in
Listing 3).

The only other point worth mentioning about the movement routines
concerns the way in which Timbril appears to dog Merlin's heels. As
long as the number of followers of this kind is small, BASIC is
perfectly adequate, and line 2000 in Listing 3 does the job for us
here. All it does is compare Timbril's map coordinates with Merlin's,
making them equal if they're not already, and print text as
appropriate. You could sensibly add other conditions here, so that
"following" occurs only if the characters are in adjacent locations,
perhaps: IF ABS(PEEK(fklc+2)-io)=1 etc.


Interaction

That's about as far as we can go at present, but I'd like to spend a
little time suggesting ways in which you can develop these interaction
routines further. The obvious thing to try in the first instance is to
increase the number of characters, objects, and locations; certainly a
greater variety in the location descriptions would be no bad idea
since these have been deliberately kept to a bare minimum here. I hope
it's obvious how to go about this; it's just a matter of adding more
DATA statements to the initialisation routines in the basic module
(see the second article), dimensioning the arrays accordingly, and
modifying the appropriate numeric constants.

You may also want to "close off" certain routes in your adventure; as
things stand Merlin can move anywhere within the map. You can do this
very easily by making some of the locations "no-go" areas in a logical
way. A simple method would be to add "a mountain" to the list of
location descriptions (giving this a numeric code of 6) and then
change the contents of the array l() so that the mountains define the
routes you need. You can then add a line of BASIC thus:

245 IF v=5 AND l(io+ti,jo+tj)=6 THEN LET z$="Merlin has no
mountaineering equipment": GOSUB 100: GOTO 200.

For greater variety you could add walls, fences, impenetrable bogs,
towering cliffs ... it's up to you.

"Hang on a tick," I hear you say. "That's all very well for Merlin,
but how do I stop the other characters from blundering into bogs or
walking into walls?" Well - if you're really set on this then you've
no alternative but to rewrite the machine code movement routines,
inserting the necessary checks, but there may be no need for all this
in many cases. Remember that you are, after all, creating only an
illusion - and what the player doesn't know about he won't grieve
over. Here's a question for you: can you tell (purely by playing the
game) whether the hunter orcs in RUNESTONE move through the mountains,
or skirt around them as the player must? (There are no prizes and in
any case I'm not telling!)

Another aspect of these interaction routines which may alarm you is
the sheer amount of memory they use, leaving correspondingly less
space for your adventure. Don't worry. For a start, once you've
decided on your characters, objects and so on, you can dispense with
all those DATA statements in the initialisation section of the basic
module since the arrays will all be stored in the variables area along
with your program when you save it. (Of course this then means you'll
have to CLEAR before you load in the program rather than within it as
at present). Huge dollops of memory can be saved by replacing commonly
occurring numbers with named constants (LET L=1, LET Z=2, etc.)
Expressions like VAL "65000" will also save three bytes every time,
but don't overuse this last trick or the speed of execution of the
program will suffer. Clyde Bish's excellent RANDOM MEMORY series will
give you lots more ideas for memory saving. Remember too that the
whole point of the exercise is to make the independent characters an
integral part of your adventure. These routines and ideas shouldn't be
seen as mere window dressing or wasted space, but as a vital core from
which your adventure develops.

This brings us to the end of the "Realms" series as I'd originally
envisaged it, but I'm aware that I've left you rather badly in the
lurch. The trouble with all these interactive characters is that the
player will need to be able to talk to them - and he can't do that
with your usual VERB/NOUN BASIC command analyser, can he? Let's see -
you want a parser which will cope with complex input like "GO NORTH
AND ASK WILLIAM TO PUT THE GOLD BAR IN THE IRON CHEST" Yes? You'd like
it in machine code for an instant response? And you'd like it suitably
friendly so that it can be easily interfaced with the rest of your
BASIC program?

What you need is VENTURESPEAK. Watch this space ...

