VENTURESPEAK

ZX Computing, October, November & December 1986





Part 1: October 1986





Alan Davis, recently returned from the Realms of Interaction,

sets out once more on a quest to produce a superior command

analysis system.





It's often said that the quality of an adventure game is predominantly

determined by the originality and imaginative scope of its plot, and

really it would be hard to deny this. Virtuosity of programming, text

compression, complex language analysis, and similar sophistications

have been loudly trumpeted by many a software company, and equally

loudly hailed by many a reviewer; yet these count for nothing if the

heart of the game - its plot and atmosphere - is dull and uninspired.

All this is true, but of course there are limits It's equally possible

for an adventure to be wonderfully imaginative in concept, but

rendered almost unplayable by inordinately long response times, shabby

on-screen presentation, or sheer "unfriendliness".



It's not difficult to find examples of this second category even among

recent commercial adventures: the grotesque "Lord of the Rings" comes

most readily to mind, with its excruciatingly slow responses coupled

to a keyboard input routine whose sluggishness makes accurate entry of

commands a sore test of patience. Or how about those hordes of Quilled

adventures, essentially rapid in response, but so often suffering from

stereotyped presentation, unfriendly vocabulary and the rigid

restriction of the standard "verb/noun" input requirement.



Faced with this situation, the BASIC programmer with a yen to write

adventures may well be put off for good. Even if he opts for the

simple "verb/noun" input format, the need for a large, friendly

vocabulary necessarily implies long delays in response whenever the

program decodes the player's input and scans the vocabulary lists.

Even then, if this limitation is accepted, there are many occasions

when the "verb/noun" type of command analyser is inadequate - for the

fact remains that you just can't write an interactive "Hobbit"-style

adventure without some capability for dealing with more complex

commands.





Instant response



The obvious solution to the problem is to resort to machine code

programming in order to deal with the command analysis aspects of

adventure writing, since this has many advantages. First, program

responses can be virtually instant, regardless of size of vocabulary.

Second, complex and multiple commands (eg. PUT THE JEWEL IN THE CHEST

AND LEAVE THE ROOM) can be dealt with, again at no cost in response

time. And finally, extra facilities may be incorporated into the

command analyser to permit, say, detailed editing facilities to

improve "friendliness", or the option of "real time" operation in the

completed adventure if required.



Such a solution in turn raises its own difficulties - not least that

of interfacing the machine code routines with the rest of a

predominantly BASIC program. We must also face the problem of

(preferably) writing code which offers enough flexibility for us to

use it for any adventure we may care to write. This, in a nutshell, is

what the Venturespeak command analysis system has been designed for.

Even if you have no understanding of machine code programming, you can

use Venturespeak yourself to write sophisticated adventures which

retain the flexibility and ease of BASIC, yet which are largely free

from its speed limitations.



Venturespeak essentially consists of a single "package" which can be

conveniently divided into 3 sections as follows:



1) A keyboard input routine which accepts typed commands up to 63

   characters long, complete with single key- press facilities for

   deleting / editing commands, and a real- time option.



2) A Parser routine which decodes complex commands containing up to

   three verbs and four nouns, such as "ASK SAM TO PUT THE COIN IN THE

   PURSE", as well as permitting several commands to be strung together

   in sequence using commas, full stops, or "AND".



3) The menu-driven Venturespeak Editor which offers comprehensive and

   easy-to-use facilities for adding, deleting, or changing vocabulary.

   It is capable of generating a single block of code which incorporates

   both keyboard and parsing routines together with the vocabulary needed

   for any particular adventure.





Assembly points



This month we'll be dealing with the input routine, and the other

aspects of Venturespeak will be tackled in succeeding articles, but

before we begin I'd like to make a strong recommendation that you

equip yourself with a decent assembler program (if you don't have one

already). You can poke in the machine code routines from BASIC of

course - and I'll provide decimal dumps for those who wish to do so -

but we'll be dealing with over 1K of machine code altogether, and the

scope for errors when typing in the long lists of numbers is

considerable, even with checksums. An assembler is well worth the

investment - I use Hisoft's "DEVPAC" and find it excellent.



Now that the hors-d'oeuvres are out of the way, we can get on with

this month's main course. Before you start, type CLEAR 59999 to lower

RAMTOP so that our code can be stored safely at address 60000 and

above. Incidentally, I've chosen this address so that the Venturespeak

routines will be compatible with those from the previous "Realms of

Interaction" series, should you wish to combine them. (The code is not

relocatable).



Listing 1 gives the assembly language program for the keyboard input

routine. The code is organised at address 60000, and is 391 bytes

long. For those assemblerless individuals, Listing 2 provides the

(decimal) bytes you'll need in conjunction with the BASIC loader given

in Listing 3. Type in Listing 3, and then RUN. Just follow the prompts

the program gives you, entering the individual bytes from Listing 2

one at a time, including the checksum after every fifth byte. If a

mistake is found, the program will ask you to enter the whole of the

offending line of 5 bytes again. The screen display which builds up

should be identical to the layout of Listing 2, and this should help

you to check everything as you go along. Once the whole thing has been

entered without errors, the program will save your code to tape as

"KEYBOARD" CODE 60000,391.



What, then, does this routine do when you call it with LET m=USR

60000? Well, basically it prints a small "prompt" symbol at the bottom

of the screen and waits for you to start typing a command. Each

character you type is stored as a single byte above RAMTOP, the bytes

being stored sequentially from address 60318 (START) onwards up to a

maximum of 63 characters. When you finally press ENTER, the routine

does an immediate return to BASIC, with the total length of your typed

command held at address 60315 (COUNT). All is then ready for the

parser (which of course we don't yet have) to take over and analyse

your command. However, this is by no means all that the routine can do

for you. The following facilities are available:



1) CAPS SHIFT/0 acts just like the usual Spectrum "DELETE" key,

   erasing the last character typed.

2) CAPS SHIFT/1 deletes everything you've typed so far.

3) CAPS SHIFT/2 enables you to recall the whole of the last command

   you entered, either so that you can enter it again unchanged, or for

   editing using the "DELETE" key.





Zero time



The routine also has a built-in real time facility which operates as

follows: if nothing has been typed, then after about 10 seconds a

return to BASIC occurs with the address 60383 (TIME) holding the value

zero. If on the other hand a return to BASIC has occurred due to the

player entering a command, the address 60383 holds the value 1. This

means that on exit from the routine we can test PEEK 60383, and

execute appropriate subroutines (say for independent action of

characters) if that memory location contains zero. If on the other

hand it contains the value 1, we know that a command analysis must be

carried out first.



If you don't want your adventure to run in real time, this feature can

