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

Merlin and Co start to take on a life of their own in this installment
of Alan Davis' adventure series.

Readers who have been patiently typing in the routines from earlier
articles in the series might well be forgiven for wondering just when
the real action was going to start. Wonder no longer, my friends - the
time has come. If you'd like to get cracking straight away then load
in the program and code you saved last month, BREAK, add the program
lines in Listing 1. Notice that the old line 2000 (which contained
only a RETURN instruction) is no longer needed - if you don't delete
this, then nothing will happen at all! When you've added the new
lines, save the complete updated program and code (GOTO 9998 will do
the job for you) and then type GOTO 8010 to get the program started.

As usual, you'll find yourself in control of Merlin, though since the
program doesn't have a proper command analyser your control is only
partial, of necessity. You can move him about or check his inventory,
but he'll perform all other actions of his own accord, as the
inclination takes him. If you just sit back and watch, you'll find
that things start to happen as the real-time operations take over.
When you're tired of his interactions with Timbril (who starts off at
the same location) you can make him wander off in search of fresh
adventures with other characters. For the present, the other people
will remain immobile; independent movement is something we'll be
dealing with next month.

It's probably a good idea to type in Listing 1 as it stands, at least
in the first instance, so that you can get a good idea of the kinds of
interaction which are taking place, but these are really no more than
demonstration examples of the sort of thing that can be achieved, and
I hope you'll be able to develop the routines to devise other
interactions of your own. For this reason I want to go through this
month's listing in some detail, describing precisely what has to be
programmed to achieve the desired ends. Deep breath ... here goes.


Objects

Line 60 defines a new function FN o(x), which returns the address in
which the i coordinate of the "xth" object stored. There's going to be
a lot of manipulation of objects, and in each case we'll need to
modify the appropriate object location coordinates. The function FN
o(x) makes this just that little bit easier. Incidentally, if you were
writing a full, working adventure you wouldn't need lines 2500 and
2570. I've included these to make the program loop twice through the
interaction routines so that some kind of interaction is more likely
to occur, keeping up a more interesting screen output. (After all,
without a full adventure to play there's not much for you to do once
the program is running!) There's a small price to pay for this in that
the program doesn't run quite as fast as it would otherwise do.

The real meat of the programming starts at line 2510, which begins by
initialising the important variables. These variables will each be
assigned a numeric value corresponding to one of the characters or
objects, as follows:

fk1: the "active" character
fk2: the "passive" character
ob: object just lying about
ob1: object carried by "fk1"
ob2: object carried by "fk2"

r1 and r2 are a couple of independent random variables used mostly to
provide variety in the text output.

The first job is to determine which characters are present at Merlin's
location and to choose one of them at random (see line 2510, where the
relevant instructions are LET m = USR who: LET fk1 = PEEK (pres+INT
(RND*m))). This defines which of the characters is going to "act", and
fk1 will always be non-zero simply because Merlin, at least, will
always be present. If there are two or more characters present (i.e. m
is greater than 1) we dive back in again to assign a value to fk2, a
character which can be "acted upon" if necessary. The last statement
in line 2510 checks to see if the same character has been picked twice
- and resets fk2 if it has.


On Location

The next job is to check through the objects present on the ground at
the current location, and pick one at random (line 2520). If there
aren't any, then "ob" will be reset.

Carried objects are dealt with next: line 2530 checks through the
active character's inventory choosing an object at random (ob1).
Again, if the character is empty-handed (i.e. m = 0) then ob1 is reset
- and if a "passive" character is involved then line 2540 does a
similar job for him, assigning a value to ob2. This leaves everything
set up ready for action.

Nine possible activities are provided for, and the first is the simple
one which involves the picking up of any object which happens to be
lying around. This is done in line 2550, and since this line is
scanned every time the interaction routine is called, it's unlikely
that any object will be left lying about for long! Here, by the way,
you can see the power of the string handling functions we dealt with
in an earlier article. It doesn't matter who picks up what - this line
will generate the appropriate text. Finally, since the object has now
been picked up, we need to change its "i" coordinate to register its
new status as "carried by fk1" - and the POKE in line 2550 does just that.