be suppressed by amending the code with the following POKEs: POKE

60033,0: POKE 60034,0: POKE 60035,0 (You might like to save two

versions of the code - one with real time, and one without).

Alternatively, if you want to keep the real time feature but slow down

the pace of things, try poking different values into 60032. POKE

60032,4 will give exits to BASIC every 20 seconds or so, for instance.



Still, trying all these things for yourself is much more fun than

reading about them, and Listing 4 will enable you to check the routine

out. First CLEAR 59999, load in the bytes, type in the lines of BASIC

from Listing 4 [file: keytest], and then RUN. When you see the prompt

at screen bottom, type in any old command (note that CAPS LOCK is set

automatically) and press ENTER. If all is well the lower screen will

clear, and your command will be exactly reproduced in the upper screen

(confirming that it has been stored correctly in memory).



Try pressing CAPS SHIFT/2 to check that the "recall last command"

facility is working correctly, and in addition check the delete

functions. It's clear, I hope, what the benefits of these facilities

are: suppose your last command was "ASK SAM TO ATTACK THE ORC", and

that on your next turn you'd like Sam to beat the daylights out of a

troll. All you need do is recall your previous command using CS/2,

delete the word "ORC", and add the word "TROLL" before pressing ENTER.



All OK? Fine. Make yourself a well-earned cup of coffee, for you now

have about one third of the complete Venturespeak system safely

stashed away on tape. See you next month, with the second instalment...





Assembler Listing for KEYBOARD

------------------------------



60000 3E08     KEYBD   LD   A,008

60002 326A5C           LD   (23658),A

60005 CDE2EA           CALL CLEAR

60008 CD2EEB           CALL PROMPT

60011 AF       RESET   XOR  A

60012 32785C           LD   (23672),A

60015 32795C           LD   (23673),A

60018 327A5C           LD   (23674),A

60021 329BEB           LD   (COUNT),A

60024 AF       WAIT    XOR  A

60025 32085C           LD   (23560),A

60028 3A795C   WAIT2   LD   A,(23673)

60031 FE02             CP   002

60033 D232EB           JP   NC,TIMEUP

60036 3A085C   CONT    LD   A,(23560)

60039 FE00             CP   000

60041 CA7CEA           JP   Z,WAIT2

60044 FE06             CP   006

60046 CA7BEB           JP   Z,REPEAT

60049 FE0D             CP   013

60051 CCFBEA           CALL Z,CHECKN

60054 FE00             CP   000

60056 CA78EA           JP   Z,WAIT

60059 FE0C             CP   012

60061 CCFBEA           CALL Z,CHECKN

60064 FE00             CP   000

60066 CA78EA           JP   Z,WAIT

60069 FE7B             CP   123

60071 D278EA           JP   NC,WAIT

60074 329DEB           LD   (CHR),A

60077 FE0D             CP   013

60079 CA0AEB           JP   Z,ENTER

60082 FE0C             CP   012

60084 CA55EB           JP   Z,DELETE

60087 3A9DEB           LD   A,(CHR)

60090 FE07             CP   007

60092 CA19EB           JP   Z,WIPE

60095 FE20             CP   032

60097 DA78EA           JP   C,WAIT

60100 3A9BEB           LD   A,(COUNT)

60103 FE3F             CP   063

60105 CA78EA           JP   Z,WAIT

60108 219EEB           LD   HL,START

60111 1600             LD   D,000

60113 5F               LD   E,A

60114 3A9DEB           LD   A,(CHR)

60117 19               ADD  HL,DE

60118 77               LD   (HL),A

60119 13               INC  DE

60120 CD3EEB           CALL CURSOR

60123 7B               LD   A,E

60124 329BEB           LD   (COUNT),A

60127 C378EA           JP   WAIT



60130 AF       CLEAR   XOR  A

60131 CD0116           CALL #1601

60134 CD26EB           CALL SETPR

60137 0640             LD   B,064

60139 3E20     SCAN    LD   A,032

60141 C5               PUSH BC

60142 D7               RST  #10

60143 C1               POP  BC

60144 05               DEC  B

60145 78               LD   A,B

60146 FE00             CP   000

60148 C2EBEA           JP   NZ,SCAN

60151 CD26EB           CALL SETPR

60154 C9               RET



60155 329DEB   CHECKN  LD   (CHR),A

60158 3A9BEB           LD   A,(COUNT)

60161 FE00             CP   000

60163 CA09EB           JP   Z,RESETA

60166 3A9DEB           LD   A,(CHR)

60169 C9       RESETA  RET



60170 CDE2EA   ENTER   CALL CLEAR

60173 3E01             LD   A,001

60175 32DFEB           LD   (TIME),A

60178 3A9BEB           LD   A,(COUNT)

60181 329CEB           LD   (CT2),A

60184 C9               RET



60185 AF       WIPE    XOR  A

60186 329BEB           LD   (COUNT),A

60189 CDE2EA           CALL CLEAR

60192 CD2EEB           CALL PROMPT

60195 C378EA           JP   WAIT



60198 3E16     SETPR   LD   A,022

60200 D7               RST  #10

60201 AF               XOR  A

60202 D7               RST  #10

60203 AF               XOR  A

60204 D7               RST  #10

60205 C9               RET



60206 3E3E     PROMPT  LD   A,062

60208 D7               RST  #10

60209 C9               RET



60210 3A9BEB   TIMEUP  LD   A,(COUNT)

60213 FE00             CP   000

60215 C284EA           JP   NZ,CONT

60218 CDE0EB           CALL QUIT

60221 C9               RET



60222 D5       CURSOR  PUSH DE

60223 3E11             LD   A,017

60225 D7               RST  #10

60226 3E06             LD   A,006

60228 D7               RST  #10

60229 3A9DEB           LD   A,(CHR)

60232 D7               RST  #10

60233 D1               POP  DE

60234 C9               RET



60235 3E11     SPACE   LD   A,017

60237 D7               RST  #10

60238 3E07             LD   A,007

60240 D7               RST  #10

60241 3E20             LD   A,032

60243 D7               RST  #10

60244 C9               RET



60245 3A9BEB   DELETE  LD   A,(COUNT)

60248 FE1F             CP   031

60250 CA70EB           JP   Z,TLINE

60253 3E08             LD   A,008

60255 D7               RST  #10

60256 CD4BEB   HERE    CALL SPACE

60259 3E08             LD   A,008

60261 D7               RST  #10

60262 3A9BEB           LD   A,(COUNT)

60265 3D               DEC  A

60266 329BEB           LD   (COUNT),A

60269 C378EA           JP   WAIT



60272 3E16     TLINE   LD   A,022