The main bulk of the interaction options comes next, each one with its
own subroutine, and line 2560 selects one of these at random. It's
worth noting that each subroutine needs its own error- checking
system, as there will be times when a certain kind of action simply
won't be possible. For example, you can't have a conversation if
there's no one to talk to (line 2600), you can't drop anything if
you're empty-handed (line 2650), and you can't thieve if there's
nothing to steal, nobody to steal from, or if you're a morally upright
citizen like Merlin! (line 2900). Remember too that in an actual
adventure you'd almost certainly want to impose other conditions -
like preventing unfriendly characters from giving valuables to each
other, for example.

Once the error-trapping is out of the way, each of the sub- routines
consists really of only two parts: first, it generates the text which
needs to be printed to the screen; and second, it shuffles the
location coordinates around as necessary. Just one detailed example
should be enough to help you sort out the others, and since the
swapping routine (lines 2750 - 2780) is fairly representative we'll
use that. Line 2750 checks that there is another character present to
bargain with (fk2), that the active character has something to offer
(ob1), and that the passive character has something to swap (ob2).
Line 2760 generates the initial conversation and prints the text. Line
2770 gives the passive character the option of refusing the deal
(depending on the value of r1). If the deal goes ahead, then line 2780
prints up the appropriate text and transfers the "i" coordinates of
the two objects so that ob1 is now carried by fk2, and ob2 carried by fk1.


Spell-casting

As I've written them here, the interactions are pretty random - but
logically consistent of course. I've included the spell- casting
routine, however, as an example of the way that the actual plot of a
particular game might influence things. Here the staff and the book of
spells are assumed to be under Merlin's command so that he can recall
them by magic if they're lost or stolen - or if he's just too lazy to
pick 'em up! In a case like this the error trapping needs to be very
specific, and so lines 2950-2970 must be included to check on the
whereabouts of these particular items. If Merlin is already carrying
both these items, for example, then there's nothing to cast the Spell
of Retrieval on (line 2950). Oh yes, just one more thing - I'll leave
you to find out for yourself what the USR 65250 call does. Spell
casting, after all, is a pretty mysterious business ...

You'll notice that there's a fairly important type of activity which
isn't dealt with at all here: combat. Obviously it would be easy to
add a simple routine of the "Timbril hits Merlin with the magical
staff" variety, but this wouldn't be enough on its own. The truth is
that combat would really need a whole article devoted to it, but here
are a few suggestions which you might like to develop.

Probably the simplest way to start is to consider the individual
characters as either "friendly" or "hostile'; perhaps using an array
to store this information for all the characters (e.g. 0 = friendly: 1
= hostile). Error-trapping would then ensure that friendly characters
don't attack each other. On top of this you'll need an array to store
the "strength" of each character, and another to store the "hit
points" for each object when used as a weapon. When a character is
attacked by another, the result can be worked out by comparing the
strengths of the two combatants, taking into account the hit points of
any weapon used. The strength of the loser is then reduced by an
appropriate amount. Death can be said to occur when a character's
strength falls to zero, and a dead character can be eliminated from
the game by setting his location coordinates to some "impossible"
value - say 200.

Something like this, together with suitable text description of the
battle, would really be the bare minimum needed for convincing combat
- and you could of course go very much further. The idea of "friendly"
and "hostile" characters could be used in other ways - so that
friendly characters don't steal from each other, for example. What you
do will depend very much on the particular adventure you're writing.

Next month will see us involved in a little machine code again so that
we can get our characters moving about independently, but in the
meantime you might like to try improving on the various routines I've
suggested here, replacing them with some of your own. Be careful
though - if you start to hear screams of protest when you switch off
your Spectrum, then you're probably doing just a little TOO well ...