60274 D7               RST  #10

60275 AF               XOR  A

60276 D7               RST  #10

60277 3E1F             LD   A,031

60279 D7               RST  #10

60280 C360EB           JP   HERE



60283 3A9BEB   REPEAT  LD   A,(COUNT)

60286 FE00             CP   000

60288 C278EA           JP   NZ,WAIT

60291 CDE2EA           CALL CLEAR

60294 CD2EEB           CALL PROMPT

60297 119EEB           LD   DE,START

60300 3A9CEB           LD   A,(CT2)

60303 329BEB           LD   (COUNT),A

60306 0600             LD   B,000

60308 4F               LD   C,A

60309 CD3C20           CALL #203C

60312 C378EA           JP   WAIT



60315 00       COUNT   DEFB 0

60316 00       CT2     DEFB 0

60317 00       CHR     DEFB 0

60318 ..       START   DEFS 65

60383 00       TIME    DEFB 0



60384 32DFEB   QUIT    LD   (TIME),A

60387 CDE2EA           CALL CLEAR

60390 C9               RET





- - - - -



Part 2: November 1986





Part 2: Alan Davis' adventure series looks at command analysis.





This month brings you the second part of the VENTURESPEAK machine code

program, and we'll be taking a look at the gentle art of "parsing the

input" - or "command analysis", if you prefer.



You're going to need the machine code keyboard routine that you saved

last month, as we need to patch this month's program onto it to

produce a single block of code. Listing 1 is the assembly language

program for the "parser" - this is the program which will scan through

a typed input, checking the words against a set of vocabulary data. As

you can see it's a fairly lengthy routine so an assembler will make

error- free entry considerably easier - but if you don't have an

assembler all is not lost, since I've given a decimal dump of the code

in Listing 2. All you need to do is type in Listing 3, RUN it, and

then enter the numbers from Listing 2 in order, including the

checksums after every fifth byte. Take things slowly, checking the

screen display against the listing as you go along, and all should be

well. When you've finished, the program will save the code to tape for

you as "PARSER" CODE 60400,750.





Parsing



So far, so good, We now need to weld the keyboard and parser sections

together as follows:



1) Reset the Spectrum using RANDOMIZE USR 0.

2) Enter CLEAR 59999 as a direct command.

3) Load in the keyboard code you saved last month (LOAD "KEYBOARD" CODE).

4) Load in this month's parser code (LOAD "PARSER" CODE).

5) Now save the whole lot as a single block with

   SAVE "V-SPEAK" CODE 60000,1150 - and keep it safe somewhere until

   next month.



In addition to this single code block, it's probably wise to keep the

two separate parts as well for the present, to facilitate checking in

case you discover errors later.



Of course, you'll be wanting to know just what this new routine does,

and to test it out. We'll certainly be looking at how it works in this

article, but as for testing it - well, I'm going to ask you to be

patient and wait until next month. You see, the problem is that our

parser is actually fairly useless at present because it doesn't yet

possess a vocabulary! (Rather like a chap who, though highly

intelligent, has no background knowledge to draw upon ...) To put

vocabulary into the parser we'll need the VENTURESPEAK EDITOR - and

that's our task for next month.



---------------------------------------------

Figure 1. Vocabulary list, with each verb,

noun and object individually numbered.

         

VERBS             D      10         SHI     5         

                  DOW    10         ARM     6         

SAY     1         DES    10         BOO     7         

TEL     1         GET    11         CHE     8         

ASK     1         TAK    11         BOX     9         

TAL     1         PIC    11         DOO    10         

L       2         DRO    12         

LOO     2         PUT    12         

N       3         EXA    13         PEOPLE         

NOR     3         REA    13         

S       4         GIV    14         SAM     1         

SOU     4         OFF    14         FRE     2         

E       5         FIG    15         PET     3         

EAS     5         KIL    15         JOH     4         

W       6         ATT    15         JAC     5         

WES     6         HIT    15         JOE     6         

IN      7         

ENT     7         

OUT     8         OBJECTS         

LEA     8         

U       9         SWO     1         

UP      9         DAG     2         

CLI     9         SPE     3         

ASC     9         KNI     4         

---------------------------------------------



For the present though, I'm going to explain the basic principles

underlying the parsing system so that when the time comes for you to

use it you'll be familiar with all the main features, We can't discuss

this in a vacuum, so in Figure 1 I've given a very elementary

vocabulary of words which you might expect to find in a typical

adventure (printed out from the EDITOR program, in fact). Figure 1

itself raises a few points which need to be mentioned before we go any

further:



1) Only the first three letters of any word are significant. This can

   occasionally give rise to some confusion because the parser can't

   distinguish between words such as "RAVEN" or "RAVINE", although in

   practice I've never found this to be a serious problem, myself. (My

   game "RUNESTONE" uses only three-letter parsing).



2) Vocabulary is divided into three distinct types: VERBS, OBJECTS and

   PEOPLE. This has advantages over the usual simpler sub-division into

   VERBS and NOUNS because it helps the error-trapping process when you

   write your adventure, as you'll see later.



3) Each item of vocabulary is assigned a number between 1 and 254

   inclusive. Synonyms are catered for by assigning the same number to

   different words, so that the verbs SAY, TELL, ASK, and TALK, for

   example, are all assigned the number 1. This is a good place to make

   an IMPORTANT NOTE: generally you can assign any number you like to any

   verb you like, BUT IT IS ESSENTIAL THAT ALL VERBS IMPLYING SPEECH BE

   ASSIGNED THE NUMBER 1, if the parser routine is to work correctly.





Input



In practice what happens will be something like this. Your BASIC

adventure program will invite input from the player by invoking the

keyboard routine: LET M=USR 60000. The player then types in his

command, presses ENTER when he's finished, and the routine returns to

BASIC having stored the player's input as a string of bytes in the

correct addresses above RAMTOP. We now want the parser to scan this

stored command and decode it, so the next step is to call the parser

routine with LET M=USR 60400. The parser now scans through the

player's command, character by character, checking the words it finds

against those in its vocabulary, ignoring any words it fails to

recognise and skipping on to the next. It eventually stops, either

when it reaches the end, or when it reaches a comma, full stop, or the

word "AND" (these last items signifying that the player has typed in

several commands at one go) and returns to BASIC.



The parser having done its job (almost instantaneously of course), we

need to extract the fruits of its labours by PEEKing certain

addresses. It makes for an easier life if the results of these PEEKs

are assigned immediately to BASIC variables with suitably

memory-jogging names, like this:

LET TELL=PEEK 61124

LET PERS=PEEK 61125

LET VB1=PEEK 61126

LET VB2=PEEK 61127

LET FK1=PEEK 61129

LET OB1=PEEK 61131

LET OB2=PEEK 61132

LET MORE=PEEK 61123



What this all amounts to is that you can extract from any one command

the code numbers for up to three verbs, two objects, and two people -

so that your BASIC program can then perform the necessary condition

tests appropriate to your adventure. A few examples should make things

clear.





---------------------------------------------

Figure 2. Examples of command analysis

                                

EXAMINE THE DAGGER              PUT THE BOOK IN THE CHEST       

                                

             A                               C

                                

     COMMAND ANALYSIS                COMMAND ANALYSIS           

                                

                                

     TELL:      0                    TELL:      0               

     PERS:      0                    PERS:      0               

                                

     VB1 :      13                   VB1 :      12              

     VB2 :      0                    VB2 :      7               

                                

     FK1 :      0                    FK1 :      0               

                                

     OB1 :      2                    OB1 :      7               

     OB2 :      0                    OB2 :      8               

                                

                                

                                

SAY TO FRED "EXAMINE THE DAGGER"ASK PETER TO GIVE THE KNIFE TO J

                                OHN

             B                               D

                                

     COMMAND ANALYSIS                COMMAND ANALYSIS           

                                

                                

     TELL:      1                    TELL:      1               

     PERS:      2                    PERS:      3               

                                

     VB1 :      13                   VB1 :      14              

     VB2 :      0                    VB2 :      0               

                                

     FK1 :      0                    FK1 :      4               

                                

     OB1 :      2                    OB1 :      4               

     OB2 :      0                    OB2 :      0               

                                

                                

---------------------------------------------





Examining



Figure 2 gives examples of the analysis of a range of commands

involving the basic vocabulary of Figure 1. (You might like to know

that these figures are all screen dumps from the VENTURESPEAK EDITOR

in "test" mode). Let's start with the first and simplest command -

2(a): "EXAMINE THE DAGGER". Only two words are really relevant here -

the verb "EXAMINE", and the noun (in this case an object) "DAGGER".

You'll see in the example that the parser has assigned the value 13 to

VB1, 2 to OB1, and zero to everything else. Now look back at the

vocabulary list in Figure 1, where you'll find that verb number 13 is

"EXA" (for "examine"), and that object number 2 is "DAG" (for

"dagger"). Makes sense? OK, then let's try something a little more

complex.



The second example, Figure 2(b), shows the analysis of the command

"SAY TO FRED "EXAMINE THE DAGGER"" and we find VB1 and OB1 assigned

just the same values as before (as we'd expect) but look: this time

the variable TELL takes the value 1I (signifying speech) and the

variable PERS is given the value 2 (the number for Fred) corresponding

to the person being addressed. Note that TELL is really only a flag

which takes the value 1 or 0 according to whether speech is signified

or not; it's the variable PERS which conveys the information about

whom the player is trying to speak to.



So why do we need the extra variables on VB2 and OB2? Well, sometimes

commands may involve two objects - and there may be instances when you

want to distinguish between two slightly different types of action,

such as putting objects ON or IN other subjects. Figure 2(c) shows the

analysis of the command "PUT THE BOOK IN THE CHEST". See how the two

verbs "PUT" (12) and "IN" (7) are picked up here, together with the

two objects in order: "BOOK" (7) and "CHEST" (8).



The final example, 2(d) is of the type where speech to one person

involves some kind of action with yet another person. And so the

command "ASK PETER TO GIVE THE KNIFE TO JOHN" sets the speech flag

(TELL) and sets PERS to 3 ("PETER"). As we'd expect, VB1 is 14

("GIVE") and OB1 is 4 ("KNIFE") but in addition to this, FK1 has

picked up the other person involved in the transaction ("JOHN"=4). We

see here, by the way, how the separation of nouns into PEOPLE and

OBJECTS eases the error checking process needed in every adventure. If

a command is found to contain a verb such as "GIVE" or "FIGHT" (where

some other person must of necessity be specified), it can be rejected

as an unacceptable entry without further enquiry if FK1 is zero.

Example 2(d) also illustrates the essential friendliness of

VENTURESPEAK, particularly where speech commands are concerned. It

matters not a jot what style of entry is used by the player - SAY TO

PETER "GIVE JOHN THE KNIFE" for example, will be decoded with complete

success by the parser.



I haven't mentioned how the system copes with multiple commands yet.

Suppose the command GET THE SWORD AND GO NORTH has been entered. The

parser will analyse the first part (GET THE SWORD) and then return to

BASIC, but it will remember how far along the command it has scanned.

If we LET MORE=PEEK 61123 (see above), the variable MORE will be

assigned the value 1 - telling us in effect that another part of the

command remains to be analysed. (For single commands MORE will be

zero). This means we can arrange for the first command to be processed

by an appropriate BASIC subroutine, and then test the variable MORE to

see whether another analysis should follow, or whether a return to

keyboard control is called for. However, the re-entry point to the

parser routine is different should a continuation of analysis be

necessary - on such occasions the parser is called with LET M=USR

60426. (This is because the usual entry at USR 60000 involves a

tidying-up process which would cause the parser to "forget" the

position it had reached on its previous scan).



A typical programming "flow chart", therefore, would be something like this:



(1) CALL KEYBOARD ROUTINE (USR 60000)

(2) CALL PARSER ROUTINE (USR 60400)

(3) PROCESS COMMAND IN BASIC

(4) IF MORE THEN LET M=USR 60426: GOTO (3)

(5) GO BACK TO (1)



I hope that by now you've begun to get some idea, in principle, of

what VENTURESPEAK can do for your adventure writing. If you're burning

for some "hands-on" experience, don't worry. You'll be able to try out

all these examples (and as many others as you wish) yourself with the

help of the EDITOR program next time, when I'll also be offering more

detailed explanations of how to incorporate the system into your own

programs, Till then ...





Assembler Listing for PARSER

----------------------------



60400 219EEB   INIT    LD   HL,START

60403 22BEEE           LD   (NCOM),HL

60406 22C0EE           LD   (PTR),HL

60409 3A9BEB           LD   A,(COUNT)

60412 5F               LD   E,A

60413 1600             LD   D,000

60415 19               ADD  HL,DE

60416 3EFF             LD   A,255

60418 77               LD   (HL),A

60419 AF               XOR  A

60420 32C4EE           LD   (TELL),A

60423 32C5EE           LD   (PERS),A

60426 AF       RESTRT  XOR  A

60427 32C6EE           LD   (VB1),A

60430 32C7EE           LD   (VB2),A

60433 32C8EE           LD   (VB3),A

60436 32C9EE           LD   (FK1),A

60439 32CAEE           LD   (FK2),A

60442 32CBEE           LD   (OB1),A

60445 32CCEE           LD   (OB2),A

60448 CD74EC           CALL COMMA

60451 2AC0EE   LOOP8   LD   HL,(PTR)

60454 AF               XOR  A

60455 32DAEE           LD   (EXTR),A

60458 CD9AEC           CALL FILTER

60461 3ADAEE           LD   A,(EXTR)

60464 FE01             CP   001

60466 CA4FEC           JP   Z,SORT

60469 2AC0EE           LD   HL,(PTR)

60472 7E               LD   A,(HL)

60473 FEFF             CP   255

60475 CA4FEC           JP   Z,SORT

60478 FE2C             CP   044

60480 CA4BEC           JP   Z,END

60483 FE2E             CP   046

60485 CA4BEC           JP   Z,END

60488 C323EC           JP   LOOP8

60491 23       END     INC  HL

60492 22C0EE           LD   (PTR),HL

60495 3AC6EE   SORT    LD   A,(VB1)

60498 FE01             CP   001

60500 CC58EC           CALL Z,SWAP

60503 C9               RET



60504 32C4EE   SWAP    LD   (TELL),A

60507 3AC7EE           LD   A,(VB2)

60510 32C6EE           LD   (VB1),A

60513 3AC8EE           LD   A,(VB3)

60516 32C7EE           LD   (VB2),A

60519 3AC9EE           LD   A,(FK1)

60522 32C5EE           LD   (PERS),A

60525 3ACAEE           LD   A,(FK2)

60528 32C9EE           LD   (FK1),A

60531 C9               RET



60532 2ABEEE   COMMA   LD   HL,(NCOM)

60535 7E       LOOP    LD   A,(HL)

60536 FEFF             CP   255

60538 CA95EC           JP   Z,ENDCOM

60541 FE2C             CP   044

60543 CA8BEC           JP   Z,SETCOM

60546 FE2E             CP   046

60548 CA8BEC           JP   Z,SETCOM

60551 23               INC  HL

60552 C377EC           JP   LOOP

60555 23       SETCOM  INC  HL

60556 22BEEE           LD   (NCOM),HL

60559 3E01             LD   A,001

60561 32C3EE           LD   (MORE),A

60564 C9               RET

60565 AF       ENDCOM  XOR  A

60566 32C3EE           LD   (MORE),A

60569 C9               RET



60570 7E       FILTER  LD   A,(HL)

60571 FE22             CP   034

60573 CCF6EC           CALL Z,SKIPSP

60576 FE20             CP   032

60578 CCF6EC           CALL Z,SKIPSP

60581 FE3A             CP   058

60583 CCF6EC           CALL Z,SKIPSP

60586 FEFF             CP   255

60588 C8               RET  Z

60589 FE2C             CP   044

60591 C8               RET  Z

60592 FE2E             CP   046

60594 C8               RET  Z

60595 23               INC  HL

60596 7E               LD   A,(HL)

60597 FE20             CP   032

60599 CA0BED           JP   Z,SINGLE

60602 FE3A             CP   058

60604 CA0BED           JP   Z,SINGLE

60607 FE2C             CP   044

60609 CA0BED           JP   Z,SINGLE

60612 FE2E             CP   046

60614 CA0BED           JP   Z,SINGLE

60617 FE22             CP   034

60619 CA0BED           JP   Z,SINGLE

60622 FEFF             CP   255

60624 CA0BED           JP   Z,SINGLE

60627 23               INC  HL

60628 7E               LD   A,(HL)

60629 FE20             CP   032

60631 CA28ED           JP   Z,DOUBLE

60634 FE2C             CP   044

60636 CA28ED           JP   Z,DOUBLE

60639 FE2E             CP   046

60641 CA28ED           JP   Z,DOUBLE

60644 FE22             CP   034

60646 CA28ED           JP   Z,DOUBLE

60649 FE3A             CP   058

60651 CA28ED           JP   Z,DOUBLE

60654 FEFF             CP   255

60656 CA28ED           JP   Z,DOUBLE

60659 C3ACED           JP   TRIPLE

60662 23       SKIPSP  INC  HL

60663 7E               LD   A,(HL)

60664 FE20             CP   032

60666 CAF6EC           JP   Z,SKIPSP

60669 FE22             CP   034

60671 CAF6EC           JP   Z,SKIPSP

60674 FE3A             CP   058

60676 CAF6EC           JP   Z,SKIPSP

60679 22C0EE           LD   (PTR),HL

60682 C9               RET



60683 2AC0EE   SINGLE  LD   HL,(PTR)

60686 7E               LD   A,(HL)

60687 CD81ED           CALL SETPTR

60690 ED5BCDEE         LD   DE,(VCV1)

60694 47               LD   B,A

60695 1A       LOOP1   LD   A,(DE)

60696 FEFF             CP   255

60698 C8               RET  Z

60699 32C2EE           LD   (TPNO),A

60702 13               INC  DE

60703 1A               LD   A,(DE)

60704 B8               CP   B

60705 CA56ED           JP   Z,VBFND

60708 13               INC  DE

60709 C317ED           JP   LOOP1



60712 2AC0EE   DOUBLE  LD   HL,(PTR)

60715 7E               LD   A,(HL)

60716 ED5BCFEE         LD   DE,(VCV2)

60720 47               LD   B,A

60721 23               INC  HL

60722 7E               LD   A,(HL)

60723 4F               LD   C,A

60724 CD81ED           CALL SETPTR

60727 1A       LOOP3   LD   A,(DE)

60728 FEFF             CP   255

60730 C8               RET  Z

60731 32C2EE           LD   (TPNO),A

60734 13               INC  DE

60735 1A               LD   A,(DE)

60736 67               LD   H,A

60737 13               INC  DE

60738 1A               LD   A,(DE)

60739 6F               LD   L,A

60740 78               LD   A,B

60741 BC               CP   H

60742 CA4DED           JP   Z,FND1

60745 13               INC  DE

60746 C337ED           JP   LOOP3

60749 79       FND1    LD   A,C

60750 BD               CP   L

60751 CA56ED           JP   Z,VBFND

60754 13               INC  DE

60755 C337ED           JP   LOOP3

60758 3AC6EE   VBFND   LD   A,(VB1)

60761 FE00             CP   000

60763 C265ED           JP   NZ,VB1DUN

60766 3AC2EE           LD   A,(TPNO)

60769 32C6EE           LD   (VB1),A

60772 C9               RET

60773 3AC7EE   VB1DUN  LD   A,(VB2)

60776 FE00             CP   000

60778 C274ED           JP   NZ,VB2DUN

60781 3AC2EE           LD   A,(TPNO)

60784 32C7EE           LD   (VB2),A

60787 C9               RET

60788 3AC8EE   VB2DUN  LD   A,(VB3)

60791 FE00             CP   000

60793 C0               RET  NZ

60794 3AC2EE           LD   A,(TPNO)

60797 32C8EE           LD   (VB3),A

60800 C9               RET



60801 23       SETPTR  INC  HL

60802 F5               PUSH AF

60803 7E       LOOP2   LD   A,(HL)

60804 FE20             CP   032

60806 CAA6ED           JP   Z,NEWWD

60809 FE22             CP   034

60811 CAA6ED           JP   Z,NEWWD

60814 FE3A             CP   058

60816 CAA6ED           JP   Z,NEWWD

60819 FEFF             CP   255

60821 CAA7ED           JP   Z,LAST

60824 FE2C             CP   044

60826 CAA7ED           JP   Z,LAST

60829 FE2E             CP   046

60831 CAA7ED           JP   Z,LAST

60834 23               INC  HL

60835 C383ED           JP   LOOP2

60838 23       NEWWD   INC  HL

60839 22C0EE   LAST    LD   (PTR),HL

60842 F1               POP  AF

60843 C9               RET



60844 2AC0EE   TRIPLE  LD   HL,(PTR)

60847 7E               LD   A,(HL)

60848 CD64EE           CALL AND

60851 FE01             CP   001

60853 C8               RET  Z

60854 2AC0EE           LD   HL,(PTR)

60857 7E               LD   A,(HL)

60858 32D7EE           LD   (CHR1),A

60861 23               INC  HL

60862 7E               LD   A,(HL)

60863 32D8EE           LD   (CHR2),A

60866 23               INC  HL

60867 7E               LD   A,(HL)

60868 32D9EE           LD   (CHR3),A

60871 CD81ED           CALL SETPTR

60874 ED5BD1EE         LD   DE,(VCV3)

60878 1A       LOOP5   LD   A,(DE)

60879 FEFF             CP   255

60881 CAF5ED           JP   Z,DUNVBS

60884 CD49EE           CALL SHORT1

60887 CAE0ED           JP   Z,VBMCH1

60890 13               INC  DE

60891 13               INC  DE

60892 13               INC  DE

60893 C3CEED           JP   LOOP5

60896 CD54EE   VBMCH1  CALL SHORT2

60899 CAEBED           JP   Z,VBMCH2

60902 13               INC  DE

60903 13               INC  DE

60904 C3CEED           JP   LOOP5

60907 CD5CEE   VBMCH2  CALL SHORT3

60910 CA56ED           JP   Z,VBFND

60913 13               INC  DE

60914 C3CEED           JP   LOOP5



60917 ED5BD3EE DUNVBS  LD   DE,(VCOB)

60921 1A       LOOP6   LD   A,(DE)

60922 FEFF             CP   255

60924 CA20EE           JP   Z,DUNOBJ

60927 CD49EE           CALL SHORT1

60930 CA0BEE           JP   Z,OBMCH1

60933 13               INC  DE

60934 13               INC  DE

60935 13               INC  DE

60936 C3F9ED           JP   LOOP6

60939 CD54EE   OBMCH1  CALL SHORT2

60942 CA16EE           JP   Z,OBMCH2

60945 13               INC  DE

60946 13               INC  DE

60947 C3F9ED           JP   LOOP6

60950 CD5CEE   OBMCH2  CALL SHORT3

60953 CA7EEE           JP   Z,OBFND

60956 13               INC  DE

60957 C3F9ED           JP   LOOP6



60960 ED5BD5EE DUNOBJ  LD   DE,(VCFK)

60964 1A       LOOP7   LD   A,(DE)

60965 FEFF             CP   255

60967 C8               RET  Z

60968 CD49EE           CALL SHORT2

60971 CA34EE           JP   Z,FKMCH1

60974 13               INC  DE

60975 13               INC  DE

60976 13               INC  DE

60977 C324EE           JP   LOOP7

60980 CD54EE   FKMCH1  CALL SHORT2

60983 CA3FEE           JP   Z,FKMCH2

60986 13               INC  DE

60987 13               INC  DE

60988 C324EE           JP   LOOP7

60991 CD5CEE   FKMCH2  CALL SHORT3

60994 CA9EEE           JP   Z,FKFND

60997 13               INC  DE

60998 C324EE           JP   LOOP7



61001 32C2EE   SHORT1  LD   (TPNO),A

61004 13               INC  DE

61005 1A               LD   A,(DE)

61006 47               LD   B,A

61007 3AD7EE           LD   A,(CHR1)

61010 B8               CP   B

61011 C9               RET

61012 13       SHORT2  INC  DE

61013 1A               LD   A,(DE)

61014 47               LD   B,A

61015 3AD8EE           LD   A,(CHR2)

61018 B8               CP   B

61019 C9               RET

61020 13       SHORT3  INC  DE

61021 1A               LD   A,(DE)

61022 47               LD   B,A

61023 3AD9EE           LD   A,(CHR3)

61026 B8               CP   B

61027 C9               RET



61028 FE41     AND     CP   065

61030 C0               RET  NZ

61031 23               INC  HL

61032 7E               LD   A,(HL)

61033 FE4E             CP   078

61035 C0               RET  NZ

61036 23               INC  HL

61037 7E               LD   A,(HL)

61038 FE44             CP   068

61040 C0               RET  NZ

61041 CD8BEC           CALL SETCOM

61044 3E01             LD   A,001

61046 32DAEE           LD   (EXTR),A

61049 2B               DEC  HL

61050 CD81ED           CALL SETPTR

61053 C9               RET



61054 3AC2EE   OBFND   LD   A,(TPNO)

61057 47               LD   B,A

61058 3ACBEE           LD   A,(OB1)

61061 B8               CP   B

61062 C8               RET  Z

61063 FE00             CP   000

61065 C291EE           JP   NZ,OB1DUN

61068 78               LD   A,B

61069 32CBEE           LD   (OB1),A

61072 C9               RET

61073 3ACCEE   OB1DUN  LD   A,(OB2)

61076 B8               CP   B

61077 C8               RET  Z

61078 FE00             CP   000

61080 C0               RET  NZ

61081 78               LD   A,B

61082 32CCEE           LD   (OB2),A

61085 C9               RET



61086 3AC2EE   FKFND   LD   A,(TPNO)

61089 47               LD   B,A

61090 3AC9EE           LD   A,(FK1)

61093 B8               CP   B

61094 C8               RET  Z

61095 FE00             CP   000

61097 C2B1EE           JP   NZ,FK1DUN

61100 78               LD   A,B

61101 32C9EE           LD   (FK1),A

61104 C9               RET

61105 3ACAEE   FK1DUN  LD   A,(FK2)

61108 B8               CP   B

61109 C8               RET  Z

61110 FE00             CP   000

61112 C0               RET  NZ

61113 78               LD   A,B

61114 32CAEE           LD   (FK2),A

61117 C9               RET



60318          START   EQU  60318

60315          COUNT   EQU  60315

61118 0000     NCOM    DEFW 0

61120 0000     PTR     DEFW 0

61122 00       TPNO    DEFB 0

61123 00       MORE    DEFB 0

61124 00       TELL    DEFB 0

61125 00       PERS    DEFB 0

61126 00       VB1     DEFB 0

61127 00       VB2     DEFB 0

61128 00       VB3     DEFB 0

61129 00       FK1     DEFB 0

61130 00       FK2     DEFB 0

61131 00       OB1     DEFB 0

61132 00       OB2     DEFB 0

61133 0000     VCV1    DEFW 0

61135 0000     VCV2    DEFW 0

61137 0000     VCV3    DEFW 0

61139 0000     VCOB    DEFW 0

61141 0000     VCFK    DEFW 0

61143 00       CHR1    DEFB 0

61144 00       CHR2    DEFB 0

61145 00       CHR3    DEFB 0

61146 00       EXTR    DEFB 0





- - - - -



Part 3: December 1986





Alan Davis puts the finishing touches to his Venturespeak Editor.





The story so far:



You are in your living room. You can see a ZX Spectrum, several copies

of ZX Computing Monthly, and a large chunk of VENTURESPEAK machine

code saved on tape. What now?

	WRITE ADVENTURE

You can't do that.

	EXAMINE TAPE

There's something missing.

	HELP

You need the 	VENTURESPEAK editor ...



Indeed you do, and here it is.



Type in Listing 1 and save it to tape with SAVE "EDITOR" LINE 1.

Rewind the tape and verify, and then stop the tape at that point - we

need to save the code from the previous articles after the editor

program so that it can be loaded automatically (see Line 4 of Listing

1). To do this, enter CLEAR 59999 as a direct command, load in the

1150 bytes you stashed away last month, and save it directly after the

EDITOR program with SAVE "V-SPEAK" CODE 60000,1150.





Figure 1 - sample screens from the editor

---------------------------------------------

1(A) Main Menu

                                

            SELECT:             

                                

1: Edit verbs                   

2: Edit objects                 

3: Edit people                  

4: POKE vocabulary into memory  

5: Save vocab. array to tape    

6: Load vocab. array from tape  

7: Hard copy of vocabulary      

8: Test Venturespeak system     



---------------------------------------------

1(B) Verbs Editor, Page 0



         WORD   NO.             

          SAY    1              

          TEL    1              

          ASK    1              

          TAL    1              

          L      2              

          LOO    2              

          N      3              

          NOR    3       VERBS  

          S      4              

       >> SOU    4 <<    Page 0 

          E      5              

          EAS    5              

          W      6              

          WES    6              

          IN     7              

          ENT    7              

          OUT    8              

          LEA    8              

          U      9              

          UP     9              

6=cursor up        7=cursor down

5&8=change page    q=main menu

ENTER=add/edit vocabulary item



---------------------------------------------

1(C) Verbs Editor, Page 1



         WORD   NO.             

          CLI    9              

          ASC    9              

          D     10              

          DOW   10              

          DES   10              

          GET   11              

          TAK   11              

          PIC   11       VERBS  

          DRO   12              

          PUT   12       Page 1 

          EXA   13              

          REA   13              

          GIV   14              

          OFF   14              

          FIG   15              

          KIL   15              

          ATT   15              

          HIT   15              

       >>          <<           

                                

6=cursor up        7=cursor down

5&8=change page    q=main menu

ENTER=add/edit vocabulary item



---------------------------------------------

1(D) Generator of parser code with vocabulary



    POKEing vocabulary bytes    

                                

                                

                                

                                

    61354   255                 

                                

Vocabulary stored from          

61150 to 61354 inclusive        

                                

                                

PRESS "Q" TO RETURN TO MENU OR  

ANY OTHER KEY TO SAVE COMPLETE  

PARSER PLUS VOCABULARY          

(1355 bytes starting at 60000)  

                                

---------------------------------------------





All set? OK - rewind the tape, type LOAD "", and wait for the whole

thing to load in. You should then be greeted on screen with the main

menu, which should look like Figure 1(a). It does? So far, so good.

Press "1" to select the "Edit verbs" option, and you should get a

screen looking like Figure 1(b) - except that of course none of the

verbs will be there since you haven't put any in yet! Press ENTER, and

you'll be asked to type in a verb - reply with the verb TELL. Then

you'll be asked to type in the number of this verb - respond with the

number 1. Hey Presto: the entry TEL#1 will appear on screen, with the

cursor automatically moving down a line ready for your next input.

(Remember that all words are truncated to their first three letters,

regardless of how many you actually type in.)



Try entering other verbs in the same way - use Figures 1(b) and 1(c)

as a guide, if you like - and notice how the editor looks after you

when you reach the bottom of the screen by clearing "Page 0" and

starting afresh at the top of "Page 1". 'Ah yes," you say, "That's all

very well, but I happened to make a mistake on Page 0. What can I do

about that?" Have no fear. At any stage you can add new entries, or

change existing entries, by skipping through them using the 5, 6, 7

and 8 keys. Use keys 5 and 8 to change pages (5 decreases page number

while 8 increases it), and use keys 6 and 7 to move the cursor up and

down the list. Position the cursor at the entry you want to change,

press ENTER, and type in the amendment. The old entry will be deleted,

and the new one inserted in its place. If you want to delete an entry

completely, without replacement, just type a space when the program

prompts you to enter a verb. It's probably obvious (but I'll say it .

anyway), that since entries are always inserted at the current cursor

position, you'll need to skip through to the end of the file to make

new additions after making an amendment - or if you prefer, you can

return to the main menu and select option "1" again, when the program

will automatically position the cursor at the end of the file for you.





Verbs



This is a good place to remind you that verbs related to speech, such

as TELL, SAY or ASK, must be assigned the number 1. Apart from this

you can allocate any number up to 254 to any verb (allocating the same

number to synonyms, of course). The order in which they occur in the

list is quite irrelevant. I should also point out that any

abbreviation you'd like the parser to accept (such as "N" for "NORTH")

must be entered separately as a synonym in its own right - there are

plenty of examples of this in Figures 1(b) and 1(c).



Once you've become used to the editing system, press "q" to return to

the main menu, and try selecting options 2 and 3. You'll find that the

method of adding entries to the "people" and "objects" vocabulary

files is just the same; the program asks you first for the word, then

for its number, whenever you press ENTER. Easy, isn't it? Don't worry

about making illegal entries by mistake - the editor is very

extensively error-trapped, and it should be virtually impossible to

crash it by accident.



What about those other options on the main menu? Option 4 ("POKE

vocabulary") does require a little explanation. You see, in any of the

3 "Edit" modes, all you're actually doing is manipulating the contents

of a temporary file - In fact it's a BASIC array, v$(). When you're

happy that all the vocabulary you need has been added, selecting

option 4 causes the editor to POKE your vocabulary into memory above

RAMTOP, making the appropriate modifications to the VENTURESPEAK

machine code as necessary. Once this is finished, the program will

offer to save the complete parser code (including vocabulary) to tape,

informing you where in memory it resided, and how long it is. (See

Figure 1(d)). This is the final chunk of code which you'll

subsequently incorporate into your adventure.





Files



Options 5 and 6 on the main menu improve the versatility of the editor

program, allowing you to save and load the temporary vocabulary file,

v$(), to and from tape. Suppose, for example, that you've just spent a

session entering vocabulary, but wish to stop and continue some other

time. All you need to do is save what you've done so far using option

5 and then load it back into the editor at the start of your next

session, using option 6. Actually, I strongly recommend that you save

the temporary file as well as the completed code even when you think

you've finished, just as a matter of course. The reason for this is

that when you come to play-test your adventure game eventually, you're

almost certain to want to make additions or modifications to the

vocabulary at some stage - and there's no way of modifying the code

itself from within the editor. However, if you've saved the temporary

array there's no problem. Just load it into the editor using option 6,

make your amendments, and then generate a fresh batch of code (using

option 4) to replace the old one.



Of the other options on the main menu, number 7 is self- explanatory.

This gives you a hard copy of the entire vocabulary file for future

reference. The only comment worth making here is that the print-out is

produced from the temporary file v$(), rather than from the finished

code - so you can get hard copy whether or not you've previously used

option 4 to POKE in the vocabulary.



The last option, number 8, allows you to test the command analysis

system in situ, but note that the editor won't let you try this unless

you've first POKEd in the vocabulary by using option 4. I went into

details of the method of command analysis last month, and now you can

try out some of those examples for yourself using this facility. Just

type in your command when you see the little "prompt" symbol, and the

system will do a complete analysis for you.



There are one or two other points I should make about the editor

itself. With the program as written, each of the three vocabulary

files can hold up to 200 entries - giving you a maximum vocabulary of

600 words. This will almost certainly give you adequate scope - and

increasing the limit needlessly will merely increase saving and

loading times for the temporary array. However, there's nothing to

stop you increasing the limit if you wish to do so; you simply need to

change the value assigned to the variable "max" in line 10 of listing

1. It should be assigned a value of (1 + some multiple of 20); LET max

= 401, for instance, will give you scope for up to 400 entries in each

file. One further point about the editor is that you can use the POKE

vocabulary option as many times as you like within a session; it will

just overwrite whatever went before.



Now that you have the editor, you're in the happy position of being

able to produce a machine code parser for any adventure you care to

write - but a few tips about incorporating it into a BASIC adventure

program may not go amiss. You'll need to CLEAR 59999, of course, so

that your parser can be safely loaded in at address 60000. If you've

written adventures in BASIC already then you should have no problems,

but I've given in Listing 2 [file: outline] a suggested outline

structure (it is no more than a mere outline) which you might find

helpful. The significance of the various symbols was explained in last

month's article. Essentially the purpose of the parser is to translate

an English sentence into a series of numbers on which condition tests

can be performed, and of course the use you make of it lies entirely

in your own hands. Nevertheless, there are methods of working which

lend themselves well to the VENTURESPEAK system.





Objects



For instance, one sensible approach might be to store all your subject

descriptions in a series of DATA statements in exactly the same order

as they appear in the vocabulary file. Thus we might have lines such as:



9001 DATA "bright sword"

9002 DATA "sharp dagger"

9003 DATA "long spear'

9004 DATA "large chest"

etc.



You'd then arrange your vocabulary so that "SWO" is assigned the

number 1, "DAG" the number 2, "SPE" the number 3, and "CHE" the number

4. In this way, values of ob1 and ob2 extracted from the parser can be

related directly to specific data items for printing messages. Thus a

command like "PUT THE SWORD IN THE CHEST" when analysed would give

ob1=1 and ob2=4. Then in your "putting" subroutine you'd have a line like:

RESTORE (9000+ob1): READ x$: RESTORE (9000+ob2): READ y$:

PRINT "You put the ";x$;" in the ";y$;"."

This would produce the message "You put the bright sword in the large

chest" - assuming of course that the necessary logical tests have been

satisfied.



You can use similar tricks for dealing with more complex commands

involving other characters. Thus you might list characters' names in a

second set of DATA statements, eg



8001 DATA "Sam"

8002 DATA "Fred" etc



ensuring that SAM is allocated the number 1 in the "people" vocabulary

file, and FRE(D) the number 2. A command such as "ASK SAM TO GIVE THE

SWORD TO FRED" can then be conveniently streamlined. The analysis

would give tell=1, pers=1, fk1=2, ob1=1, and vb1=whatever number you

assigned to the verb "GIVE". In the speech subroutine, after the

appropriate checks to ensure that Sam is indeed present, you'd have a

line like:

RESTORE (8000+pers): READ p$: PRINT "You talk to ";p$;"."



Subsequently vb1 is inspected, resulting in the "giving" subroutine

being called. Here would be another series of condition tests (Is the

object available for giving? Is fk1 - Fred - present?) leading

ultimately to a line like this:

RESTORE (9000+ob1): READ x$: RESTORE (8000+fk1): READ y$:

LET p$=(p$ AND tell)+("You" AND NOT tell):

PRINT p$;" give";"s" AND tell;" the ";x$;" to ";y$;"."



In this particular example you'd then see on screen the message: "You

talk to Sam. Sam gives the bright sword to Fred." Of course you could

embellish this as much as you like - writing convincing conversation

routines is an important part of the fun! Notice that the line

suggested above will deal with the situation no matter who is doing

the giving; if the variable "tell" is zero, you'd just get: "You give

the bright sword to Fred".



So there you are - the VENTURESPEAK parser is at your disposal. For

the rest - the creation of that wonderful adventure which will

outshine "Sherlock" - over to you ...

