artificial intelligence
on the commodore 64
moke your micro think
L^SiL O ■ •
artificial intelligence
on the commodore 64
moke your micro think
keith & steven brain
First published 1984 by:
Sunshine Books (an imprint of Scot Press Ltd.)
12-13 Little Newport Street,
London WC2R 3LD
Copyright © Keith and Steven Brain, 1984
All rights reserved. No part of this publication may be reproduced,
stored in a retrieval system, or transmitted in any form or by any means,
electronic, mechanical, photocopying, recording and I or otherwise, with¬
out the prior written permission of the Publishers.
British Library Cataloguing in Publication Data
Brain, Keith
Artificial intelligence on the Commodore 64.
L Artificial intelligence 2. Commodore 64
(Computer)
1. Title IL Brain, Steven
00L53TO285404 Q335
ISBN 0-946408-29-7
Cover design by Graphic Design Ltd.
Illustration by Stuart Hughes.
Typeset by V & M Graphics Ltd, Aylesbury, Bucks.
Printed in England by Short Run Press Ltd, Exeter.
2
CONTENTS
Page
Introduction 7
1 Artificial Intelligence 9
2 Just Following Orders 13
3 Understanding Natural Language 29
4 Making Reply 47
5 Expert Systems 65
6 Making Your Expert System Learn for Itself 79
7 Fuzzy Matching 93
8 Recognising Shapes 105
9 An Intelligent Teacher 117
10 Putting It All Together 125
3
Contents in detail
CHAPTER 1
Artificial Intelligence
Fantasy — reality: two-way conversations, robots, expert systems.
CHAPTER 2
Just Following Orders
Preset orders and fixed responses — DATA arrays — expanding the
vocabulary — removing redundancy — abbreviated commands — partial
matching — sequential commands.
CHAPTER 3
Understanding Natural Language
Dealing with sentences — subjects, objects, verbs, adjectives, adverbs —
punctuation — a sliding search — rearranging the word store array.
CHAPTER 4
Making Reply
Getting more sensible replies — making logical decisions before replying —
choosing the correct subject — problems with objects — changing tense.
CHAPTER 5
Expert Systems
How an expert works — simple problems — more difficult problems -
including pointers — sequential and parallel branching — checking how
well the answers match the data — better in bits.
CHAPTER 6
Making Your Expert System Learn for Itself
Letting the computer work out its own rules for two objects - a wider
spectrum — watching what happens.
5
Artificial Intelligence on the Commodore 64
CHAPTER 7
Fuzzy Matching
Recovering information from the human mind Soundex Coding a
computer program for converting names — retrieving information.
CHAPTER 8
Recognising Shapes
Simulating the action of a light sensor — inserting into sentences — a
branching short cut.
CHAPTER 9
An Intelligent Teacher
Questions and answers — keeping a score — shifting the emphasis of
questions to areas of difficulty — making questions easier or harder.
CHAPTER 10
Putting It All Together
Making conversation with the computer — making decisions, cost arrays
and profit arrays — the Computer Salesman.
6
Introduction
Artificial Intelligence is undoubtedly an increasingly important area in
computer development which will have profound effects on all our lives in
the next few decades. The main aim of this book is to introduce the reader
to some of the concepts involved in Artificial I ntelligence and to show them
how to develop ‘intelligent’ routines in BASIC which they can then
incorporate into their own particular programs. Only a superficial
knowledge of BASIC is assumed, and the book works from first principles
as we believe that this is essential if you are really to understand the
problems involved in producing intelligence, and how to set about
overcoming them.
The basic format of the book is that ideas are taken and suitable routines
built up step by step, exploring and comparing alternative possibilities
wherever feasible. Rather than simply giving you a series of completed
programs, we encourage you to experiment with different approaches to let
you see the results for yourself. Detailed flowcharts of most of the routines
are included. The main emphasis in the routines is placed on the AI aspects
and we have therefore avoided Parting up’ the screen display as this tejids to
obscure the significance of the program. In places you may notice that odd
lines are redundant, but these have been deliberately included in the
interests of clarity of program flow. As far as possible, retyping of lines is
strenuously avoided but modification of lines is commonplace. All listings
in the book are formatted so that they appear as you will see them on the
screen. In most cases, spaces and brackets have been used liberally to make
listings easier to read but be warned that some spaces and brackets are
essential so do not be tempted to remove them all. All routines have been
rigorously tested and the listings have been checked very thoroughly so we
hope that you will not find any bugs. It is a sad fact of life that most bugs
arise as a result of‘tryping mitsakes’ by the user. Semi-colons and commas
may look very insignificant but their absence can have very profound
effects!
Artificial Intelligence is increasing in importance every day and we hope
that this book will give you a useful insight into the area. Who knows — if
you really work at the subject you might be able to persuade your machine
to read our next book for itself!
Keith and Steven Brain
Groeswen, January 1984
7
CHAPTER 1
Artificial Intelligence
Fantasy
For generations, science fiction writers have envisaged the development of
intelligent machines which could carry out many of the functions of man
himself (or even surpass him in some areas), and the public image of
Artificial Intelligence has undoubtedly been coloured by these images. The
most common view of a robot is that it is an intelligent machine of generally
anthropomorphic (human) form which is capable of independently
carrying out instructions which are given to it in only a very general
manner.
Of course, most people have ingrained Luddite tendencies when it comes
to technology so in the early stories these robots tended to have a very bad
press, being cast in the traditional role of the ‘bad guys’ but with near¬
invincibility and lack of conscience built in. The far-sighted Isaac Asimov
wove a lengthy series of stories around his concept of ‘positronic robots’
and was probably the first author really to get to grips with the realities of
the situation. He laid down his famous Three Laws of Robotics’ which
specified the basic ground rules which must be built into any machine
which is capable of independent action — but it is interesting to note that he
could not foresee the time when the human race would accept the presence
of such robots on the earth itself.
‘Star Wars’ introduced the specialised robots R2D2 and C3PO, but we
feel that many of their design features were a little strange. Perhaps there is
an Interplanetary Union of Robots, and a demarcation dispute prevented
direct communication between humans and R2D2. In ‘The Stepford
Wives’, the local husbands got together and had the (good?) idea of
converting their wives into androids who automatically did exactly what
was expected of them, but the sequel revealed the dangers of the necessity
to continuously reinforce with an external stimulus! Perhaps one hope for
mankind is that any aliens who chance upon us will not have watched
‘Battlestar Galactica’, and will therefore build robots of the Cylon type
who, rather like the old Space Invaders, are always eventually defeated
because they are totally predictable.
Of course intelligent computers also appear in boxes without arms and
legs, although flashing lights seem obligatory. Input/output must
obviously be vocal but the old metallic voice has clearly gone out of fashion
9
Artificial Intelligence on the Commodore 64
in favour of some more definite personality. If all the boxes look the same
then this must be a good idea, but please don’t make yours all sound like
Sergeant-Major Zero from ‘Terrahawks’! Michael Knight’s K1TT sounds
like a reasonable sort of machine to converse with, and it is certainly
preferable to the oily SLAVE and obnoxious ORAC from ‘Blake’s Seven'.
ORAC seemed to pack an enormous amount of scorn into that little
perspex box, but other writers have appreciated the difficulties which may
be produced if you make the personality of the machine too close to that of
man himself.
In Arthur C. Clarke’s ‘2001: A Space Odyssey’, the ultimately-intelligent
computer HAL eventually had a nervous breakdown when he faced too
many responsibilities; but in ‘Dark Star’ the intelligent bomb was quite
happy to discuss Existentialism with Captain Doolittle but was unwilling
to deviate from his planned detonation time, although still stuck in the
bomb bay. In ‘The Restaurant At The End of The Universe’, the value of
the Sirius Cybernetics Corporation Happy Vertical People Transporter
was reduced significantly when it refused to go up as it could see into the
future and realised that if it did so it was likely to get zapped; and the Nutri-
Matic Drinks Synthesiser was obviously designed by British Rail Catering
as it always produced a drink that was ‘almost, but not quite, entirely unlike
tea’.
More worrying themes have also recently appeared. The most significant
feature of‘Wargames’ was not that someone tapped into JOSHUA (the US
Defence Computer), but that once the machine started playing
thermonuclear war it wouldn’t stop until someone had won the game. And
in ‘The Forbin Project’ the US and Russian computers got together and
decided that humans are pretty irrelevant anyway. Of course, if you are
Marvin the Paranoid Android and have a brain the size of a planet and a
Genuine People Personality, you can succeed without weapons by
confusing the enemy machine into shooting the floor from under itself
whilst discussing your personal problems.
Reality
The definition and recognition of machine intelligence is the subject of fast
and furious debate amongst the experts in the subject. The most generally-
accepted definition is that first proposed by Alan Turing way back in the
late 1940s when computers were the size of houses and even rarer than a
slide-rule is today. Rather than trying to lay down a series of criteria which
must be satisfied, he took a much broader view of the problem. He
reasoned that most human beings accept that most other human beings are
intelligent and that therefore if a man cannot determine whether he is
dealing with another man (or woman), or only with a computer, then he
must accept that such a machine is intelligent. This forms the basis of the
10
Chapter l Artificial Intelligence
famous Turing Test\ in which an operator has to hold a two-way
conversation with another entity via a keyboard and try to get the other
party to reveal whether it is actually a machine or just another human being
— very awkward!
Many fictional stories circulate about this test, but our favourite is the
one where a job applicant is set down in front of a keyboard and left to
carry on by himself. Of course he realises the importance of this test to his
career prospects and so he struggles valiantly to find the secret, apparently
without success. However after some time the interviewer returns, shakes
him by the hand, and congratulates him with the words ‘Well done, old
man, the machine couldn’t tell if you were human so you are just what we
need as one of Her Majesty’s Tax Inspectors!’
Everyone has seen from TV advertisements that the use of computer-
aided design techniques is now very common, and that industrial robots are
almost the sole inhabitants of car production lines (leading to the car
window sticker which claims ‘Designed by a computer, built by a robot,
and driven by an idiot’). In fact, most of these industrial robots are really of
minimal intelligence as they simply follow a pre-defined pathway without
making very much in the way of actual decisions. Even the impressive
paint-spraying robot which faithfully follows the pattern it learns when a
human operator manually moves its arm cannot learn to deal with a new
object without further human intervention.
On the other hand, the coming generation of robots have more-
sophisticated sensors and software, which allow them to determine the
shape, colour, and texture of objects, and to make more rational decisions.
Anyone who has seen reports of the legendary ‘Micromouse’ contests,
where definitely non-furry electric vermin scurry independently and
purposefully (?) to the centre of a maze, will not be aM AZEd by our faith in
the future of the intelligent robot, although there seems little point in giving
it two arms and two legs.
Another important area where Artificial Intelligence is currently being
exploited is in the field of expert systems, many of which can do as well (or
even better) than human experts, especially if you are thinking about
weather forecasting. These systems can be experts on any number of things
but, in particular, they are of increasing importance in medical diagnosis
and treatment — although the medical profession doesn’t have to worry
too much as there will always be a place for them since ‘computers can’t
cuddle’.
A major barrier to the wider use of computers is the ignorance and pig¬
headedness of the users, who will only read the instructions as a last resort,
and who expect the machine to be able to understand all their little
pecularities. Processing of ‘natural language’ is therefore a major growth
area and the ‘fifth generation’ of computers will be much more user-
friendly.
11
Artificial Intelligence on the Commodore 64
Most of the serious work on Artificial Intelligence uses more suitable
(but exotic) languages than BASIC, such as LISP and PROLOG, which
are pretty unintelligible to the average user and are probably not available
for your home micro in any case. The BASIC routines which follow cannot
therefore be expected to give you the key to world domination, although
they should give you a reasonable appreciation of the possibilities and
problems which Artificial Intelligence brings.
12
CHAPTER 2
Just Following Orders
As your computer is actually totally unintelligent, you can only converse
with it in very simple terms. The first step, used in many simple adventure
games, is to have a series of preset orders to which there are fixed responses.
Let's start by taking a look at giving compass directions for which way to
move. At first sight, the simplest way to program this appears to be to ask
for an INPUT from the user and to write a separate IF-THEN line for each
possibility (see Flowchart 2.1).
100 PRINT"DIRECTION?".;
120 INPUT IN?
200 IF INS”"NORTH" THEN PRINT "NORTH"
210 IF I NT-" "SOUTH" THEN PRINT "SOUTH"
220 IF INT”"WEST" THEN PRINT "WEST"
230 IF I NT-" "EAST" THEN PRINT "EAST"
200 GOTO 10O
13
Artificial Intelligence on the Commodore 64
If you type in anything other than the four key command words, nothing
will be printed except for another input request. It would be more user-
friendly if the computer indicated more clearly that this command was not
valid. You could do that by including a test which shows that none of the
command words has been found, but this becomes very long-winded, and
effectively impossible when you have a long list of valid words. (Note that
this line is so long that you can only enter it if you use the keyword
abbreviations given in the back of your Commodore 64 manual.)
240 IFI m< >"NORTH"AND1N¥<>"SOUTH"ANDIN$<
>"WEST"ANDINT<>"EAST"THENARINT"INVflLID R
EQUEST"
On the other hand, adding GOTO 100 to the end of each IF-TH EN line will
force a direct jump back to the INPUT when a valid command is detected.
If all the IF tests are not true then the program falls through to line 240
which prints a warning. Making direct jumps back when a valid word is
found is a good idea anyway, as it saves the system making unnecessary tests
when the answer has already been found (see Flowchart 2.2).
Flowchart 2.2 Deleting In necessary Tests
200 IF IN*-"NORTH" THEN PRINT "NORTH" : GO
TO 100
14
Chapter 2 Just Follow ing Orders
210 IF IN$*"SOUTH" THEN PRINT "SOUTH" GO
TO 100
220 IF IN$="WEST" THEN PRINT "WEST" ; GOTO
100
230 IF I N'T” "ERST" THEN PRINT '"ERST" : GOTO
100
240 PRI NT"INVRLID REQUEST"
That will echo the command given on the screen but of course it does not
actually DO anything. As a model to work with, we will start at a position
defined as X%=0 and Y%=0 and indicate movement as plus and minus in
relation to this point. Notice that integer variables are used wherever
possible, as they are processed faster than real numbers, and this also
removes the possibility of clashing with reserved variables.
10 X*=0 : Y*“0
We now need to add the real response to the command, as well as the
message indicating that it has been understood (see Flowchart 2.3).
200 IF INS*"NORTH" THEN PRINT "NORTH" : ‘A'
~Y“;-1 : GOTO 100
210 IF IN*-"SOUTH" THEN PRINT "SOUTH" •
"Y*i+1 • GOTO 100
220 IF IN*~"WEST" THEN PRINT "WEST"=
*;-l ; GOTO 100
230 IF IN$~"ERST" THEN PRINT "ERST" : X?,~X
5S+1=G0T0 100
That modification actually shows your position appropriately, relative to
the origin. So that you can see what is happening, and where you are, add a
printout of your current position:
lie print":-:",:-:*'.,"Y"; t/.
Using subroutines
Of course, that was a very simple example and. particularly where the
results of your actions are more complicated, it is usually better to put the
responses into subroutines.
200 IF IN£~"NORTH" THEN GOSUB 2060 : GOTO
100
15
Artificial Intelligence on the Commodore 64
210
100
IF
IH$-
"SOUTH
" THEN GOSUB 2100 : GOTO
220
Ld l/l
IF
IN$~
"WEST"
THEN GOSUB 2200 GOTO 1
uU
220
IF
"ERST"
THEN GOSUB 2300 •• GOTO • 1
00
2000
PRINT
"GOING NORTH"-
* ,1 ■ . tin . J
1 1 1
=RETURN
2100
PRINT
"GOING SOUTH"=
Y’:~Y'-;+1
* RETURN
2200
PRINT
"GOING WEST" 0"
1 V ■— "/ -4 .
RETURN
230O
PRINT
"GOING EAST"N*:
1 P . _• 1 > ■ , ,|
RETURN
Flowchart 2.3 Adding a Response
16
Chapter 2 Just Following Orders
More versatility
You could extend this use of IF-THEN tests ad infinitum (or rather ad
memoriam finitum!), but it is really a rather crude way of doing things
which creates problems when you want to make your programs more
sophisticated. A more versatile way to deal with command words and
responses is to enter them as DATA and then store them in string arrays.
First you must DIMension arrays of suitable length for command words
(CS) and responses (R$). As variable-length strings are allowed (up to 255
characters) the actual text can be of almost any length.
30 DIM 3 >.* R$< 3 >
If you put the commands and responses in pairs in the DATA statement,
then it is more difficult to get them jumbled up and easier to read them in
turn into the equivalent element in each array (see Table 2.1).
10000 DATA NORTH,GOIMG NORTH,SOUTH,GOING
SOUTH,WEST,GOING WEST,EAST, GOIMG' ERST
11000 FOR N~0 TO 3
11010
1 1020
READ C$<
NEXT N
: N >, R$< N >
ELEMENT
NUMBER
COMMAND
WORD C$(n)
RESPONSE
R$(n)
1
NORTH
GOING NORTH
2
SOUTH
GOING SOUTH
3
WEST
GOING WEST
4
EAST
GOING EAST
Table 2.1 Content of Command and Response Arrays
To initialise the arrays (fill them with your words), when you RUN add a
GOSUB and RETURN.
40 GOSUB 10000
11030 RETURN
17
Artificial Intelligence on the Commodore 64
All those IF-THEN tests can now be replaced by a single loop which
compares your INPUT with each element of the array containing the
command words (C$) in turn (see Flowchart 2.4). Lines 200-220 need to be
replaced by the following lines but notice also that line 230 must be deleted.
'200 FOR N-0 TO 3
210 IF IN*”C$<N> THEN PRINT' Rtf N> ; GOTO 1
00
220 NEXT H
Flowchart 2.4 More Versatility
Now, IF your input, INS, corresponds to any of the command words, the
program jumps out of the loop after printing the appropriate response,
RS(N).
Of course we are now back in our original position of actually doing
nothing, so we need to be able to call those action subroutines. First of all
18
Chapter 2 Just Following Orders
let’s arrange to jump out of the loop, if a match is found, to a new routine at
line 300.
210 IF IN$-C$<N) THEM PRINT RT< N> : GOTO 3
00
We still have a pointer to indicate which word matched the input, as N (the
number of array elements checked) holds this value. We can use this in an
ON-GOSUB line to move to appropriate routines which are similar to the
ones we wrote earlier, except that there is no need to define the particular
message: this has already been printed as R$(N).
309 ON <N+1> COSUB 2000,2100,2200,2300 : G
0T0 100
2000
_ |
I - « 1 X
RETURN
2100
111*.. .1 , A
1 '1 ■'.+ 1
RETURN
22O0
V•.*..... H
‘ r'*•*» X
RETURN
2300
1
RETURN
Expanding the vocabulary
The arrays can easily be expanded to contain more words. It would be
better if we defined the number of words as a variable WD%, which we
would then use to DIMension the arrays and for both the filling and
scanning loops. This produces a general routine which is easily modified.
28 WD ':~2
30 DIM C$< WO”; >.. R$< WD"i ">
200 FOR N-0 TO WD'I
110O0 FOR N-0 TO WD‘:
For example we can add intermediate compass directions which change
both X and Y axes.
20 WDW
10010 DATA NORTH EAST,GOING NORTH ERST,3
OIJTH ERST,GOING SOUTH ERST
1O020 DATA SOUTH WEST,GOING SOUTH WEST,N
ORTH WEST,GOING NORTH WEST
and add some more subroutines:
3O0 ON <N+1> C0SUB 2000.2100,2200,2300,2
400,2500,2600,2700 : GOT0 1@0
19
Artificial Intelligence on the Commodore 64
2400
Y5S*
mi
i wv+ i.
RETURN
2500
Y’i“
m1
VVkVV+I
» i - o i i - ■ f X
RETURN
2600
1, ,» H . 1
1 •
mi
«*"'i 1
= RETURN
2700
— 1
1
mi
vVsVV-l
RETURN
Removing redundancy
All the responses so far have included the word ‘GOING’ and this word has
actually been typed into each DATA statement. Now typing practice is
very good for the soul but it would be much more sensible to define this
common word as a string variable. Notice that a space is included at the end
to space it from the following word.
10100 G$?"GOING "
You can then delete all occurrences of this word in the DATA and combine
G$ with each key word in the response instead.
210 IF IN$-C$<N> THEN PRINT G$.;R$(N > : GOT
0 300
10000 DATA NORTH,NORTH,SOUTH,SOUTH,WEST,
WEST > ERST,ERST
10010 DATA NORTH ERST/NORTH ERST,SOUTH E
AST,SOUTH ERST
10020 DATA SOUTH WEST,SOUTH WEST,NORTH W
EST,NORTH WEST
Now that is starting to look rather silly as both arrays now contain exactly
the same words, so why not get rid of the response array, R$, and simply
print C$(N)? Well, in this case you could do that without any problem, but
of course where the responses are not simply a repetition of the input (as is
very often the case) the second array is essential.
If you look hard at all those subroutines you will realise that they all do
only one thing — update the values of X% and Y%. Now we could include
that information in the original DATA and get rid of them altogether! We
need to add two more arrays to hold the X and Y coordinates, add the
appropriate values into the DATA lines after each response, and READ in
this information in blocks of four (INPUT, RESPONSE, X-MOVE,
Y-MOVE- see Table 2.2).
30 DIM C*< WD5i >, R$<: WD’i ), X< WDX >, Y< WDX)
10000 DATA NORTH,NORTH,0,-1,SOUTH,SOUTH,
8,1, WEST, WEST,~1,0,ERST,ERST,1,0
10010 DATA NORTH ERST,NORTH ERST,1,-1,SO
20
Chapter 2 Just Following Orders
IJTH ERST , SOUTH ERST ,1,1
19020 DATA SOUTH WEST,SOUTH WEST,-1,1,HO
RTH WEST,NORTH WEST,-1,-1
11010 READ C*<N>,R$<N>,N>,Y<N )
ELEMENT COMMAND
NUMBER WORD
C$(n)
RESPONSE
R$(n) X-MOVE Y-MOVE
X(n) Y(n)
1
NORTH
NORTH
0
-1
2
SOUTH
SOUTH
0
1
3
WEST
WEST
-1
0
4
EAST
EAST
1
0
5
NORTH-EAST
NORTH-EAST
1
-1
6
SOUTH-EAST
SOUTH-EAST
1
1
7
SOUTH-WEST
SOUTH-WEST
-1
1
8
NORTH-WEST
NORTH-WEST
-I
-1
Table 2.2 X and Y Moves Incorporated into Arrajs
Now we can delete lines 300 to 2700 and modify line 210 so that X%and Y%
are updated here (see Flowchart 2.5).
210 IF I N$=C$( N >• THEN PR I NT G* = R*< N > : XX-
X5£+X< H > : Y5j*Y5j+Y< N > ; GOTO 100 *
This overall pattern of putting all the information into a series of linked
arrays is a very common feature which is used in several of the later
programs in this book.
21
Artificial Intelligence on the Commodore 64
Flowchart 2.5 Using Linked Arrays
Abbreviated commands
So far we have always used complete words as commands, but that means
that you have to do a lot of typing to give the machine your instructions. If
you are feeling lazy you might think of changing the command words to the
first letter of the words only, and then INPUT a single letter. However,
unless you start using random letters that will only work as long as no two
words start with the same letter! To code all the eight compass directions
used above, we will have to use up to two letters: N, NE, E, SE, S, SW, W,
NW.
1 0000 DATA N ,NORTH, O , - 1, S ,SOUTH, 0 ,1, W;WE
ST,-1,0,E,ERST,1,0
10010 DATA NE,NORTH EAST,1,-1,SE,SOUTH E
AST, 1,1
10020 DATA SW,SOUTH WEST,-1,1,NW,NORTH W
EST,-1,-1
22
Chapter 2 Just Following Orders
Notice that it is only the actual command words which have changed and
that the computer gives a full description of the direction, as we are still
using that second array which holds the response.
Partial matching
In all the programs above we have always checked that the input matched a
word in the command array exactly. However, it would be useful if we
could allow a number of similar words to be acceptable as meaning the
same thing. For example, you could check whether the first letter of the
input word matched the abbreviated keyword by only comparing the first
character (taking LEFT$(IN$,1)).
190 IN*==LEFTf< im i 1 >
That will work with NORTH, SOUTH, EAST and WEST, but there are
obvious problems in dealing with the intermediate positions. In addition
there are lots of words beginning with the letters N, S, E and W — all of
which would be equally acceptable to the machine as a valid direction.
For example:
NOT NORTH
would produce:
GOING NORTH
A more selective process is to match a number of letters instead ofjust one.
In this example the first three letters of the four main directions are quite
characteristic.
NOR
SOU
EAS
WES
If you use these as command words, then, for example:
NOR
NORTH
NORTHERN
and NORTHERLY
will all be equally acceptable, but:
23
Artificial Intelligence on the Commodore 64
NOT
NEARLY
NOWHERE
and NONSENSE
will all be rejected.
All we need to do is to take the first three letters of the input,
LEFT$(IN$,3), and compare them with a revised DATA list. Lines 10010
and 10020 can be deleted and the word number variable WD% must then
be amended to 4.
20 WD5S*3
190 IN$~LEFT$( IN$, 3 1
16000 DfiTfi NOR,NORTH,6,-1,SOU,SOUTH,0,1,
WES,WEST,-1,0,EfiS,ERST,1,8
Sequential commands
In the routines above we have dealt with the intermediate compass
positions as separate entities, but if we could give a sequence of commands
at the same time we would not need to do this. There is always more than
one way to get to any point, and if more than one command word could be
understood at the same time we would not have to worry about checking
for directions such as ‘NORTH EAST’ as they could be dealt with by the
combination of‘NORTH 1 and ‘EAST’.
This brings us to the very significant question of how to split an input
into words. First you must ask yourself how you recognise that a series of
characters make up a separate word. The answer, of course, is that you see a
SPACE between them. Now if we look for spaces we can break the input
into separate words which we can look at individually.
The easiest way to look for spaces is with the INSTR command which
searches the whole of a designated search string for a match with a second
target string. Unfortunately this command is not provided in standard
Commodore BASIC , so we will have to use a series of BASIC commands
to emulate this. These will be placed in a subroutine at line 5000, which we
will refer to for the rest of this book as simply the INSTR routine.
5008 FOR N~ 1 TO LEN<IN$ >
5018 IF IN$,N, 1 " THEN SP5s=N‘RET
URN
5920 NEXT N
5038 SP'/.=0
5040 RETURN
24
Chapter 2 Just Following Orders
This routine will check whether the first character in IN$ is a space. If it is
not a space then it will automatically continue checking until the end of INS is
reached. If no space is found in the whole of INS then SP% will be set to
zero. If a space is found then the value of SP% will be the number of
characters along INS that the space is located (see Flowchart 2.6).
Flowchart 2.6 Locating the Position of a Space
We need to call this from the main routine and we will print out the result
when we RETURN so that you can see what is happening.
130 GOSUB 5008
140 PRINT SP'ii : GOTO 100
Try this out with:
NOR WES
SP% 4
NORTH WEST
SP% 6
NOR NOR WEST
SP% 4
Notice that the length of the word is accounted for by SP%but that only the
first space is found. To find all the spaces we are going to have to work
harder. First delete that temporary line 140.
Let’s look at the input logically from the start (lefthand side). We will
replace the LEFT$(1N$,3) with M1D$(1N$,ST%,3) so that we can look at
any three-letter combination in the whole of 1N$. To make it more sensible
25
Artificial Intelligence on the Commodore 64
we will call the result of this W$ as it shows the position of a word. To start
with we must set the search start position ST% equal to one and add a space
to the front of INS so that the first word is also found (see Flowchart 2.7).
125 STV.«1: IN*®” " + IM*
130 GOSUB 5000
190 INS,ST’;, 3>
210 IF W$=C$<N> THEN PRINT G$;R$<N) :
N > •• Y5S«YV.+Y< N > : GOTO 100
5000 FOR N«ST5S TO LEN<IN$>
If you run this as it stands then you will still only find the first word as we
have GOTO 100 on the end of line 210. However simply sending the
program back to the INSTR check in line 130 instead does not help either,
as it will always start checking from the beginning of INS and will always
find the same first space. Once we have found this first space we need to
Flowchart 2.7 Searching for a Keyword
move the start position ST% for the next search on to the character after
that space. SP%+1. When no more spaces can be found then the end of the
input has been reached and we can GOTO 100 again.
140 IF SP>.>0 THEN ST’i-SP^+l : GOTO 190
150 GOTO 100
26
Chapter 2 Just Follow ing Orders
210 IF U$=C$(H) THEN PRINT G$; R$CN > : Y>.-Y,
V.+v< N > * Y5S«YV.+Y< N > : GOTO 130
Now typing:
NORTH WEST
produces:
GOING NORTH
GOING WEST
and even:
NOR NOR EAST
is decoded as:
GOING NORTH
GOING NORTH
GOING EAST
It would be a lot neater if we deleted all those redundant‘GOINGs’and put
all the reported directions on the same line. We need to PRINT G$ once,
immediately before the INSTR check. Now each time we go through the
loop comparing the current word with those stored, we PRINT R$(N); if
there is a match. As there is a semi-colon after this, the words will be printed
on the same line but we also need to add spaces between them. Finally we
add a simple PRINT just before we go back for a new input, to move the
cursor position on to the next line.
126 PRINT
145 PRINT
219 IF W*-C*<N> THEN PRINT
«X*.+X< N * Y';=Y';+Y< N > •• GOTO 130 •
Now:
NORTH EASTERLY SOUTH WEST
sends you neatly round in circles:
GOING NORTH EAST SOUTH WEST
27
CHAPTER 3
Understanding Natural Language
So far we have only communicated with the computer in a very restricted
way, as it has only been programmed to understand a very few words or
letters and it only recognises these if they are entered in exactly the right
way. For example, if you put a space before or after your command as you
INPUT it then it will be rejected. This is because we are comparing whether
the two strings match exactly.
On the other hand in the real world everyone uses what is known as
‘natural’ language which is a very sophisticated and extremely variable
thing which only the human brain can cope with effectively. Even if we
forget for the moment the difference between ‘English’ and ‘American’ or
even regional dialects of either (can ‘Ow bist old but’ really mean ‘How are
you old friend’?) dealing with language has an infinite number of problems.
Even the most sophisticated systems in the world cannot cope with
everything. There is an old story which illustrates this point very well. The
CIA developed a superb translation program which could instantly convert
English into Russian and vice versa. In the hope of impressing the
President they laid on a demonstration of its capabilities, in which it
converted everything he said into Russian, spoke that, and then retranslated
the Russian back into English. He was most impressed and was totally ab¬
sorbed until one of his aides reminded him that he had forgotten that the First
Lady was waiting for him outside. When he ruefully commented ‘out of
sight, out of mind’ he was amazed to hear the machine come back with
‘invisible maniac’!
Dealing with sentences
Everyone knows that real language is made up of sentences, but what
exactly do we mean by a sentence? Well, the most obvious way we recognise
a sentence is that we see a full stop! However if we are going to be able to
deal with sentences, we are going to have to think a lot harder than that.
The Oxford Dictionary definition includes ‘a series of words in
connected speech or writing, forming grammatically complete expression
of single thought, and usually containing subject and predicate, and
conveying statement, question, command or request’ but also concedes
that it is used loosely to mean ‘part of writing or speech between two full
stops’. Phew! Can somebody translate that into everyday English, please?
29
Artificial Intelligence on the Commodore 64
The intricacies and illogicalities of the English language are infamous so
how can we expect a computer to cope?
Well, let’s start by looking at some simple examples of sentences.
1 WANT.
consists of a subject I and a verb WANT
I WANT BISCUITS.
also has an object BISCUITS
I WANT CHOCOLATE BISCUITS.
qualifies the object with an adjective CHOCOLATES
I SOMETIMES WANT CHOCOLATE BISCUITS.
qualifies the verb with an adverb SOMETIMES.
The most important word in all the above examples was ‘WANT’ as it
conveyed the main idea. The second example was more informative as it
indicated that only one particular type of object. BISCUITS, was wanted.
The addition of an adjective, CHOCOLATE, gave further information on
the type of object wanted, but life became more uncertain again when the
adverb SOMETIMES was included.
Now how could a computer program decode such sentences? The answer
must be to find some logical structure in the sentence, so what ‘rules’ could
we lay down for this example?
1) All started with a subject I and ended with a full stop.
2) The last word was always the object BISCUITS (unless there was no
object and only two words).
3) If the word before the object was not the verb WANT it was an adjective
CHOCOLATE.
4) If the word before the verb was not the subject I it was an adverb
SOMETIMES.
Let’s write a program in which we give the computer sentences and ask it to
break them up into their component parts.
To start off, we need to give it a vocabulary of objects, adjectives and
adverbs to work with. We will READ these from DATA and storethemin
arrays OB, AJ and AV, according to type.
30
Chapter 3 Understanding Natural Language
10 GOSUB 10000
10000 DIM 0B$(5> ,AJ$C5 ),A V$<2 >
10999 REM OBJECTS
11©00 DflTfi BISCUITS,BUNS,CAKE
11010 DflTfi COFFEE.-TEA, WATER
11019 REM ADJECTIVES
11020 DATA CHOCOLATE,GINGER,JAM
11030 DATA COLD,HOT,LUKEWARM
11029 REM ADVERBS
11040 DATA ALWAYS, OFTEN*, SOMETIMES
11100 FOR N“0 TO 5
11110 READ OB$<N >
11120 NEXT N
11130 FOR N~0 TO 5
11140 READ flJ*< N >
11150 NEXT N
11160 FOR N-0 TO 2
11170 READ'AV$(N>
11180 NEXT N
11190 RETURN
Now we need to break the sentence into words (see Flowchart 3.1). Once
again we will do that with an INSTR search for spaces, and to make life
easier we will add a space on to the end of IN$ so that the format of the last
word looks just like that of other words.
100 INPUT IN*
120 IN*=IN*+" M
130 GOSUB 5000
190 GOTO 130
The end of the sentence has been reached when no more spaces can be
found.
140 IF SP’^0 THEN 200
If a space is found then the section of INS from ST% (current search start)
to SP%—ST% (current space—current start=length of word) is cut out
and stored in a word store array W$(WC%).
150 U*< we* >=MI D*< I m , ST*;, SPJi-ST5£ >
10010 DIM W$C4)
To begin with ST%=1 so that the search starts at the first character in the
31
Artificial Intelligence on the Commodore 64
Flowchart 3.1 Cutting Out Words
input string. The word count variable WC% is set to zero so that the first
word found is stored in the zero element of the word store array.
110 STV.= 1' WC^0
The word count is incremented (so that the next element of the array W$ is
used next time) and a check made that there are not more than five words in
the sentence. The start position for the next search is then set to one more
than the position of the last space and the search is continued.
160 WCV.-WC“;+1
17W IF UC*>5 THEN PRINT "SENTENCE TOO LO
NG" : GOTO 100
180 ST‘;~SP''.+ 1
32
Chapter 3 Understanding Natural Language
A test is now made to see whether there is a match between the key words in
the sentence and the objects in the vocabulary array OB$(N) (see Flowchart
3.2). Only words 2, 3 and 4 are checked as these are the only possible
Flowchart 3.2 Looking for a Match
positions for the object in our restricted sentence format. Three different
routines are jumped to according to the position of the matching word in
the sentence. If no match is found a message is printed and a new input
requested.
208 FOR N-0 TO 5
210 IF W$<2)=0B$CN> THEN 508
220 IF Wf<3>«0B*CN> THEN 600
230 IF W$<4>~0B$<N> THEN 700
240 NEXT N
250 PRINT "OBJECT NOT FOUND"
260 GOTO 100
If the object was found as word three then there was neither adjective or
adverb.
33
Artificial Intelligence on the Commodore 64
500 PRINT "NO ADJECTIVE OR ADVERB"
510 GOTO 100
If the object was found as word four then there could have been either an
adjective or an adverb in the sentence (see Flowchart 3.3).
600 PRINT "EITHER ADJECTIVE OR ADVERB"
Flowchart 3.3 Adverb or Adjective
First we check for a match between the second word and the contents of the
adverb array.
610 FOR N-0 TO 2
620 IF W$<1>~AV$<N> THEN 900
630 NEXT N
If no match is found then we check the third word against the adjective list
640 FOR N=0 TO 5
650 IF W$<2>»AJ$<N> THEN 1000
660 NEXT N
If a match is not found in either of these lists, then it would be useful to
34
Chapter .? Understanding Natural Language
indicate which word was not understood. The simplest answer is to check
whether the second word was not the verb ‘WANT’, as in that case the
second word must have been an adverb. On the other hand, if the second
word was the verb then the third word must have been an adjective. Notice
that the actual word which did not match is now included in the message.
670 IF U$<1X>"WANT" THEN PRINT "ADVERB
".: W*< 1 " NOT UNDERSTOOD • GOTO 100
680 PRINT "ADJECTIVE NOT UNDER
STOOD" : GOTO 100
If a match is found in either test then a success message is printed. Note that
these possibilities are exclusive and that in four words we can only have one
or the other.
900 PRINT "ADVERB"
910 GOTO 100
1000 PRINT "ADJECTIVE"
1010 GOTO 100
Where both adverb and adjective are present we must check for both, and
therefore a match in the first test also jumps on to the second test (see
Flowchart 3.4).
700 PRINT "ADVERB AND ADJECTIVE"
710 FOR N~0 TO 2
720 IF W*<1>=AV$<N> THEN 750
730 NEXT N
If no match is found for the adverb, then this fact is reported: a flag AV% is
set to 1 to indicate failure at this point before the adjective is checked.
740 PRINT "ADVERB "1 >:■ " NOT IJNDERSTO
OD " : AV*'.~ 1
758 FOR N"0 TO 5
760 IF USK3)*flJ$<N) THEN 800
770 NEXT N
If a successful match for the adjective is not found then the program loops
back after a report.
730 PRINT "ADJECTIVE U5K3>;" NOT UNDER
STOOD"
790 GOTO 100
35
Artificial Intelligence on the Commodore 64
Flowchart 3.4 Adverb and Adjective
If the adjective was found then a test is made that the adverb flag AV% was
not set before a match is reported. In any case, the flag is reset before the
next input.
800 IF fiV".=0 THEN PRINT "ADJECTIVE AND A
DVERB OK."
810 AV*;=0
820 GOTO 100
What about punctuation?
As we have already said, you usually recognise the end of a sentence
because it has a full stop, although when you type into a computer you
usually forget all about such trivialities. But what will happen in the
36
Chapter 3 Understanding Natural Language
program so far if some ‘clever' user puts in the correct punctuation? If you
think for a moment, you will realise that the computer will start
complaining as it will no longer recognise the last word, as this will actually
be read as the word plus the full stop.
We therefore need to check if the last character in the input string INS is a
full stop: this is simple as the ASCII code for this character is 46. The best
place to check seems to be immediately after the INPUT. If the code of the
last character is 46, then simply throw this character away and then
continue as before.
Flowchart 3.5 Dealing with Punctuation
We will add this as a subroutine which is jumped to as soon as an input is
made. Other punctuation marks may also appear at the end of the sentence,
so we will read the last character as a variable LC% which we will also use
later. This is stored as a simple variable by taking the ASCII code of the last
character in INS: using simple variables saves a lot of typing of string ($)
indicators (see Flowchart 3.5).
105 GOSUB 2009
2000 LC*i=flSC< RIGHTS* INS'.-1 >}
2010 IF LC’4~46 THEN 2100
2090 RETURN
2100 IN$=LEFT$<I NS,LEN< I Hf )-1>: RETURN
37
Artificial Intelligence on the Commodore 64
More useful Sentence terminators are the question and exclamation marks
which often indicate the context of the words. We can distinguish these in
the same way by their ASCII codes and, for the moment, we will just report
their presence.
2020 IF LC’i-33 THEN PR I NT "EXCLAMATION! " :
GOTO 2100
2030 IF LC*®63 THEN PRINT"QUESTION"■GOTO
210O
The normal INPUT command will not accept anything after a comma,
which it reads as data terminator. H owever we can produce a routine using
GET which will accept any text including commas. First of all INS is set
empty and a *<’ printed as a cursor.
100 IN**""-PRINT "<"
Now a check is made for a key-press and if no key is pressed then the check
is repeated.
101 GET If•IF I**"" THEN 101
When a key is pressed a cursor left code — is printed, followed by the
character corresponding to the key pressed. IS. This character is then added
on to INS and a jump made back to the keycheck. In this way the entry
appears on the screen as in a normal INPUT, and any errors can be
corrected with the backspace key.
103 PRINT "C< --T";I*■"<"; : IN**IN*+1$ : GOT
0 101
The end of the input is indicated by checking for the RETURN key, which
has an ASCII code of 13. If the entry is complete, then the cursor is moved
to the next line.
102 IF fiSCU 50-13 THEN PRINT ■ GOTO 105
Commas may be useful in indicating different parts of a sentence, which
could be examined as ‘sub-sentences’ in their own right. However, in simple
cases they are best deleted and replaced by spaces before the sentence is
broken into words (see Flowchart 3.6). Note that this will only function
totally correctly if there is no space after the comma, as any space following
a replaced comma will be seen as a new word.
Rather than write a completely new INSTR routine, we will modify our
38
Chapter J Understanding Natural Language
Flowchart 3.6 Replacing Commas and Apostrophes
existing one so that we can check INS for any predefined string TAS. To
make things clearer in the long run, we will make the variable pointing to
the position of the match in the string IS%, which can then be swapped with
any number of different variables, such as SP%. First we must modify our
space check to the new format.
130 Tft*-- " " : GGSUB 5000 = SP%~ I $’/.
5010 IF MID$< IN5UH.- 1 >“Tfl$ THEN IS*i=H : PET
URN
503© IS’;-0
Now the same method can be used to look for a comma, before replacing it
with a space.
115 TR$~".." ■ GGSUB 3000
3000 GGSUB 5000’CM**IS*
3010 IF CM*=0 THEN ST*=1 ; RETURN
3020 IN$=»LEFT«-IN*,CM*-1)+" "+RIGHT$‘. INf
, LEfK IN$ >-GM* >
3030 ST*«CM*+1
3G40 GOTO 3000
If you add this line, you can see the punctuation being taken out of the
string item.
3025 PRINT -IN*
Apostrophes can be dealt with in the same way, except that we do not
replace them with a space but simply close up the words.
39
Artificial Intelligence on the Commodore 64
115 , " : GOSUB 3000 : TR$“"''"■ GOSUE 310
0
3100 GOSUB 5000'flP‘^IS*/.
3110 IF fiP*i=0 THEN ST’:= 1 : RETURN
3120 I N$~LEFT$< I N$, RP--.-1 HR IGHT3K I N$, LEN
•: iNf >-RP‘o
3125 PRINT IN$
3130 STV.-RP':+1
3140 GOTO 3100
A sliding search approach
Although the method of examining a sentence described above will work, it
has the disadvantage that it requires the sentence to be entered in a
particular, restricted format. For example, if you enter:
1 WANT HOT CAKES OFTEN
the computer will report:
OBJECT NOT FOUND
as it mistakenly takes the last word OFTEN as the object.
On the other hand using a sliding search of the whole sentence for each
key word, without first breaking the sentence down into words, has the
advantage that it allows a completely free input format. In this approach
we take the first key word and try to match it against the same number of
letters in INS, starting at the first character. If this test fails then it is
automatically repeated, starting from the second character, etc. until a
match is found or the end of INS is reached. For example, if INS was i
WANT CAKE’ and the first key word was’CAKE’ the comparisons would
be:
Pass I I WA
Pass 2 WAN
Pass 3 WANT
Pass 4 ANT
Pass 5 NT C
Pass 6 T CA
Pass 7 CAK
Pass 8 CAKE (match found)
So far our INSTR routine has only tried to match a single character, but we
40
Chapter 1 Understanding Saturn! language
will have to modify line 5010 again, so that it takes into account the length
of the target string LEN(TAS).
5Q1Q IF MID*UN$,N,LEN<Tfl$>>=Tfl$ THEN IS
J£*N ! RETURN
Delete lines 105-1010 and add this line to check for the first object OB$(0).
210 Tft$~QB$<M> : GOSUB 5000 = SPV.= IS* : IF SP*'.
>0 THEN PRINT 0B$<M>.;"
Each object can be compared in the same way by forminga loop. (Note that
printing a semi-colon after OB$(M) ensures that each word is printed on
the same line.)
200 FOR M~0 TO 5
220 NEXT M
Similar checks can be made for matching with words in the adverb and
adjective arrays.
300 FOR M=0 TO 2
310 Tflf-RV$< M > •• GOSUB 5000 « SP5S* I S’; = IF SP*;
>0 THEN PRINT
329 NEXT M
400 FOR M~0 TO 5
410 Tfl$"fl J¥< M > : GOSUB 5000 = SP*= I S'; > IF SF'.-i
>0 THEN PRINT "i
420 NEXT M
1000 GOTO 100
To report what has been found, and so that we can use the words
discovered later, we will store each in an array as it is detected. We already
have a word store array W$ but we will expand it to hold up to 20 words
(which should be enough for even a very verbose sentence!).
10010 DIM
If a match is found a temporary string T$ is set equal to the matched word,
and a subroutine called at line 1500, which puts the word detected inthefirst
array element ( see Flowchart 3.7).
2 1 0 Tfi$-0e*< n > s GOSUB 5000 : SP'-;-1SX : IF sp*;
>0 THEN T$«0B$<M> : PRINT T$}" : GOSUB 15
41
Artificial Intelligence on the Commodore 64
0Q
1500 Wf< WC'C >~T$
Flowchart 3.7 Sliding Search
The word count WC% is then incremented, so that the next word is put in
the next element, before returning.
1520 ic';-uc*;+i
1520 RETURN
Using a temporary string T$ in the actual subroutine means that we can
also use it in the tests for adverbs and adjectives in exactly the same way.
310 TA$~AV$< M >: GOSUB 5000 ’ SPV.* I3* : IF SP‘;
>0 THEN T$=flV«M)‘ PRINT T$; " ".-GOSUB 15
00
410 Tfl$~flJ$<: M > : GOSUB 5000 = SP^= I S'i : IF SR*;
>0 THEN Tf*flJ«<M) = PRINT Tf.; M ".-GOSUB 15
00
Partial matching
One advantage of the sliding search is that you can easily arrange to
recognise a series of connected words by only looking for some key
characters. This is obviously useful as it saves you having to put in both
single and plural nouns such as BISCUIT and BISCUITS. If you amend
the DATA in line 11000 as shown below than both will be recognised.
11000 DATA BISOUIT,BUN,CAKE
42
Chapter 3 Understanding Natural Language
However life is not that simple as using BUN rather than BUNS can
produce some unexpected results. On the plus side it will detect BUN,
BUNS, and BUNF1GHT but unfortunately BUNCH, BUNDLE,
BUNGALOW. BUNGLE, BUNK, BUNION, and BUNNY as well!
This problem is not restricted to prefixes as the computer will also not
distinguish between HOT and SHOT. You could include a check that the
character before the start of each match was a space (ie that this was the
start of a word, see Flowchart 3.8). SP% gives the current start-of-word
position so MID$(IN$,SP%-1,1) is the character before this.
210 Th$--Oe*< II >: GOSUB 5000 = SP%* I S>. * IF SF'X
”0 THEN NEXT M•GOTO 230
211 IF MID*< IN$,SP*;--1,1 X>" " THEN NEXT
M = GOTO 230
212 T$=OB$(M> = PRINT T$j" ";=GOSUB 1586
310 Tfi**flV*< M > : GOSUB 5000 ^ I S*i = IF SP>.
-0 THEN NEXT M ! GOTO 330
311 IF MID*<IN$,SPX~1,1><>" " THEN NEXT
M:GOTO 320
312 T*«flV*< 1*1 >' PR I NT T* :■ " "; GOSUB 1500
410 Tfti=fiJ$( M > = GOSUB 5000 = SP'i* I SZ ’■ IF SP>.
-0 THEN NEXT M : GOTO 430
411 IF IIIIN$.. SPX-1,1 X>" " THEN NEXT
M•GOTO 430
412 T$*fl J$< M > = PR I NT T$" " j = GOSUB 1500
For this to function correctly on the first word, just add a space to the start
of INS.
110 IN**" "+IN$
In a similar way, you could use checks on the next letter afterthe match, or
the length of the word, to restrict recognised words.
43
Artificial Intelligence on the Commodore 64
Putting things in order
Although we have now' detected all the words in the sentence, regardless of
their position or w hat else is present, they are found and stored in the order
in which they appear in the DATA. This is because the comparison starts
with the first item in the object array rather than the first word in the
sentence. It w'ould be useful if we could rearrange the word store array so
that the W'ords in it were in the order in w hich they appeared in the sentence.
To do this, we must keep a record of the sentence position of the word
SP% and word count WC%, as each word is matched in a new word
position array WP%. This is a two-dimensional array with the sentence
position kept in the first element, WP(WC%,0). and the word count,
WP(WC%J), in the second.
10020 DIM WPC19>1>
1510 WP< WC5S, 0 < UP< WC":, 1
The actual sorting subroutine which does the rearrangement is at line 4000.
This must only be reached if a match is found.
440 IF WC5i=0 THEN 470
450 GOSUB 4000
460 GOTO 100
470 PRINT"NO MATCH FOUND”
480 GOTO 100
The sort routine (see Flowchart 3.9) takes the sentence position of the first
w'ord found (first element in the first dimension WP(0,0)) and compares it
with the sentence position of the second word found (second element in the
first dimension WP(OT 1,0)). If the position variable for the first word is of
Flowchart 3.9 Putting Words in Order
higher value than that for the second word then the first word found is
farther along the sentence than the second word, and these therefore need
to be swapped around. This will put the sentence-position pointers right
but the word-count markers also need to be rearranged to the correct
positions. This process is repeated until the word pointers are all in the
correct order. Notice that the actual contents of the string array which
44
Chapter 3 Understanding Natural Language
holds the words are not altered but only the pointers (index) to them.
4006 FOR N~0 TO WC5S-2
4016 IF NP<H,0Kl'JPvM+l,0> THEN NEXT N’GO
TO 4040
4026 D5J=WP< M0 >= WP( N, 0 >"WP< N+1,0 > = WP< N+1
, 0 >"D*i
4630 DV.*WP< N, 1 >: WP< N, 1 >=UP< N+l, 1 > = WPC N+1
> 1 )-D"i ■ GOTO 4600
If the strings are now printed in revised word-count, WC%. order, they will
be as they were in the original sentence, which should make it easier to
understand them.
4040 PRINT : FOR N*0 TO ICfc-1
4056 PRINT W$(WP(N, 1 >>; "
4060 NEXT N-PRINT
All elements in the sentence position array WP(N.O) and the word count
WC% must be reset to 0 before the next input.
4070 FOR N”0 TO 19
4080 WP< N 0 >“0
4690 NEXT N
4100 WCX=0
4110 RETURN
45
CHAPTER 4
Making Reply
More sensible replies
We have considered at length how to decode sentences which are typed into
the computer, but the replies it has produced so far have been very limited
and rigid. Although many of the original words in a sentence are often used
in a reply, in a real conversation we look at the subject of the sentence and
modify this word according to the context of the reply.
For example the input:
I NEED REST
might expect the confirmatory reply:
YOU NEED REST
and similarly:
YOU NEED REST
should generate:
I NEED REST
If you look at that situation logically, you will realise that for each input
subject there is an equivalent output subject, and that we have simply
chopped off the original subject and added the remainder of the sentence to
the appropriate new subject.
T is only a single character so we could check LEFT$(1N$, I). If this was
T then PRINT “YOU” could be added to the front of the remainder of the
input, RIGHT$( IN$,LEN(IN$)-1.
10 INPUT IN*
30 IF LEFT$( IN*.. 1 I u THEN ‘PRINT "Y0U"+
RIGHT* 1 " IN*,LEN< IN$>~1 >
60 GOTO 10
47
Artificial Intelligence on the Commodore 64
In the same way, the first three characters LEFT$(INS,3) could bechecked
against ‘YOU’ and replaced when necessary by T.
50 IF LEFT$< IM $> 3"YOU" THEN PRINT ,, I ,, +
rights: in*, lew in*>-3>
If you try that out with a series of sentences, you will see that it works OK
until you type something like:
YOU ARE TIRED
which comes back as the rather unintelligent:
I ARE TIRED
We could get around this by checking for the phrases i AM' and ‘YOU
ARE' as well as'I’and ‘YOU’ on their own, but notice that you must test for
these first and add GOTO 10 to the end of lines 20 and 40 to prevent a
match also being found with ‘1’ and 'YOU' alone.
20 IF LEFT*<IN$,4)="1 AM" THEN PRINT "VO
U ARE"+RIGHT$<IN$,LEWIN$>-4 >* GOTO 10
40 IF LEFT$C IN*,?)-"YOU ARE" THEN PRINT
" I AM" +RI GHT*< I N*, LENC I N* >-? ) = GOTO 10
Although this method will work, the program soon gets very long-winded
as a separate line is needed foreach possibility as we must take into account
the length of the matching word or phrase. Where many words are to be
checked, it is therefore better to use a multidimensional string array which
can be compared with the input by a loop.
A convenient format is to have a two-dimensional array 10S(n,m) where
the first dimension of each element, IO$(n,0), is the input word or phrase
and the second dimension, IO$(n,l), is the corresponding output word or
phrase. It is easier to avoid errors if these are entered into DATA in
matching pairs and READ in turn into the array. Start a new program with
these lines which set up the array.
10 GOSUE 10000
10000 DIM 10*0,1)
11000 DATA I,YOU,YOU,1,1 RM,YOU
ARE,YOU ARE,I AM
120O0 FOR N~0 TO 3
1201 0 READ 1 0*< N , id ), I 0*< N, 1 )
12030 NEXT N
13000 RETURN
48
Chapter 4 Making Reply
Flowchart 4.1 Using a Corresponding Reply
We will use a looping sliding string search again, which for the moment will
just print out the corresponding word or phrase to that matched. IOS(N,l)
(see Flowchart 4.1 ). One advantage of the sliding string search here is that it
will happily match embedded spaces in phrases as we have not broken INS
into ‘words’ before matching.
100 INPUT IN*
110 sjy-\
200 FOR M-0 TO 3
210 Tfi$= 10$< M.. 0 > : GOSUB 5000 • SP*i= I S'< -IF 3
P*;>0 THEN PRINT 10*01.. 1 >
220 NEXT M
250 GOTO 100
It is better to redefine the required response word as a new string which is
the first part of the reply RI$, and then PRINT this when the loop is left.
210 T fit- 10*< M, 0 > • GOSUB 5000 • SP*i“ I S>. ■■ IF S
P"£>0 THEN Rl$=IQ$ai- 1 :■
220 PRINT Rl$
To get a fuller reply, we need to add back on the rest of the original
sentence R2S (after inserting a space). It is not difficult to define the'rest of
the sentence'. We just need to subtract the end position of the word from
the LENgth of the sentence and use this value in RIGHTS. SP% points to
the start of the matched word: we have a record of the LENgth of this word
in the first dimension of the array as IOS(N.O). so we just need to subtract
SP%+LEN(lO$(N.0)).
210 Tfl$~ 10« M, 0 > = GOSUB 5000 = SP>.= I S'; : IF S
PJ£»0 THEN 220
49
Artificial Intelligence on the Commodore 64
215 R1$=I0$<M, 1) = R2$=" M +RIGHT$aN*,LEN<
I N$ >-< SP*+LEN< 10$< ri, 0 ) > >')
230 PRINT R1$;R2$
Flowchart 4.2 A Fuller Reply
Now when you try:
I AM CLEVER
the computer agrees:
YOU ARE CLEVER
But if you then press RETURN again it still tells you that you are clever—
which is not true, as you have not emptied INS, R1 $ and R2S before looping
back to the next input!
100 IN®="" ! INPUT IN®
240 Rl$™"" ! R2$ = ""
Before you feel too clever try:
WE ARE STUPID
50
Chapter 4 Making Reply
which may well surprise you when it gives the reply:
YOU
If you think for a few moments, you will see that one of our keywords is
hiding inside another word in this particular sentence. If you cannot see it
then try:
WE ARE INCOMPETENT
where the computer disagrees with you by returning:
YOU COMPETENT
Although each keyword is tested for in turn, each one is set to R1 $ when a
match is found so only the last match is reported. As the keyword is only
checked for once in each sentence, embedded T only causes problems when
this is not the keyword in the sentence.
To get around this we must consider which keywords may cause
problems. Although the letter T is very common, it is very rarely the last
letter in a word and so we could check that there is a space after the
keyword. We must treat all keywords in the same way so add a space to the
end of each. This could be done by changing all the DATA but it saves
memory in the long run if we add the space as the array is set up. Note that
there is no need to add spaces on to the end of the replies.
12020 10$< N * 0 10$< N .• O >+" “
We also now need to subtract one less character from INS to give R1$, as
the space has now become an integral part of the keyword.
215 R1*-I0$<M, 1 ):R2*- M " + RIGHT*< IN$.*LEN\
I m >-< SP5S+LEM 10$< M, 0 > > )+1 >
The computer will now readily agree about your incompetence.
If the first keyword is not at the start of the sentence, then everything
before it will be ignored in the reply.
For example the answer to:
WHAT IF I FALL?
will be:
YOU FALL?
51
Artificial Intelligence on the Commodore 64
Some strange results can still occur when two true keywords are present.
For example:
WHAT IF YOU AND I FALL
gives
I AND 1 FALL
and
WHAT IF 1 AND YOU FALL
replies
I FALL
However, adding more suitable keywords is easy and some combinations
will just not be acceptable. To make the routine more general, it is better to
define the number of keywords as a variable K W% and use this in place of
the actual number.
10 KW*'.~5 : GOSUB 10080
200 FOR N”0 TO KU'i
10000 DIM I0*<KW';,1>
11010 DATA WE,WE,THEY,THEY
12000 FOR N-Q TO KW*-;
Now the answer to:
WHAT IF WE FALL?
is the more logical:
WE FALL?
Pointing to replies
So far our computer has displayed only slightly more intelligence than a
parrot, as it has merely regurgitated a slightly modified version of the input.
The next stage, therefore, is to make it take some logical decisions on the
basis of the input before it replies.
The numbers of subjects SU%, verbs VB% and replies RP% are defined
as variables so that the program can be easily expanded, and three arrays
52
Chapter 4 Making Reply
using these are set up. (As we have a zero element in the array, these values
are all one less than the number of words.) SU$(n,n) is a two-dimensional
array which is concerned with the subjects in the input and output
sentences. The first dimension (n,0) contains the recognised subject words
and phrases allowed in the input, and the second dimension (n, 1) contains
the opposites which may be needed in the output. VB$(n) holds the legal
verbs, and RP$(n) a series of corresponding replies.
10 GOSUB 10000
10000 311**26: VB*i»6: RF'*i“6
10010 DIM simsu'-., 1 )
10020 DIM V£¥<VB‘i )
10030 DIM RP$< F:P‘. >
Table 4.1: Pairs of Subjects in SI $<n,n)
SU$(n,0)
I HAVE
EVE
1 AM
EM
YOU HAVE
YOU’VE
YOU ARE
YOU’RE
YOU
SHE HAS
SHE IS
SHE’S
SHE
THEY’VE
THEY ARE
THEY’RE
THEY
HE HAS
HE IS
HE’S
HE
WE HAVE
WE’VE
WE ARE
WE’RE
WE
I
SU$(n,l)
YOU HAVE
YOU’VE
YOU ARE
YOU’RE
I HAVE
I’VE
I AM
I’M
I
SHE HAS
SHE IS
SHE’S
SHE
THEY'VE
THEY ARE
THEY’RE
THEY
HE HAS
HE IS
HE’S
HE
WE HAVE
WE’VE
WE ARE
WE’RE
WE
YOU
53
Artificial Intelligence on the Commodore 64
The first two lines of DATA contain paired input and output subjects (see
Table 4.1 ) and these are READ into corresponding dimensioned elements
in the SUS(n.n) array. As the pronouns (i\ ‘YOU’, etc) are frequently
linked to other words to form phrases (such as ‘I'VE’), these combined
forms are also included in the DATA. Notice that these are arranged in
such an order that the most complete phrase containing a keyword is
always found first. A space is added on to the end of each element, so that
some clashing of partial matches is avoided and a space is automatically
formed in the reply.
11009 DATA I HAVE,YOU HAVE,I'VE,YOU'VE,I
AM,YOU ARE,TM,YOU' RE,YOU HAVE,I HAVE
11010 DATA YOU'VE,I’VE,YOU ARE,I AM,YOU'
RE,I'M,YOU,I
11020 DATA SHE HAS,SHE HAS,SHE IS,SHE IS
,SHE'S,SHE'S,SHE,SHE
11030 DATA THEY'VE,THEY'VE,THEY ARE,THEY
ARE, THEY'RE,THEY'RE,THEY,THEY
11040 DATA HE HAS,HE HAS,HE IS,HE IS,HE'
S,HE'S,HE,HE,WE HAVE,WE HAVE
11050 DATA WE'VE,WE'VE,WE ARE,WE ARE,WE'
RE,WE'RE,WE,WE,I,YOU
12000 FOR N~0 TO SUV.
12010 READ SU$( N, 8 >, SIJ$< N, 1 >
12020 SU$< N, 0 >=SU$< N, 0 )+" " 1 SU$< N, 1 >=SU$
(H,l)+" "
12020 NEXT N
The next DATA line contains the main verbs which are READ into
VB%$(n). The verb ‘to be’ is omitted as its variations are so complicated,
and many of its versions are already accounted for in the ‘subject’ check.
11060 DATA HATE,LOVE,KILL,DISLIKE,LIKE,F
EEL,KNOW
12048 FOR N-0 TO VBX
12050 READ VB$< N
12060 NEXT N
The last set of DAT A contains the replies which are put into R P$(n), before
control RETURNS to the main part of the program. To make things simple
to understand and check at this stage, all the replies contain the original
verb, although of course they could say anything.
54
Chapter 4 Making Reply
11070 DATA PROBABLY HATE YOU AS WELL.. LOV
E YOU TOO,KILL YOU
11-080 DATA DISLIKE LOTS OF THINGS, LIKE C
HIPS,FEEL POWERFUL,KNOW EVERYTHING
12070 FOR N=0 TO RP’:
12080 READ RP*(N >
12090 NEXT N
13000 RETURN
Matching
The input string is now compared with the list of subjects in the first
dimension of SU$(n,n) (see Flowchart 4.3). If there is no match then a new
Flowchart 4.3 Setting Match Pointers
55
Artificial Intelligence on the Commodore 64
input is requested, or else a subject match variable SM% is set to the
element number at which a match was found. (Note that 1S$ is always used
in this program to indicate the position of an INSTR match.)
200 FOR N-0 TO SU‘;
210 SJ>.~ 1 ; Tfl$=SUf< M0 ) > • GQSUB 5000
220 IF THEN NEXT M : GOTO 108
230 SMJS«M
The verb array is now compared with INS. If no verb is found, then the
input is rejected, or else the verb match variable VM% is set.
240 FOR M~0 TO VB'i
250 Tfl$-VE?$< I'l > > : GOSUB 5000
260 IF IS';=0 THEN NEXT M : GOTO 100'
270 VMJS»M
Making reply
Now that the subject and verb have been identified, we can pick up the
appropriate reply by using VM% as a pointer to the reply array RP$(n).
500 RL$~RP$< VMV. >
In the simplest case we can just add the appropriate subject to the front of
RLS before we print it.
520 RL$*SU*< StVi, 9 )+RL$
550 PRINT RLf
560 GOTO 100
Now, for example, if you type in:
1 HATE COMPUTERS
the program will reply with:
1 PROBABLY HATE YOU AS WELL
and:
1 KNOW A LOT
generates:
1 KNOW EVERYTHING
56
Chapter 4 Making Reply
Alternative subjects
If you prefer the machine to agree with you rather than trying to beat you at
your own game, then just change the subject added to RL$ to the second
element of the array (the ‘opposite’).
520 RL*»SU«SMJSil>+RL$
now:
I KNOW A LOT
generates:
YOU KNOW EVERYTHING
For more variety, you can pick the subject at random from the first or
second element, so that the reply is not predictable.
510 I NT< RND< 1 H0.5 >
520 RL$=SU$<SM5S,RS5£)+RL$
Putting the subject in context
It would be more sensible altogether if we chose the correct subject
according to the context of the reply, but to do that we must have markers
in the reply array. We will use a slash sign 4 /'to indicate that the word in the
first dimension of the subject array is to be used, and an asterisk **’ to
indicate that the word in the second dimension is to be used.
11070 DATA /PROBABLY HATE YOU AS WELL,/L
OVE YOU TOO,/KILL YOU
11088 DflTR *DISLIKE LOTS OF THINGS,/LIKE
CHIPS,*FEEL POWERFUL,*KNOW EVERYTHING
We can search the reply string RP$(VM%) pointed to by the verb marker
VM % for a slash sign \'\ provided that we rename this as INS before we
enter the INSTR check. If a slash sign is found, then the contents of the first
dimension of the subject array SU$(SM%,0) are added to the reply RLS, less
the first character (the slash sign, see Flowchart 4.4).
500 RLf~RP l t< VM?'. >
510 I N$~RL$ ’ ST';~ 1 = TR$~ " / " = GOSUB 5000
520 IF I S'; >0 THEN 800
800 RL*»SU*< SM*;, O )+R I GHT$< RLf .• LEHC RL* >•-1
S
810 GOTO 530
57
Artificial Intelligence on the Commodore 64
Flowchart 4.4 Putting the Subject in Context
On the other hand if no slash sign is found in the reply then a second search
is made for an asterisk If this is found, then the second dimension of
SU$(n,n) is used in the same way.
530 ST^l -Tfi*-"*." : GOSUB 5090
540 IF I S’; >0 THEN 820
820 RL*«SUf< SMJi, 1 HR I GHTf < F:L*, LEW F:L$ H1
820 GOTO 550
Now:
I LOVE ME
will give:
1 LOVE YOU TOO
but:
I FEEL POWERFUL
produces:
YOU FEEL POWERFUL
Inserting into sentences
To make things simple, we have always started our reply sentences with the
subject, but in real life this is not always the case. Now that we have markers
in the replies to indicate what type of subject is to be added, we can also use
them to indicate where in the reply to insert this word or phrase. First we
58
Chapter 4 Making Reply
Flowchart 4.5 Inserting into a Sentence
will amend the DAT A so that the word to be inserted is never at the start, to
make the insertion process obvious.
11070 DATA DO YOU REALISE THAT /PROBAE’LY
HATE YOU AS WELL,WELL /LOVE YOU TOO
1108O DATA IF /DON’T KILL YOU FIRST,SO W
HAT *DISLIKE LOTS OF THINGS
11080 DATA DO /LIKE CHIPS,WHY DO #FEEL P
OWERFUL,HOW DO *KNOW EVERYTHING
We actually already have a record of where to insert the word as IS% tells
us where in the reply the slash or asterisk was found. All we need to do is to
take the part of the reply before the marker, LEFT$(RL$,IS%~1), add the
correct version of SU$(SM%,n), and then the rest of the reply
RIGHT$(RL$,LEN(RL$)-IS%)
800 RL**LEFT*< RL$, IS*i-1 >+SUf< SM-;, @ )+RIGH
Tf < RL$,LENC RLf >-1S'i)
820 RL$~LEFT$< RLf, IS*i-l HSU*< Sf1\', 1 )+RIGH
Tt( RL$, LEN( RL$ >-1 S’i >
Now:
I WILL KILL HIM
59
Artificial Intelligence on the Commodore 64
produces:
IF I DON'T KILL YOU FIRST
and:
I DISLIKE COMPUTERS
gives:
SO WHAT YOU DISLIKE LOTS OF THINGS
Although we are now inserting the subject into the reply sentence more
naturally, we are only dealing with one subject per sentence. Another
minor modification will allow us to insert any number of subjects into a
sentence. All we need to do is to keep repeating the search for markers until
no more are found. A start variable ST% is defined as I in line 500, and then
a search is made for the first type of marker. When a match is found, ST% is
reset to one more than the match position. When RL$ has been modified by
line 800 we now need to jump back to 510 to look for more markers. If no
match is found for the first marker then ST% is reset to 1. The second type
of marker is then checked for in the same way.
500
RL$
*RP*CVMV.)‘S
3T*4= 1
510
IN*.
-RLf •• TA$ = ".-
-" : GOSUB 5
000
520
IF
IS*;>0 THEN
ST*;-IS*;+1
: GOTO
900
525
ST*;
*1
530
IN/.
~RL$ : TA$=":1
r : GOSUB 5
000
540
IF
IS’-./Q THEN
ST*;~IS*;+1
: GOTO
320
81Q GOTO 510
830 GOTO 530
11070 DATA DO YOU REALISE THAT /PROE’ABL
Y HATE YOU AS WELL, WELL .••-LOVE YOU TOO
11080 DATA IF /DON'T KILL YOU FIRST
11085 DATA SO WHAT /DISLIKE LOTS OF THI
NGS ESPECIALLY *
11030 DATA DO /LIKE CHIPS,WHY DO *FEEL
POWERFUL, *TH INK *KN0W EVERYTHING
Now:
I KNOW EVERYTHING
60
Chapter 4 Making Reply
produces:
YOU THINK YOU KNOW EVERYTHING
and:
I DISLIKE COMPUTERS
gives:
SO WHAT I DISLIKE LOTS OF THINGS ESPECIALLY YOU
OBJECTions on the SUBJECT
Everything is starting to look rosy until you try something like:
I HATE YOU
which replies:
DO YOU REALISE THAT YOU PROBABLY HATE YOU AS WELL
The problem here is that we are jumping out of the search routine as soon as
the first match is found, and that although we are checking for the subject
T we are finding the object ‘YOU’ first. As ‘YOU’ comes before T in the
subject array this is found first, in spite of the fact that it comes later in the
sentence.
As we cannot practically mimic all the intricacies of the human brain, we
will have to make the assumption that the subject always comes before the
verb, and the object after it. In the program so far we have been checking
for the subject before we checked for the verb, and we will have to reverse
that order. The verb position in the input is the value of IS% when a verb is
found, so we will save that as a verb position VP% pointer.
200 FOR M=0 TO VB*
210 ST*= 1 • ri > : GQSUB 5000
220 IF ISJJs0 THEN NEXT M : GOTO 100
238 VflX- M : VP>£” I s';
Now when a match with the subject array is found, we can compare that
position IS% with the stored verb pointer VP%, and reject the match if the
subject is positioned after the verb (see Flowchart 4.6).
61
Artificial Intelligence on the Commodore 64
Flowchart 4.6 Rejecting Object Matches
240 FOR M=0 TO Sift
250 ■■ Tfl$=SU$< fl > • GOSUB 5000
260 IF IS‘/."0 THEM NEXT M'GOTO 100
270 IF ISJS>VP5£ THEN NEXT fl : GOTO 100
280 SMX=M
(If you are too lazy to retype those lines you can add a couple of jumps to
rearrange the order instead.)
140 GOTO 240
231 GOTO 500
271 GOTO 200
270 VMX=H : VF'X~ I S'-'.
225 IF ISX >VP’i THEN NEXT fl : GOTO 100
62
Chapter 4 Making Reply
A change of tense
If we change to the past tense of the verb, we may or may not find this. With
the first five verbs the situation is straightforward: to change to the past
tense we just add k D' to the end of the present tense. Both forms are
therefore accepted.
HATE HATED
LOVE LOVED
KILL KILLED
DISLIKE DISLIKED
LIKE LIKED
H owever, with the last two verbs the word changes completely, so there can
be no simple match. Although we might get away with checking for‘KN\ as
this is a rare combination, it would not be practical for us to use such a
common group as ‘FE 1 as a keyword.
FEEL FELT
KNOW KNEW
It is easier if we treat all verbs in the same way and, if there are no
constraints on memory, then we can simply put all the possible versions
into the verb array in pairs.
10000 SU*;~26 « VP’i-13: RP^S
11060 DATA HATE, HATED, LOVE, LOVED, KILL, KI
LLLED,DISLIKE,DISLIKED
11060 DATA LIKE,LIKED,FEEL,FELT,KNOW,KHE
W
Unless we want to have different replies for the different tenses, we will now
have to divide the verb variable VM% by two, to point to the correct reply
for both forms.
230 VM~M "2 : VP';** I S':
63
CHAPTER 5
Expert systems
A human expert is someone who know's a great deal about a particular
subject and who can give you sensible advice (‘expert opinion 1 )
on it. Such expertise is only acquired after long training and a great deal of
experience, so unfortunately real experts are few and far between. In
addition they are often not on hand when a problem needs to be solved.
Scientists have therefore applied themselves to the problem of producing
computer programs which mimic the functions of such human experts.
Such programs have the advantage that they can be copied very easily to
produce an infinite number of experts, and of course they do not need tea-
breaks, sleep, pay-rises, etc, either! Of course, the computer must be totally
logical and can still only follow pre-programmed instructions entered by
the programmer. It is interesting to note that science fiction authors have
envisaged problems when the ultimate‘experts’(such as HAL in ‘2001: A
Space Odyssey’ or Isaac Asimov’s positronic robots) are faced with
alternative courses which conflict with more than one of their prime
directives and which produce not system crashes but ‘pseudo-nervous
breakdowns’.
Before we can start W’riting programs for ‘expert systems’, we must ask
ourselves how a human expert works.
Let us first consider the simplest situation, where the expert’s task is to
find the answer to a knowm problem.
First of all he takes in information on the current task.
Secondly he compares this with information stored in his brain and looks
for a match.
Finally he reports whether or not a match has been found.
What we need here is simply a database program which tries to match the
input against stored information. (See Flowchart 5,1). A user-friendly
system would accept natural language (see earlier), but to keep things
simple here we will stick to a fixed input format. To start with, let’s look at
recognising animals by the sound they make. We set up two arrays: the
question array QU$(n) contains the sounds which are known, and each
65
Artificial Intelligence on the Commodore 64
element of the answer array AN$(n) contains the name of the relevant
animal.
10 GOSUE' 10Q00
10000 DIH QU$( 4 >.. RN*< 4 >
10010 DATA MIAON,CAT,WUFF,DOG,MOO>COW,HO
OT,OWL,NEIGH,HORSE
10020 FOR N=0 TO 4 ■ READ QU$< NAN5K N > : NE
XT N
10030 RETURN
Now we just need to ask for a sound and compare it with the contents of
QU$(n).
20 PRINT"WHAT NOISE DOES IT MAKE";
20 INPUT IN*
40 FOR N-0 TO 4'IF IN$*QU$(N> THEN 100
50 NEXT N
60 PRINT"SORRY I DON'T KNOW THAT ONE"
70 GOTO 20
100 PRINT "AN ANIMAL THAT " ; GJU4K N >> "S IS
A " i AN*C N >
110 GOTO 20
Perhaps we should say at this point that our computer expert may well be
better at this task than the human kind, as it cannot make subjective
judgements, become bored, or accidentally forget to check all of the
66
Chapter 5 Expert Systems
information in its memory. On the other hand it is not very literate as it
reports‘A OWL’, etc. (We will leave you to tidy that up by adding a routine
which checks w hether the first letter of the answer array match is a vowel.)
Branching out
The example above is very simple as only one question is asked, and there is
only one possible answer. In reality we need to be able to deal with more
difficult problems, where the answer cannot be found without asking a
whole series of questions. For example, what should an expert do if he put
the key in the ignition switch of his car and turned it, but nothing
happened?
There could be a number of reasons for this:
FLAT BATTERY
BAD CONNECTIONS
SWITCH BROKEN
STARTER JAMMED
STARTER BROKEN
SOLENOID BROKEN
To find the cause, he should follow a logical path and make a number of
checks. The first thing to do is to check whether it is only the starter motor
which is not working:
IS IGNITION LIGHT ON? (Y/N)
If the answer to this is ‘N’ then there is no power at the switch, so the cause
must be one of the first three possibilities listed above. We can narrow
things down more by finding out if the lights work:
DO LIGHTS WORK CORRECTLY? (Y/N)
If the answer is yes. then the battery cannot be fiat and it must be connected
to the light switch correctly. So presumably the switch is broken and a
suggestion can be made that you replace it.
REPLACE IGNITION SWITCH
If the lights do not work, then the connections should be checked.
ARE BATTERY CONNECTIONS OK? (Y N)
If the answer is yes, then the battery is fiat so you must charge it (or push!)
67
Artificial Intelligence on the Commodore 64
CHARGE BATTERY OR PUSH CAR
In the same way, a sequence of checks could be made to deal with a
situation where there is a power but the starter mechanism itself does not
work (the last three possibilities).
The simplest way to program this branching structure is by a series of IF-
THEN tests (see Flowchart 5.2).
10 PRINT"FAULT DIAGNOSIS"
20 PRINT
30 PRINT"IS IGNITION LIGHT ON <Y/N>"
40 INPUT IN*
50 IF IN$~"Y" THEN 180
60 PRINT"DO LIGHTS WORK CORRECTLY OVN>"
68
Chapter 5 Expert Systems
70 INPUT IN*
80 IF IN*~"Y" THEN 110
90 PRINT"REPLACE IGNITION SWITCH"
100 RUN
110 PRINT"ARE BATTERY CONNECTIONS OK OV
N )"
120 INPUT IN*
130 IF IN*="Y" THEN 160
140 PRINT"REPAIR CONNECTIONS"
150 RUN
160 PRINT"CHARGE BATTERY OR PUSH CAR!"
170 RUN
180-etc-
This sort of program is relatively easy to write, but as usual is inefficient as
it becomes longer and more complicated.
Pointing the way
A more efficient way to deal with the situation is to put the text into arrays
KloHcharl 5.3 Pointing to the Next Output
69
Artificial Intelligence on the Commodore 64
and have pointers which direct you to the next question or reply, according
to whether you answer yes or no to the current question (see Flowchart
5.3).
The format for entering the DATA for each branch point is, then:
(TEXT),(Pointer for ‘YES’),(Pointer for'NO')
The first question was:
IS IGNITION LIGHT ON? (Y N) ... I
If the answer was ‘N’ then you need to ask the second question:
DO LIGHTS WORK CORRECTLY?(Y N) ... 2
Otherwise you need to continue with the other part of the diagnosis (which
we have not included but which would be point 7).
We need to set up three arrays: OPS(n) contains the output (text). Y(n)
the pointer for 'yes’, and N(n) the pointer for 'no . To make the program
easy to modify, a variable NP is used for the number of points. The DATA
is read in groups of three into each element in these arrays. Where the
DATA point is a possible end of the program, this is indicated by the Y(n)
and N(n) pointers being set at zero.
10 GOSUE* 10000
10000 HP"7
10010 D11’1 OPtX HP > .• YX HP >.■ H< HP >
11O00 DfiTfl "IS IGMITI0H LIGHT OH",7,2
11010 DfiTfl "DO LIGHTS WORK CORRECTLY" .• C
4
11020 DfiTfl "REPLACE SWITCH",0,0
11030 DATA "ARE BATTERY COHHECTIONS OK 1
1104O DATA "CHARGE BATTER v OR PUSH CAR*
0,0
11050 DATA "REPAIR COHHECTIOHS",0,0
11060 DATA "-rest of program-",0,0
12000 FOR H=1 TO HP
12010 READ 0P$ <H),Y<H >,H<H>
12O20 HEXT H
12000 RETURM
The actual running routine is very simple. A pointer CP is used to indicate
the current position in the array: to begin with this is set to I and the first
70
Chapter 5 Expert Systems
text printed. If this is an end point Y(CP)=0 (hardly likely just yet!), then
CP is reset to 1 so that the sequence starts again. On the other hand, if a real
pointer is present then an INPUT is requested. If the input is‘Y\ then CP is
set to the value contained in the appropriate element of the Y(n) array,
otherwise it is set to the value contained in the N(n) array.
20 CP-1
20 PRINT 0P4XCP)
40 IF Y<CP>=0 THEN 20
50 INPUT im
60 IF IN$" H Y" THEN CP=*Y< CP > * GOTO 30
70 CP«N<CP>
30 GOTO 30
A parallel approach
An alternative to the sequential branching method described above is the
parallel approach which always asks all the possible questions before it
reaches its conclusion. This method usually takes longer than following an
efficient tree structure, but it is more likely to produce the correct answer as
no points of comparison are omitted.
Let us consider how we might distinguish between various forms of
transport.
We will consider eight features and mark 1 or 0 for the presence or
absence of these in each of our five modes of transport (see Table 5.1). If
you look closely you will notice that the pattern of results varies for each of
the different possibilities so it must be possible to distinguish between them
by these features.
Table 5.1:
Presence or
Absence of Features
bicycle
car
train
plane
horse
wheels
1
1
1
1
0
wings
0
0
0
1
0
engine
0
1
1
1
0
tyres
1
1
0
1
0
rails
0
0
1
0
0
windows
0
1
1
1
0
chain
1
0
0
0
0
steering
I
1
0
1
I
We will enter these values as DATA and then READ them into a two-
dimensional array FE(n,n) which will hold a copy of this pattern, together
71
Artificial Intelligence on the Commodore 64
with a string array containing the names of the objects OB$(n).
10 G0SIJB 10000
10090 DIM 0E'$< 5 > , FEC 5,8 >
11 000 DflTft BI CYCLE, 1,0,0.. 1,0,0,1,1
11010 DflTft CAR,1,0,1,1,0,1,0,1
11020 DATA TRAIH,1,0,1,0,1,1,0,0
11030 DATA PLANE,1,1,1,1,O,1,0,1
11040 DATA HORSE,0,0,0,0,0,0,0,1
12000 FOR H-l TO 5
12010 READ 0B$< N >
12020 FOR M-l TO 8
12030 READ FE< N,M>
12040 NEXT H,N
12000 RETURN
We can now ask whether the first feature is present or not and use the reply
to print out which modes of transport match at this particular point (see
Flowchart 5.4).
Flowchart 5.4 A Parallel Approach
72
Chapter 5 Expert Systems
100 PRINT"DOES IT HAVE WHEELS"
50© INPUT IN*
510 AN~1 : IF IN$~ ,, N“ THEN flN=0
520 FOR N*1 TO 5
530 IF FE<N,l)*flN THEN PRINT OB*<N)
540 NEXT N
In this case, answering ‘Y’ will produce a print-out of:
BICYLE
CAR
TRAIN
PLANE
and answering ‘N’ will produce a print-out of only:
HORSE
This clearly demonstrates a possible disadvantage of the parallel method
as, although we have just shown that only a horse does not have wheels, the
program insists that we still ask all the other questions before it commits
itself. This is not really as silly as it seems at first, as if you answer ‘ Y’ to the
next question (‘does it have wings’) you will see that the computer quite
logically refuses to believe in flying horses.
If we put the actual comparison part as a subroutine we can use it to
check for all eight features in turn. We would need to make slight
modifications, adding an array pointer AP which is incremented to check
the next element of the feature array FE(N,AP) in each cycle (see
Flowchart 5.5).
100 PRINT"DOES
110 GOSUB 500
120 PRINT"DOES
130 GOSUB 5O0
140 PRINT"DOES
150 GOSUB 500
160 PRINT"DOES
170 GOSUB 500
180 PRINT"DOES
190 GOSUB 500
200 PRINT"DOES
210 GOSUB 500
220 PRINT"DOES
230 GOSUB 500
IT
HAVE
WHEELS"
IT
HAVE
WINGS"
IT
HAVE
AN ENGINE
IT
HAVE
TYRES"
IT
NEED
RAILS"
IT
HAVE
WINDOWS"
IT
HAVE
A CHAIN"
73
Artificial Intelligence on the Commodore 64
240 PRINT"IS IT STEERABLE"
250 GOSUB 500
400 PRINT
410 RUN
510 flP“flP+l : FlN-1 1 IF IN**"N" THEN RN*0
530 IF FE<N,AP>=AN THEN PRINT OB$<N>
560 RETURN
Flowchart 5.5 Checking the Features in Turn
Top of the pops
The previous routine will print out a list of matches for each individual
question as it proceeds, but it will not actually tell us which set of DATA is
an overall match for the answers to all the questions. We can produce a
SCORE which shows how well the answers match the DATA by having a
success array element SU(n) for each object, which is only incremented
when a match is found FE(N,AP)=AN (see Flowchart 5.6).
74
Chapter 5 Expert Systems
Flowchart 5.6 Measuring Success
260 PRINT
279 PR I NT 1 'SCORE 11
280 PRINT
300 FOR N=1 TO 5
310 PRINT 0B*<N>iSU<N)
320 NEXT N
530 IF FE<N> flP)=flN THEN PRINT 0B$(N)‘SLK
N >=SLK N )+l
10010 DIM SIX 5 )
If a complete match is found then SU(n) will be equal to 8. Where one or
more points were incorrect the score will be lowered. Scoring in this way is
particularly useful where the correct answers to the questions are more a
matter of opinion than fact (eg is a horse really steerable?), as the highest
score actually obtained probably points to the correct answer anyway.
(Notice that in this case each correct answer has equal weighting.)
Better in bits
You may have noticed that we just happened to use eight features for
comparison and it may have occurred to you that this choice was not
entirely accidental as there are eight bits in a byte. If we consider each
feature as representing a binary digit (see Table 5.2), rather than an
absolute value, then each object can be described by a single decimal
number which is the sum of the binary digits, instead of by eight separate
values. We will convert to decimal with the least significant bit at the top so
that, starting from the top at ‘wheels’, each feature is equivalent to 1,2,4, 8,
16, 32, 64, 128 in decimal notation.
75
Artificial Intelligence on the Commodore 64
Table 5.2
: Binary Weighted Features
bicycle
car
train
plane
horse
wheels
1
1
1
1
0
wings
0
0
0
2
0
engine
0
4
4
4
0
tyres
8
8
0
8
0
rails
0
0
16
0
0
windows
0
32
32
32
0
chain
64
0
0
0
0
steering
128
128
0
128
128
sum total
201
173
53
175
128
Flowchart 5.7 Producing a Binary Score
76
Chapter 5 Expert Systems
It is not too difficult to convert our‘score’ of 1 to 8 into the appropriate
binary value, as long as we remember that the decimal value of the binary
digit BV must double each time we move down, and that we must only add
the current binary value to the score if the answer was ‘yes’ (AN=1, see
Flowchart 5.7).
If you consider for a moment, you will realise that we only need to keep
track of the total number produced, SU, by adding the binary values of the
‘yes' answers. There is no need to loop through and check each part of the
array contents each time, or even to have a two-dimensional array at all!
The only DATA we need to enter are the overall decimal values for each
object, DV(n), and when all the questions have been asked we can check
these against the decimal value obtained by the binary conversion of the
‘yes, no’ answers, SU (see Flowchart 5.8). The simplest thing for you to do
Flowchart 5.8 Matching the Decimal Value
now is to delete everything after line 260 and start entering from scratch
again!
270
PRINT,
"SCORE".
: SU
280
PRINT
300
FOR N"
1 TO 5
310
IF DV<
N)*SU THEN
PRINT,"0B$<
400
320
NEXT N
330
PRINT,
"OBJECT
NOT
FOUND"
400
PRINT
410
RUN
500
INPUT
IN*
77
Artificial Intelligence on the Commodore 64
510 RN~1■IF IN*«"N" THEN RH*0
520 IF RH~ 1 THEN SU=SIJ+BV
520 BV=BV+BV
540 RETURN
10000 DIM OB* <5 ),DV<5 >
10010 E'V=1
11000 DflTR BICYCLE,201
11010 DflTR CAR,173
11020 DflTR TRAIN:.53
11030 DATA PLANE,175
11040 DflTR HORSE,129
12008 FOR N-l TO 5
12010 READ OB$<N),DV<N)
12020 NEXT N
12000 RETURN
This approach obviously saves a lot of memory and time, as each array
element takes up several bytes and must be located before it can be
compared, so it is particularly useful where you are dealing with large
amounts of information. On the other hand, it does mean that you have to
calculate the decimal equivalents of all of the bit patterns before you can
use them, and it also gives you no clues when a complete match is not
found. (Note that you cannot simply take the nearest decimal value here, as
the decimal equivalent value of each correct answer depends on its
position.) Of course you could do the calculations the hard way, but if you
enter the bit pattern as a string, IS, then it is quite easy to convert it to the
equivalent decimal value DV by comparing each single character slice
MIDS(I$,N,1) with T and then adding on the value of the appropriate
binary digit BD if a match is found.
20008 BD~1 : INPUT 1$
20010 FOR N~1 TO 8
20020 IF MID$( 1$.*N; 1 1 M THEN DV=DV+BD
20O20 BD-BD+BD
20040 NEXT N
20050 PRINT DV
20060 RUN
78
CHAPTER 6
Making Your Expert System Learn for
Itself
Although the ‘expert' systems described so far will function all right, they
all require you to give them the correct rules on which to base their
decisions in advance, which can be very tedious.
However, it is possible to construct an expert program which can learn
from its mistakes and work out the decision rules for itself, provided that
you can tell it when (although not where) it goes wrong. This is obviously
an advantage if you are not altogether sure of the correct rules yourself
anyway! In this case we start out with a series of features which should
enable us to distinguish between the different objects, but without any pre¬
defined yes/ no pattern of these features (‘decision rule’) to guide us. Instead
we use the program itself to calculate what the pattern should be.
We will work with our familiar transport example and begin by setting
up some variables. FE% is the number of features to be considered (8),
FE$( n) is an array containing the names of these features, FV(n) is an array
which will hold the values which you give to each feature as input at any
particular point (0 or 1), and RU(n) is an array which will hold the current
overall values of the decision rule on each feature.
10 gosub 10000
10000 FE.--.~8
10010 DI n FE$C FE"; >, FVC FE’-i >, RUC FE-; >
10020 FOR N=1 TO FE’i
10020 READ FEfCH)
10040 NEXT N
11000 DATA WHEELS,WINGS,ENGINE,TYRES,RAI
LS,WINOONS,CHRIN,STEER1NG
12000 RETURN
Each feature is considered in turn (see Flowchart 6.1). First the current
feature value FV(n) for this cycle is set to zero, and then a ‘yes/no’ input
INS is requested from the user on each point. If INS is ‘Y’ the feature value
element FV(N) is set to I; otherwise it remains set at zero. This will produce
a pattern which describes the object as ‘0’ and ‘T in array FV(n).
79
Artificial Intelligence on the Commodore 64
( INPUT
FEATURE)
WO
YES
CURRENT
FEATURE
VALUE ^ 1
DE615/0N
VALUE = 0
■
YES
Flowchart 6.1 Learning to Distinguish Between Two Objects
60 FOR N~1 TO FE’i
70 FVOO-0
80 PRINT FE$CN>;"
90 GET I NT- IF I NT-" ,h THEN 90
100 PRINT INT,
110 IF IN$~"V" THEN FV(N}~ 1
120 NEXT N
Before you start a decision variable DE% is set to zero. This is
recalculated as the sum of the current value of DE%, plus each of the
feature values FV(N) entered, multiplied by the current decision rule values
RU(N).
125 DE'i=0
130 FOR N~1 TO FE'i
150 OE’-'.~DEX+FV< N >:*:RLK N >
160 NEXT N
170 PRINT "DE'-.~ M ;DE>.
80
Chapter 6 Making Your Expert System Learn for Itself
Which is which?
To start with we will consider the simplest situation where there are only
two possibilities — a bicycle or a car. Initially we make the distinction
between these quite arbitrarily by saying that if the final value of DE% is
equal to or greater than 0 then it is a bicycle, whereas if DE% is less than 0
then it is a car. It does not really matter that this is not actually true as the
system will soon correct itself. When the program has made a decision on
the basis of the value of DE% it requests confirmation (or otherwise) of the
result.
180 IF DE5£>*0 THEN PRINT”IS IT fl BICYCLE
M ;* INPUT IN**GOTO 200
190 IF DE"i<0 THEN PRINT” IS IT fl CAR M .-I
NPUT IN**GOTO 220
Three possible courses of action may be taken according to whether or not
the computer’s decision was correct. If it was correct then effectively no
action is taken (a weighting variable WT% is set to zero), and the program
loops back for another try. If DE% was >=0 but the computer was wrong,
then the weighting variable WT% is set to minus one, whilst if DE% was <0
but the computer was wrong then WT% is set to plus one.
200 IF INf^Y” THEN WT%=*0: GOTO 240
210 klT*'.=-l : GOTO 240
220 IF IH$="Y" THEN UT>,=0 • GOTO 240
230 WT‘;-i
The effect of the weighting variable is to modify the values in the rule array
RU(N), pulling them down when they are too high, and pulling them up
when they are too low.
240 FOR N=1 TO FE’i
250 RLK N )-RlK N HFV< N >TWT“i
260 PRINT RLKN),
270 NEXT N
280 PRINT
290 GOTO 60
The way the system operates is best seen by a demonstration. Type RUN
and then follow this sequence of entries. (Note that the punctuation has
been designed to give a screen format which clearly indicates the
relationship between your input values and the decision rule values.)
First of all enter these values:
WHEELS Y WINGS N ENGINE N TYRES Y
RAILS N WINDOWS N CHAIN Y STEERING Y
81
Artificial Intelligence on the Commodore 64
The program will return with a decision value DE% of zero, as this is the
initial value and no modifications have yet taken place:
DE%=0
As DE% is 0, the system assumes that this is a bicycle and asks for
confirmation, to which the answer is of course ‘yes’.
IS IT A BICYCLE ? Y
The print-out of the contents of the rule array RU(n) shows that these have
not changed from zero as the correct answer was, by pure chance, obtained:
oooo
0 0 0 0
Now try entering this sequence, which describes a car:
WHEELS Y WINGS N ENGINE Y TYRES Y
RAILS N WINDOWS Y CHAIN N STEERING Y
DE% is still zero, so the wrong conclusion is reached and the wrong
question is asked, to which the answer must be ‘no’:
DE%=0
IS IT A BICYCLE ? N
Now, as a mistake was made, the decision rule is modified by subtracting
one from each value in the rule array where a ‘yes’ answer was given. The
contents of the rule array thus become:
-I
0
-1
“1
0
-1
0
-1
If you once more
enter the values which describe a car, the program will
come up with the correct answer:
WHEELS Y
WINGS N
ENGINE Y
TYRES Y
RAILS N
WINDOWS Y
CHAIN N
STEERING Y
DE%=-5
IS IT A CAR ? Y
-1
0
-1
-1
0
-1
0
-1
82
Chapter 6 Making Your Expert System Learn for Itself
Before you feel too pleased with yourself, try giving it the values for a
bicycle again, which it will get wrong!
WHEELS Y WINGS N ENGINE N TYRES Y
RAILS N WINDOWS N CHAIN Y STEERING Y
DE%=-3
IS IT A CAR ? N
0 0-10
0 -I 1 0
However the positive features which are common to the bicycle and the car
are now automatically increased by one, so that if you repeat this last
sequence it will now produce the correct conclusion:
WHEELS Y WINGS N ENGINE N TYRES Y
RAILS N WINDOWS N CHAIN Y STEERING Y
DE%=1
IS IT A BICYCLE ? Y
0 0-10
0-11 0
The situation has now stabilised and the program will always recognise
both car and bicycle correctly every time you enter the features which
describe them:
WHEELS Y WINGS N ENGINE Y TYRES Y
RAILS N WINDOWS Y CHAIN N STEERING Y
DE%=—2
IS IT A CAR ? Y
0 0-10
0 -I 1 0
Notice that the final value of DE% for a bicycle is 1, and for a car—2. If you
look at the rule array values, you will see that these correspond in both
number and position to the unique features which distinguish these objects
(CHAIN for bicycle, and ENGINE and WINDOWS for car).
83
Artificial Intelligence on the Commodore 64
A wider spectrum
Although you have now managed to teach your computer something, it is
not exactly earth-shattering for it to be able to distinguish between only
two objects. Let’s expand the system to deal with a wider spectrum of
possibilities (see Flowchart 6.2). To start with we need to define the
Flowchart 6.2 Learning the Rules for a Wider Spectrum of Possibilities
number of objects we wish to be able to recognise OB%, name them as
DATA which we READ into a new array OB$(OB%), change our decision
rule array into a two-dimensional form, RU(FE%,OB%), which can hold
rules for each of the objects separately, and set up a decision array DE(n) to
hold decision values for each object.
84
Chapter 6 Making Your Expert System Learn for Itself
10 Gosue 10000
10000 FE’/.=8= OBX-5
10010 DIN FE$C FE’; FVC FE* >, RIJ< FE*, OB’; ),Q'
B$<OB*>,DE<OB*>
10020 FOR N~1 TO FE*
10020 RERD FE$CN>
10040 NEXT N
10050 FOR N~i TO OB*
10060 RERD OB* CN >
10070 NEXT N
11008 DRTR WHEELS,W I NGS,ENG I NE,TYRES,RR I
LS,M I NDOWS,CHR I N,STEER I MG
11010 DRTR B I CYCLE, CAR, TRRIN, PLANEHORSE
12000 RETURN
Rather than just having a single decision variable DE%, we need here to
determine a decision value for each object each time. In each cycle we must
first set DE% to zero, and then zero every element in the decision array
DE(n) so that we start with a clean slate for every object.
20 DE*=0
30 FOR N=1 TO QE'X
40 DEC N )=0
50 NEXT N
The values for each feature are then entered in exactly the same way as
before.
60 FOR N=1 TO FE’;
70 FVC N )~0
80 PRINT FEfC N
90 GET IN$ : IF IN$="" THEN 90
100 PRINT IN*
110 IF IN$="Y" THEN FVCN>=1
120 NEXT N
Each element of the decision array DE(n) is now updated according to the
status of the entered values FV(n) and the contents of the appropriate rule
array element RU(n.m).
120 FOR N~1 TO FE’;
140 FOR M“1 TO 0B>.
150 DEC M >~DEC M )+FVC N )TRUC N, M >
160 NEXT M,N
85
Artificial Intelligence on the Commodore 64
We now need to look to see if any of the decision values for any of the
objects DE(n) are greater than or equal to the overall decision value DE%.
If this is true, we set a ‘top score’ TS% variable equal to the number of the
object producing the best match.
170 FOR N” 1 TO OB'-.
IPO IF DE<H)>~DE“; THEN DEX'DECH) • TSX~N
190 NEXT N
The best guess of the system is that this is the correct answer, so once again
it asks for confirmation, and simply returns for a new input without
making any changes if the answer was correct.
200 PRINT "WAS IT "; 0E'*< TSX >; "
210 GET IN*-IF IN*""" THEN 210
215 PRINT IN*
220 IF IN*="Y" THEN 20
If this was not the correct answer, the names and numbers of all the objects
are printed out and you are asked for the number of the correct answer
CR%. (The limitations on CR% prevent you crashing the program by
entering an illegal value.)
230 FOR N=1 TO OB’-i
240 PRINT N,00*'-.N >
250 NEXT N
260 PRINT "WHICH WAS IT";
270 GET CR*; : IF CRX< 1 OR CRX>5 THEN 270
275 PRINT CR5£
A check is now made to see if the decision value for each object DE(n) is
greater than or equal to the overall decision value DE% and whether the
object being considered is not the correct answer. If both of these are true
then the rules are updated again by subtracting the correct feature values
FV(n) to bias in favour of the correct answer.
280 FOR N~1 TO OB*;
290 PRINT DE< N >DE’i > CR’;
:-*00 IF DECN)>"DE’; AND NOCR’i THEN FOR
I TO FEX : RUC N / N )*RU< H.. N >"FV< tl >' NEXT M
310 NEXT N
Now the correct feature values FV(n) are added to the rule array for the
correct object, to bias in the opposite direction.
86
Chapter 6 Making Your Expert System Learn for Itself
320 FOR ri=l TO FEJi
320 RU< M, CR J£ >-RU< M, CRX >+FV< M >
340 NEXT M
Finally the status of the rule arrays are printed out so that you can see what
is happening.
350 FOR M” 1 TO OE'X
360 FOR N~ 1 TO FE‘i
370 PRINT RLK N.. M >i
380 NEXT N
390 PRINT
400 NEXT N
410 GOTO 20
Once again a demonstration is the best way to understand what is
happening so enter the following sequence:
WHEELS Y WINGS N ENGINE N TYRES Y
RAILS N WINDOWS N CHAIN Y STEERING Y
The program will come back with the erroneous conclusion that it was a
horse, so you must tell it that this was wrong, when it will ask you for the
correct answer (bicycle = I):
WAS IT HORSE N
1 BICYCLE
2 CAR
3 TRAIN
4 PLANE
5 HORSE
WHICH WAS IT I
The statuses of the various decision and rule arrays are now printed out for
your information (note that the labels shown here are not included on the
screen).
(DE(N))
(DE%)
(CR%)
0
0
I
0
0
1
0
0
1
0
0
1
0
0
1
87
Artificial Intelligence on the Commodore 64
1
0
0
1 0
0
1
1
(bicycle)
— 1
0
0
-1 0
0
-1
-1
(car)
— 1
0
0
-1 0
0
-1
— 1
(train)
■-I
0
0
-1 0
0
-1
-]
(plane)
-1
0
0
-1 0
0
— 1
— 1
(horse)
A
B
c
D E
F
G
H
(A=
: wheels
B= wings
C=engine
D=tyres
E=
-rails
F=windows
G=Chain
H=Steering)
If you look closely you will see that the features which have caused
alterations in the rule arrays are wheels, tyres, chain and steering — all
features which we defined as part of a bicycle and not found in a horse. In
addition, you will see that the values for these features in the bicycle rule
array are now all plus one, whilst the values for these features for all the
other objects are now all minus one.
Now give it the features of a car, which it will think a bicycle, and then
correct it. Notice that the rule arrays for bicycle and car are now amended to
take into account the new information.
WHEELS Y WINGS N ENGINE Y TYRES Y
RAILS N WINDOWS Y CHAIN N STEERING Y
WAS IT BICYCLE N
1 BICYCLE
2 CAR
3 TRAIN
4 PLANE
5 HORSE
WHICH
WAS IT 2
3
3
2
-3
3
2
-3
3
2
-3
3
2
-3
3
2
0
0
-1
0
0
-1
1
0
(bicycle)
0
0
1
0
0
1
-1
0
(car)
-1
0
0
-1
0
0
-1
-1
(train)
-1
0
0
-1
0
0
-1
-1
(plane)
-1
0
0
-1
0
0
“1
-1
(horse)
88
Chapter 6 Making Your Expert System Learn for It self
ABCDE FGH
(A=wheels B=wings C=engine D=tyres
E=rails F=windows G=chain H=steering)
Next give it a plane, which it decides is a car, and correct it again.
WHEELS Y WINGS Y ENGINE Y TYRES Y
RAILS N WINDOWS Y CHAIN N STEERING Y
WAS IT CAR N
1 BICYCLE
2 CAR
3 TRAIN
4 PLANE
5 HORSE
WHICH WAS IT 4
And now a train, which it still gets wrong!
WHEELS Y WINGS N ENGINE Y TYRES N
RAILS N WINDOWS Y CHAIN N STEERING N
WAS IT PLANE N
1 BICYCLE
2 CAR
3 TRAIN
4 PLANE
5 HORSE
WHICH WAS IT 3
And finally a horse, which comes out as a plane!
WHEELS N WINGS N ENGINE N TYRES N
RAILS N WINDOWS N CHAIN N STEERING Y
WAS IT PLANE N
1 BICYCLE
2 CAR
89
Artificial Intelligence on the Commodore 64
3 TRAIN
4 PLANE
5 HORSE
WHICH WAS IT 5
If you continue to feed your expert information, eventually it will get the
right answer every time. How long this will take depends upon the extent of
the differences between the features of the objects, and on the order in
which the objects are presented to the expert. Be warned that it can take a
long time before it becomes infallible. Here is one sequence which
eventually came out right every time.
plane (train)
car (YES)
horse (YES)
plane (car)
car (YES)
car (YES)
bicycle (YES)
bicycle (YES)
plane (car)
car (YES)
bicycle (car)
train (YES)
car (plane)
plane (car)
plane (bicycle)
plane (car)
plane (car)
plane (YES)
train (car)
car (plane)
plane (YES)
plane (YES)
car (YES)
horse (YES)
bicycle (YES)
plane (YES)
car (plane)
car (plane)
plane (YES)
horse (YES)
train (YES)
car (YES)
car (plane)
car (YES)
plane (YES)
bicycle (YES)
To see the final state of the rule array when the ultimate state is reached,
you can stop the program and then type GOTO 350 as a direct command.
As the final scale of values ranges from T6 to —2, you should not be
surprised that it took a long time to get there.
1 0 -1
1 0
-1 4 I
0 -i
0 -1 1
-2 2
-2 6 0
o -i
-10 0
-1 0
ABC
D E
(A=wheels
B=wings
E=rails
F=windows
-2 3
0 (bicycle)
1 -2
0 (car)
1 -1
-2 (train)
0 -2
-2 (plane)
0 -1
0 (horse)
F G
H
C=engine
D=tyres
G=chain
H=steering)
Of course, in a real application of such an expert system you could feed it a
90
Chapter 6 Making Your Expert System Learn for Itself
mass of collected information and conclusions on a subject area and then
leave it alone to digest this and to come up with the rules in its own good
time. As these rules are stored in arrays you could easily write a routine to
save these for re-use later.
91
CHAPTER 7
Fuzzy Matching
Computers are totally logical but our own memory banks are much more
unreliable, which can lead to problems when you are trying to recover
information on a particular subject. For example, English is a very variable
language and there are frequently alternative spellings of the same (or very
similar) surnames, which can cause difficulties.
One way around this problem is to try to match the sound of the word,
rather than the actual letters in it, by means of‘Soundex Coding’, which
was originally developed to assist processing of the 1890 census in the USA.
This method of coding ensures that similar-sounding words have almost
the same code sequence.
The rules for coding a word are as follows:
1) Always retain the first letter of the word as the first character of the code.
From the second letter onward:
2) Ignore vowels (a, e, i, o, u).
3) Ignore the letters w, y, q and h.
4) Ignore punctuation marks.
5) Code the other letters with the values 16 as follows:
Letters Code
bfpv 1
cgjksxz 2
dt 3
1 4
mn 5
r 6
6) Where adjacent letters have the same code only the first one is retained.
7) If length of code is greater than four characters then take first four only.
8) If length of code is less than four characters then pad out to four
characters with zeros.
93
Artificial Intelligence on the Commodore 64
To make this clear here are some examples of Soundex Coded names:
BRAIN B650
(B is retained, R is 6, A and 1 are dropped, N is 5 and a zero is added to pad
out the code.)
CUNNINGHAM - C552
(C is retained, U is dropped, both Ns are represented by the singlecode5,1 is
dropped, the third N is represented by 5, G is 2, H and A are dropped, and
M is coded as 5 — but the resulting code (C5525) is truncated to four
characters.)
GORE - G600
(G is retained, O is dropped, R is 6, E is dropped and zeros are added to pad
the code.)
IRELAND 1645
(1 is retained, R is 6, E is dropped, L is 4, A is dropped, N is 5 and D is 3 —
but the resulting code (16453) is truncated to four characters.)
SCOT - S230
(S is retained, C is 2, O is dropped, T is 3 and zero is added to pad the code.)
If your name is full of vowels and other rejected letters, then you will find
that your code is somewhat abbreviated!
HEYHOE H000
(H is retained, all the other letters are rejected (!), and the code is filled up
with zeros.)
Coding routine
To save all that brainwork, let’s develop a program which allows you to
input a word in English and output it in Soundex Code (see Flowchart
7.1) The first thing to do is to jump to a set-up routine which reads each
group of the retained letters into one element of a Soundex Code string
array SC$(n). (Note that the letters are arranged so that they are in the
array element corresponding to their code value.)
94
Chapter 7 Fuzzy Matching
Flowchart 7.1 Producing a Soundex Code
10 Gosue 10000
10000 DIM SC$<: 6 )
11000 DAT 1=1 BFF'V, CGJKSXZ, DT .• L , MN, R
12000 FOR H-l TO 6
12010 READ SC«M>
12020 NEXT N
12000 RETURN
We can now input the word to be converted, INS, and, to begin with, make
the coded version of this, COS, the first letter of that word (following the
first rule above).
95
Artificial Intelligence on the Commodore 64
100 INPUT IN*
110 CU$-LEFT$<: IN$\* 1 )
We now need to check the other letters of the word, 2 TO LEN(INS), in turn
after first making a temporary string TM$ equal to the current letter to be
translated.
120 FOR N~2 TO LEN<IN$>
130 TMf=MID$C I * N .■ 1 >
As conversion to the code numbers will be required at various points in the
final problem, we will set up this process as a subroutine at line 1000.
140 GOSUE* 1000
We have to check TM$ against each individual letter in each group of
letters SC$(n) to find a match. To check each letter group, we have to go
round six times, making a search string SES the current Soundex Code
group, and jumping to an 1NSTR routine which checks each letter in the
group against TM$ in turn.
1000 FOR P-l TO 6
1010 SE$=Se*<P>
1020 GOSUE- 5008
The INSTR routine is similar to the one used in previous chapters.
When the INSTR check has been made, we have to determine whethera
match has been found to any of the Soundex groups, and if so, to which
group. If no match is found then SP% will be set to zero. If a match is found
then SP% will be set to M which will point to the value of the code group
matched.
5000 FOR M-l TO LENCSEf)
5010 IF MID$'.:SE$,ri, 1 )=™$ THEN SP’i-M ; RET
URN
5020 NEXT M
5030 sp;-:~0
5040 RETURN
If a match is found, SP%>0, then we convert the numeric value of the loop
scanning the code groups P to a string TM$ which replaces our original
temporary string. (The STR$ command converts a number into a string,
but we also need to use RIGHTS as STRS automatically adds a space onto
the front of the number string.)
96
Chapter 7 Fuzzy Matching
1020 IF SP5£>0 THEM TM*=RIGHT*CSTR*<P>.■ 1 >
> RETURN
If no match is found in that group, we have to check the next group.
1040 NEXT P
If no match is found at all, then TM$ must contain one ofthe characters to
be ignored. So we reset TMS empty [$=“”] and RETURN.
1050 TM*=" ,#
I960 RETURN
We can now make the coded string COS equal to the original coded string
plus the newly converted character TM$.
170 C0*=C0**TM$
Now we loop back to deal with the next character in IN$.
180 NEXT H
When the end of INS is reached, we print out the input INS and the entire
coded string COS before going back to 100 for another input.
210 PRINT: PRINT "NAME 11 * "CODE 11: PRINT
cot
320 GOTO 100
If you input the name STEVEN you will now get the code S315 which is
correct. However, if you try BRAIN or CUNNINGHAM you will get the
codes B65 and C55525 respectively. The code for BRAIN is too short and
needs padding out with zeros, and the code for CUNNINGHAM is too
long and the same codes are repeated one after another for the letter N.
Dealing with the details
To solve the problem of the repetition of the same code for adjacent letters,
we need to keep a record of the last temporary string LTS. We need to make
LTS the code of the first character in INS to start with, so that the initial
letter is not repeated. As we go through the FOR-NEXT loop, we must
compare LTS with TMS, and if they are the same we must not add TMS to
COS. Otherwise we need to make LTS the latest TMS.
97
Artificial Intelligence on the Commodore 64
110 TMf *LEFT*< I N$, 1) = CO$=TH$ : GOSUB 1000 ••
LT$=TM$
150 IF TM$=LT$ THEN GOTO 180
168 LT$=TM$
Now we can sort out the problem of the code being too short. First of all we
check the length of the string LEN(CO$)<4. If it is too short, we add three
zeros on to the end and then use LEFTS to cut the string back down to the
correct size (four characters).
98
Chapter 7 Fuzzy Matching
190 IF LEN< C0$ ; ><4 THEN CO$ 5S CO$+"000" : CQ$
“LEFT?< COT, 4 >
Finally, if the string is too long then we cut it down to size with
LEFT$(CO$,4) again.
200 IF LEN< 00$ >>4 THEN COT-LEFT?':! COT, 4 )
Matchmaking
Now that we have a reliable method of producing the Soundex
Codes, let’s give it something to work on. The first task is to read a
list of names out of DATA statements into a name string array NA$(n).
Our demonstration list only consists of eighteen names — if you want
more, a quick flick through your local telephone directory should soon
solve that problem! Note that the number of words is also stored as NW%.
10010 NW*=17iDIM Nfl*<NW50
11010 DATA ABRAHAM,ABRAHAMS,ABRAMS,ADAM,
ADAMS,ADDAMS,ADAMSON,ALAN,ALLAN,ALLEN
11020 DATA ANTHONY,ANTHONY,ANTONY,ANTROB
US,APPERLEY,APPLEBEE,APPLEBY,APPLEFORD
12020 FOR N-0 TO 17
12040 READ NAT< N>
12050 NEXT N
The whole idea of matching with Soundex Codes relies on the fact that you
use the Soundex Code to make the match before printing the possible
words. We therefore have to find the codes for each of the names from the
DATA and put these coded into an equivalent string array NC$(n). The
routine to find the Soundex Code is virtually identical to the one used to
find the code of an input, as described above.
10020 DIM MC*OMO
12068 PRINT-PRINT "NAME","CODE"•PRINT
12070 FOR Q~0 TO NWX
12080 PRINT NATKQ >,
12098 TM$"LEFTf(NATKQ>,1> : COT-TMT'GOSUB
1000 LTT~TMT
1210O FOR N=2 TO LEN<NA*<Q>2>
12110 TM$=MIDT<NATK Q>,N,1>
12120 GOSUB 1000
12120 IF TM?=LT? THEN NEXT N•GOTO 12170
12140 LT?-=TM?
99
Artificial Intelligence on the Commodore 64
12158 C0f*C0f+TMf
12160 NEXT N
12170 IF LEN<C0f><4 THEN CO$=CO$+"000"*C
Of~LEFTf< COf 4 >
12180 IF LENCCOf >>4 THEN CQf=LEFT$<COf,4>
12130 PRINT COf
12200 NCf(Q >“COf
12210 NEXT Q
If you RUN this now, you will see all the codes for the DATA produced
before the input request.
NAME CODE
ABRAHAM
A165
ABRAHAMS
A165
ABRAMS
A165
ADAM
A350
ADAMS
A352
ADDAMS
A352
ADAMSON
A352
ALAN
A450
ALLAN
A450
ALLEN
A450
ANTHANY
A535
ANTHONY
A535
ANTONY
A535
ANTROBUS
A536
APPERLEY
A164
APPLEBEE
A141
APPLEBY
A141
APPLEFORD
A141
The only thing we need to do now is to find which codes of these names
match the code of your input and then to print out these names with a
FOR-NEXT loop.
240 PRINT
250 FOR N=0 TO NUT
260 IF COf=HCf<N> THEN PRINT Nflf<N),NC$(
N >
270 NEXT N*
This will only print words with exactly matching Soundex Codes. For
100
Chapter 7 Fuzzy Matching
example, if you try entering the name APPLEBE you will get the following
response:
? APPLEBE
NAME CODE
APPLEBE AI41
APPLEBEE A141
APPLEBY A141
APPLEFORD A141
Although APPLEBE (one E at the end!) is not present in the DATA, we
have found APPLEBEE and APPLEBY, as well as APPLEFORD (where
the interesting sound at the end has been chopped off).
Flowchart 7.3 Partial Matching
101
Artificial Intelligence on the Commodore 64
Partial matching
Notice that on the other hand APPERLEY has been rejected, even though
it sounds quite similar at first. It would therefore be useful if we could also
print out partial matches.
This can easily be done by adding an extra FOR -NEXT loop, which
compares a decreasing section of the input LEFTS(COS.M) with
decreasing lengths of the stored codes LEFT$(NC$(N),M) (see Flowchart
7.3).
230 FOR H“4 TO 1 STEP ~i
248 PRINT PRINT H,"CHARACTERS MATCH"•PRI
NT
260 IF LEFT*< COT, 11 >~LEFTT( NCT< N >, M > THEN
PRINT NflT(N>.■ NCTCN>
280 PRINT PRINT "PRESS KEY TO CONTINUE"
290 GET INTIF IHT“"" THEN 290
30O PRINT PRINT
210 NEXT M
If you now try APPLEBE you can see the whole range of possibilities.
? APPLEBE
NAME CODE
APPLEBE AI41
4 CHARACTERS MATCH
APPLEBEE A141
APPLEBY A14I
APPLEFORD A141
PRESS KEY TO CONTINUE
3 CHARACTERS MATCH
APPLEBEE A141
APPLEBY A141
APPLEFORD A141
PRESS KEY TO CONTINUE
2 CHARACTERS MATCH
ABRAHAM AI65
ABRAHAMS AI65
ABRAMS A165
APPERLEY A164
102
Chapter 7 Fuzzy Matching
APPLEBEE
A141
APPLEBY
A141
APPLEFORD
A141
PRESS KEY TO CONTINUE
1 CHARACTERS MATCH
ABRAHAM
A165
ABRAHAMS
A165
ABRAMS
A165
ADAM
A350
ADAMS
A352
ADDAMS
A352
ADAMSON
A352
ALAN
A450
ALLAN
A450
ALLEN
A450
ANTHANY
A535
ANTHONY
A535
ANTONY
A535
ANTROBUS
A536
APPERLEY
A164
APPLEBEE
A141
APPLEBY
A141
APPLEFORD
A141
PRESS KEY TO CONTINUE
103
CHAPTER 8
Recognising Shapes
We normally recognise objects using our senses of sight, sound, taste and
feel, whereas of course our basic computer can only obtain information
through the keyboard. Whilst it is possible to produce sensors w'hich can be
interfaced with your machine to give it another view of the outside world,
constructing these requires a reasonable amount of electronic and
mechanical knowledge and skill. We will make do instead with a simulation
of the action of a light sensor to illustrate how shapes can be recognised.
Let us think for a start about three simple shapes — a vertical line, a
square, and a right-angled triangle.
We can recognise these shapes by looking at the pattern they make on an
imaginary grid and deciding whether or not there is a point set at each X
and Y coordinate.
In the case of a line only the first X coordinate is used, but all of the Y
coordinates. A square is a little more complicated, as all the X
coordinates on Y rows 1 and 8 are set, and from Y rows 2 to 7 only the first
and last X points are set. Finally, a triangle is even more complicated, as
the slope is produced by incrementing the X axis each time
Table 8.1 Decimal Values of Shapes Described in Binary Form
Y row
line
square
triang
1
1
255
1
2
1
129
3
3
1
129
5
4
1
129
9
5
1
129
17
6
1
129
33
7
1
129
65
8
1
255
255
One obvious way to describe these particular figures would be to
represent each point by a single bit and to produce a decimal value for each
row, in the same way as we did before when we were looking at expert
systems (see Table 8.1). In fact this type of approach is used to produce the
characters which you see on your screen display, the formats for which are
105
Artificial Intelligence on the Commodore 64
stored in memory in just this form. For example Figure 8.1 shows how the
letter ‘A’ is built up.
There are now machines available (Optical Character Readers) w hich can
reverse this process. They actually ‘read’ a printed page by scanning the
paper in a grid pattern and measuring whether or not light is reflected at
particular coordinates.
Figure 8.1 Forming the Fetter ‘A'
What they actually take in will be a pattern of ‘yes' and ‘no' for each
coordinate, and of course this must then be decoded and compared with the
patterns for known shapes. The most obvious way to make this comparison
would be to consider every point in turn as a binary digit and then to
convert each row back to a decimal value which could be compared with a
table of known values. However this has the disadvantage that we must
actually check every individual point on the grid (64 points).
A branching short cut
A quicker approach relies on the fact that each character can actually be
detected by looking at only a much smaller number of critical features of
the pattern. For example. Figure 8.2 gives a decision tree which will find all
106
Chapter 8 Recognising Shapes
107
Figure 8.2a Decision Tree for Alphabet
Chapter 8 Recognising Shapes
the capital letters of the alphabet using only 12 points (see Figure 8.3), and
it is not even necessary to check all 12 in any particular case. If you follow
each of the routes, you will see that the maximum number of steps to be
X
1 2 3 4 5
X
X
X
X
X
X
X
X
X
l .
X
X
X
Figure 8.3 Points I sed in Decision Tree
followed is seven, and that most letters are found in less than five steps
(Table 8.2). This must obviously be quicker than comparing all 64 points!
Table 8.2 Numbers of Steps Required for Recognition of Each Character
3 steps I, D
4 steps - L, J, C, G, O. W
5 steps - S, A, Q, R, T, F. U, space
6 steps - P. V, Y, H
7 steps - B, M, N, E, K, X, Z
109
Artificial Intelligence on the Commodore 64
To demonstrate how this approach works, we will simulate the action of
the scanning head by producing a grid on the screen, on which you can
construct characters.
The text screen start address 1024 and colour RAM offset 54272 are
defined as variables, TS and CO respectively, as they are used frequently.
The screen is cleared and a dark area 6X8 blocks is set up in the top
lefthand corner. A lighter-coloured 5X7 grid is then superimposed on this
to mark the actual working area (of course there must be a margin around
the edge so that characters do not merge).
10 COS UP 10000
10000 TS-1024:CO-54272
12000 PRINT "CCLR3"
12010 FOR H~1 TO 10
12029 PRINT
12030 NEXT N
12000 FOR X“0 TO €
13010 FOR Y=0 TO 8
13020 POKE TS+C0+X+< YY40 >,. 11
12030 POKE TS+X+< Y:fc40 X- 224
13040 NEXT Y,X
13050 FOR X*1 TO 5
13060 FOR Y=1 TO 7
13070 POKE TS+CO+X+C Y*40 1
13080 NEXT Y,X
12090 X-1•Y-1
1210O RETURN
A flashing cursor is now produced to show your position. CP is the current
position on the text screen, TS + offset, the current colour of which is saved
as CC by PEEKing the equivalent position in the colour RAM. A different
colour CC + 4 is then POKEd into place and the original colour (CC)
POKEd back, so that there is no lasting effect.
20 GET R$
20 CP»TS+X+(YY40>:CC^PEEKXCP+CO > : POKE CP
+CQ, CC+4 • POKE CP+CO,. CC
40 IF fi$~"" THEN 20
The X and Y coordinates are updated according to the movement of the
cursor keys, and if the spacebar is pressed the colour of the current position
is set to black (0). If you make a mistake, the left arrow erases the current
position by resetting the colour to 1, or CLR jumps to the set-up routine
110
Chapter 8 Recognising Shapes
and erases all the current grid. Pressing RETURN leads to the decoding
routine, or else the program loops back to the keycheck.
50 IF R*="[RIGHT CURSOR]" THEN X=X+1
SO IF fl$*"CLEFT CURSOR]" THEN >/=X-l
70 IF fit*"CDOWN CURSOR]" THEN Y=Y+1
80 IF A*="CUP CURSOR]" THEN Y«Y-1
90 IF fi$=" " THEN POKE TS+CO+X-KY#40>
, 0
100 IF fl$a"[<--]" THEN POKE TS+CO+X-KY*40
>, 1
110 IF ft*="CCLR]" THEN GOSUB 13000
120 IF ASCXA$ >=13 THEN 2000
170 GOTO 20
Limits must be set to prevent the cursor wandering off the 5 X 7 grid area.
130 IF X<1 THEN X=1
140 IF X>5 THEN X=5
150 IF Y<1 THEN Y~1
160 IF Y>7 THEN Y«7
The decision tree is held in a series of linked arrays where NB isthe number
of branches, LE$(n) holds the names of the letters, Cl(n) the X coordinate
to be checked next, C2(n) the Y coordinate to be checked next, N(n) the
next element to use iftheansweris‘no’,and Y(n)thenextelementtouseifthe
answer is ‘yes’.
11000 NB~53
11010 DIM LEt( NB >,C1 < NB >, C2< NB >, N( NB >, Y<
NB >
11020 FOR N=1 TO NB
11030 READ LE$< N >, Cl< N >, C2C N >, N< N >, Y< N >
11040 NEXT N
The best way to enter the DATA is probably as 53 separate lines (one for
each branch point), as this makes it easy to enter and to edit out any
mistakes.
14010 DATft /l,1,2/19
14020 DATA ,1,5,2,10
140.30 DATA ,3,2, 4,9
14040 DATA ,5,1,5,8
14050 DATA ,3,1,6.7
111
Artificial Intelligence on the Commodore 64
14060 DflTfi 11 11 ,, ,,
14970 DATA "5",,,,
14080 DATA ".T",,,,
14090 DATA " I",, .•,
14100 DATA .5,4. 11.-14
14110 DATA ,5,5,12,13
14120 DATA "C",,,,
14130 DATA "G",,,,
14140 DATA ,5,7,18,15
14150 DATA ,2,4,17,16
14160 DATA "A",,,,
14170 DATA "0",,,,
14180 DATA "0",,,,
14190 DATA ,5,1,20,29
14200 DATA ,5,4,21,28
14210 DATA ,5,3,27,22
14220 DATA ,5,7,23,26
14230 DATA ,5,5,24,25
14240 DATA "P",,,,
14250 DATA "8",,,,
14260 DATA "R",,,,
14270 DATA "L",,,,
14280 DATA "D",,,,
14290 DATA ,5,7,45,30
14208 DATA ,2,6,31,44
14310 DATA ,5,3,32,39
14320 DATA ,1,5,33,36
14330 DATA ,3,1,34,35
14340 DATA "X",,,,
14350 DATA "2",,,,
14360 DAT A ,'4,2, 38,37
14370 DATA "K",,,,
14280 DATA "E",,,,
14390 DATA ,2,4,40,43
14400 -DATA ,4,2,42,41
14410 DATA "M",,,,
14420 DATA "H",,,,
14430 DATA "H",,,,
14440 DATA "W",,,,
14450 DATA ,3,1,46,51
14460 DATA ,1,5,47,50
14470 DATA ,2,4,48,49
14480 DATA "Y",,,,
14490 DATA "V",,,,
112
Chapter H Recognising Shapes
14500 DRTR "tJ",,,,
14510 DRTR ,1,5,52,53
14520 DRTR
14520 DRTR "F",,,,
If you are more confident (or are trying to save space) then all the DATA
can be condensed on to eight rather unreadable lines which are OK for
those who are good at counting commas, but very difficult to edit.
14010 DRTR ,'1,1,2,19, ,1,5,3,10,,3,2,4,9,
,5,1,5,8,,3,1,6,7," ",,,,,"S",,,,
14080 DRTR ".J",,,,,"I",,,,,,5,4,11,14, ,5
,5, 12, 12, "C",, ,,, "G", , . ., ,5.7, IQ, 1*=:
14158 DRTR ,2,4,17,16, "fl",,,,, "Q 1 ', ~, "0
",,,,,, 5, 1,20,29, ,5,4,21,28, ,5,3,27,22
14220 DRTR ,5,7,23,26,,5,5,24,25,"P",,,,
"DU , up H H i ii M p. II
.» c* .**>>> r. ,i ,i _» j l j, j i , L* ,• * i ♦
14290 DRTR ,5,7, 45,20,, 2, 6, 31 .. 44,, 5,3,32
,29,,1,5,33,36,,2,1,34;35,"X"
14350 DRTR "Z",,,,,,4,2,28,37,"K",,,,,"E
",,,,,,2,4,40,43,,4,2,42,41,"M",,,,
14420 DRTR "N",,,,,"H",,,,,"W",,,,,,3,1,
46,51,,1,5,47,50,,2,4,46,49,"V",,,,
14490 DRTR "V" ,,,*,, "U",,,,,, 1,5,52,53, "T
n Hern
> > > > j r s s *
To check the design produced against the patterns available (see Flowchart
8.1), the array pointer AP is first set to 1 so that the search is started from
the beginning. X and Y coordinates are read from the Cl (AP)and C2(AP)
elements pointed to, and the last position LP pointer set equal to the
current array pointer AP.
The point colour PC at these coordinates is determined by PEEK(TS4-
CO+X+(Y*40)) AND 15. If this is zero than the point has beensetand the
‘yes’ pointer Y(AP) must be followed. If any other value is found then the
‘no 1 pointer N(AP) is followed. In either case a check is made to see whether
the element pointed to contains a zero (indicating the ultimate end of a
branch), which shows that a character has been found. If so, the
appropriate letter LE$(LP) is printed, and the display is held until a key is
pressed, when a new cycle is initiated. As long as a higher value than zero is
found then this must be another branch point and so the program loops
back to 2010 and picks up the new values of Cl(AP) and C2(AP).
To allow you to see which points have been checked, these are set to
different colours as they are found. ‘Yes’ and ‘no’ branches can be
distinguished as tested points which were not set, POO. and will now belight
113
Artificial Intelligence on the Commodore 64
Flowchart 8.1 Character Recognition
green, 3, whilst points which were set will be red (3+1). Any points which
were set but not tested will remain black.
2000 HP“1
2010 X*C 1C flp > : Y*C2< flP > '• LP--RP
2020 PC^PEEKCTS+CQ+X+<Y#40>> AND 15
2030 IF PC-0 THEN RP--Y< flP > ■ GOTO 2050
2040 flP«N<RP >
2050 IF-RP-0 THEN 2070
2060 POKE TS+CO+X+C Y*40 >, 3 +< PC-0 > : GOTO 2
010
2070 PRINT LE$<LP>;
2080 GET fl$-IF RT- ,,M THEN 2080
2090 G0SUB 12000 GOTO 20
114
Chapter 8 Recognising Shapes
If you want to see which part of the tree was actually followed, then add
these modifications which will print out the sequence. The grid is moved
down the screen by adding an offset of 481 to SS and a blanking string BLS
defined which is used for partial screen clearance.
10000 SS=1024+481
10005
2005 PRINTTHOMEU"; " flP H ’PRINT
2055 PRINT FiP
2070 PRINT * PRINT " l# ; LE*< LP )• PRINT
2075 PRINT“PRESS fi KEY TO CONTINUE"
2085 PR I NT THOME FOR N*1 TO 10 ’ PRINT BL$ : HE
XT N
The disadvantage of this more rapid method, of only checking critical
points, is that it will make a mistaken match if it encounters a shape that is
not on the tree, whereas if all points are checked then no match will be
found in such a case.
Early Optical Character Readers would only accept a single particular
typeface, but the latest machines not only accept different styles of type, but
actually learn the recognition rules for themselves by means of a built-in
expert system. You teach these by showing them a few pages of text and
then entering these same characters via the keyboard. However we feel that
it will still be a long time before anyone can produce a machine that can
read OUR handwriting!
115
CHAPTER 9
An Intelligent Teacher
Another place where artificial intelligence can be particularly useful is in
teaching programs. It is all very well having a program which tests a
student's knowledge at random, but this is not how a real human teacher
works. As well as asking the questions, he keeps an eyeon the progress ofthe
students, increases the difficulty of the questions as experience increases,
and tests them more rigorously on the types of problems with which they are
having difficulties. For example, if a child takes a test involving addition,
subtraction, multiplication, and division, but only gets the division-type
questions wrong, then it follows that the child should be given more
division questions in the future to provide more practice.
Let’s have a look at how we can introduce these ‘human’ qualities into a
teaching program.
Questions and answers
We need to create random numbers to be used in the first question,
which we will make addition. Using INT(RND( I)* 10) will give numbers
between 0 and 9.
20 RHIX 1 )*10)
30 INK FIND*: 1 TUO >
The computer adds these together and then goes on to an input and
checking subroutine at 1000.
40 ' GOSUE’ 1000
First, the routine must print the question and input your answer IP%.
1000 PR I NT Wi: " •+ ", B'i . " »«.
1010 INPUT IP'S
Your answer must then be checked. If the program answer C% is the same
as your answer, then CORRECT is printed and the routine returns to line
40. Otherwise WRONG is printed followed by the correct answer.
117
Artificial Intelligence on the Commodore 64
1020 IF C5S-IP5S THEN PRINT "CORRECT" : RETU
RN
1030 PRINT "WRONG, THE CORRECT ANSWER WA
C “ • £•/
1040 RETURN
The other three subjects (subtraction, multiplication, and division) can be
easily dealt with in the same way if we replace the ‘ + 'sign in line 1000 by a
sign string SG$, which we can set to the appropriate character at the time.
As 1NT(RND(1)*10) is common to all the calculations, we might as well
define this as a function RD.
15 OEF FNRtX X >*RND< 1 >* 10
20 fl?s*FNRD< AD*; >
20 E'*'."FNR['T ADV. >
40 sof="+" = c*-;=a'-;+b*; •• gosue i 000
50 flV.«FNRD< SU’O
60 B5i=FNRD< SU*; >
70 sgc= c*;~a*;~b*; ; gosue 1000
30 fi*;=FNRD< mu* >
30 E*;~FNRD< MU’;>
100 SG$“"*" : C>.~ A*#BX ! GOSUE 1000
lie AV.-FNRD 1 'Di>
120 B**FNRD<DIX>
130 SG$= ; C*-^A*;/B*; « GOSUE 1000
1000 PR I NT A*-;SGf; BV .; " -•";
Finally we jump back to line 20 to ask more questions.
140 GOTO 20
Dividing by zero!
As it stands, the program can crash if B% happens to be zero when a
division is selected. This can be simply fixed by always adding one on to B%
in this case:
120 B*«FNRD<D150+1
Deleting decimals
We are using integer variables to keep us to round numbers, but of course a
118
Chapter 9 An Intelligent Teacher
division may still produce a fractional answer, which you cannot enter
correctly: IP% will be rounded down, eg:
3/2 = 1.5
The program will accept 1, 1.5, 1.9 or any other number between I and
1.999 ... as correct.
To avoid producing decimals, A% needs to be a multiple of B%. To
achieve this we calculate B% first and make A% equal to B% multiplied by
a random number between 0 and 10.
110 E'"i“FNRD( DI"; )+l
120 fl*;= I NT< FNRD< DI X > nBX
Keeping a score
Now that we have the test itself working, we need to consider how to keep a
score. The simplest thing is to increment a tries variable TR% each time the
subroutine at 1000 is used, and to increment a score variable SC% each
time a correct answer is obtained.
1010 INPUT IP";• TR‘;'~TR':'+1
1020 IF CX^IPX THEN : PRINT "CORRECT" •• SC-M-
SC*:+1 = GOTO 1040
1040 PRINT "YOUR SCORE IS ";SC*; ; Jpy ■.
RETURN
If you prefer the score as a percentage then amend line 1040 as follows:
1040 PRINT "YOU HAVE HAD "; INK < SC^TP* )
* 100 >; "X CORRECT" • RETURN
How many questions?
As it stands the program will ask one question of each type in sequence, ad
infinitum. We can limit the number by defining the number of questions
NQ% as a variable.
10 NQX-22
Each time a question is asked, NQ% is decreased by 1, and when NQ%=0
the test ends (after eight questions of each type have been answered).
Artificial Intelligence on the Commodore 64
150 IF NQ*>0 THEN 20
160 END
1010 INPUT IP5S«TR5£*TR5£+1 ! NQ'4
1
Shifting the emphasis
If we are going to bias the questions in favour of areas of difficulty, then we
need to keep a record of performance in each individual area. We therefore
need separate variables for each type of question (AD%for addition. SU%
for subtraction. MU% for multiplication, and DI% for division). These
variables are defined in terms of one eighth of the total number of
questions to be asked NQ%.
10 NG'v
hD*-;
■2: flDV.*NQV8 : SU*;=fiD-; : MU^FlD* •• Di’; ;
Now if the correct answer C% is the same as your answer IP% then an
increment variable IN% is set to -1. CORRECT is printed, and the routine
returns. Otherwise 1N% is set to 1. and WRONG is printed followed by the
correct answer.
1020 IF C5S-IP5S THEN IN5S»-1 PRINT "CORREC
T " ■ PETI IR.N
1020 IN^.* 1 - PRINT "WRONG.- THE CORRECT FINS
WER WFlS "iC's.
104O RETURN
1N% is added to the appropriate individual number of questions variable
AD%, SU%, MU% or Dl% on returning, producing an increase in this
value if the answer was wrong, or a decrease if the answer was right.
40 S
i!
NV.
70 S
;G$-"
N %
100
SG$'=
in:-;
130
SG*=
INV.
= C'i- Fft+E*-; : GOSUB 1000 : 1
• c*;“R*;-b*'. : gosub 1 000 : su:-;~su ’;+1
»: « gosub i 000 : riu*-;=nu*;+
•• ; gosub 1000 : DI *;=D 1 *;+
Now we add a check to see whether all the questions of a particular type
have not been correctly answered (eg AD%>0, see Flowchart 9.1) If all
questions of one type have been correctly answered, then no more of this
type will be asked as the line is jumped over. If the appropriate number of
120
Chapter 9 An Intelligent Teacher
Flowchart 9.1 Intelligent Teacher
each type has been answered correctly (AD%=0. SU%=0, MU%=0
DI%=0) then the program ends.
40 IF RDJS>0 THEN SG*=" + ";CJS»A5i+Bfc : GOSUB
1000-flDV.aflD5£+IN5S
70 IF $U':>0 THEN SG$”"-" : GOSUB
1000 ; SU"'.-3U';+1N*'.
100 IF MU"4>0 THEN SG*="*" = C*=Fft*B* • GOSI'
B 1000 ■ Mll*i=MIJ*i+1H’:
130 IF DI*:>0 THEN SG$='V" = GOSU
B 1000 = DI5S«DI5J+INJ£
140 if fid *;-0 find suJi*© and rm -0 find di*-;
=0 THEN 160
Notice that you are no longer asked questions about areas in which you
121
Artificial Intelligence on the Commodore 64
have correctly answered four questions without making any errors. If you
make a mistake then AD%, etc, will be increased and so you will have to
answer more than four correctly before AD reaches zero.
Degrees of difficulty
How about making the questions easier or harder according to how well
you are doing (ie the values of AD%, SU%, MU%, and DI%)? So far the
current values for A% and B% have always been between 0 and 9 as they
were produced by RND(1)*10, but we now need to bias the numbers
produced for the questions towards higher values, if you are correct, and
lower values, if you are incorrect. At the same time, we must ensure that
you do not produce negative values if your performance is abysmal.
The ‘worst case' will be if you get all the questions right in three of the
groups, and all the questions wrong in the last group. In this case only four
questions will be asked on the first three groups, leaving 32—(3*4)=20
questions to be asked on the last group. In addition we must remember that
X (eg AD%) starts at a value of 4, so that the maximum value of X which
could be obtained is 20+4=24.
We therefore set up a weighting variable WT%, which is calculated by
subtracting three times the number of questions to be asked in each group
(3* AD%) from the total number of questions NQ%and adding back on the
number of questions in a group AD% at the start.
WT%= NQ%-(3* A D%)+A D%
This is more simply expressed as:
WT%= N Q%-( 2 * A D%)
10 NQ‘i“32 * RD’^NQ VS = SUVRD* : flUVRC* : DIV
RD*= UTVNQV< 2#RD?S >
We now replace the fixed value of ten by the difference betwen WT% and
X.
15 DEF FHRCK X >«RND< 1 >*< UTW
To begin with, WT%=24 and X=4 so numbers between 0 and 19 will be
selected. If a correct answer is given, then X will be reduced to 3 and
numbers between 0 and 20 will be chosen. After four correct answers, X will
not change (for this type of question) as it will have reached zero and the
line will be skipped. The last values will therefore be between 0 and 22.
122
Chapter 9 An Intelligent Teacher
On the other hand if the first answer is incorrect then X will increase by 1
and the range of numbers produced reduced by 1 (0—18). In the‘worst case’
X will be increased twenty times to 24 and (WT%-X) will fall to zero for
both A% and B% (so you should be able to solve that particular problem!).
123
CHAPTER 10
Putting It All Together
In the previous chapters we have dealt, from first principles, with various
aspects of Artificial Intelligence. In this final chapter we have linked
together many of these individual ideas in a single complete program.
The original ‘intelligent’ program was the famous ‘ELIZA’, which was a
pseudo-psychiatrist program written to send up a particular style of
psychiatric therapy. We have resisted the temptation to follow this lead and
have opted instead to produce a replacement for the average computer
salesman. This program combines some ideas on the processing of natural
language and on expert systems, to produce a result which should both
understand your requests and make suggestions which take into account
both your requirements and a number of hard commercial facts.
Enough words and values have already been included to make the
program interesting, but you can easily customise it by adding your own
ideas to the DATA. (We take no responsibility for the values included so
far, which are for demonstration purposes only, or for the views on particu¬
lar machines expressed by the program!) The program itself is quite
complex but it follows the methods described earlier in the book and
the functions of the various line variables and arrays are given in
Table 10.1
Making conversation
The format of the program is that you are asked for your views on each of a
number of possible features in turn (the exact wording of the question
being selected at random from a selection of phrases). Note that the key
word or phrase is inserted into the sentence where necessary, and that the
correct conjugation is applied.
Your input is examined in detail for keywords, and a rule array updated
according to your requests. (If you want actually to watch the rule array
being updated then delete line 5490.) Many of the keywords are truncated
so that one check can be made for a number of similar words, and a test is
included to see if the matching string is at the start of a word.
The simplest answer is ‘YES’ or ‘NO’, which adds or subtracts 1 from the
rule for that feature. If you mention the name of the feature (eg
‘GRAPHICS’) then a further 1 is added to the rule. In addition, using a
125
Artificial Intelligence on the Commodore 64
Table 10.1 Main Variables in ’Salesman’
SIMPLE VARIABLES
IS
11$
12 $
IP
QP
Q
R
BB
PH
PH$
M
OF
OM
LD
FS
NP
51
52
RU
OB
AJ
AV
LI
DL
NJ
NV
HM
CO
FE
CT
CS
EX
HI
LO
TC
TP
INSTR start
target string
search string
INSTR pointer
no. of question sentences
no. of questions
no. of rules
bank balance
phrase number
phrase words
match marker
object flag
object match
like/dislike
rest of sentence pointer
negative pointer
AND match pointer
BUT match pointer
rule update marker
no. of objects
no. of adjectives
no. of adverbs
no. of likes
no. of dislikes
no. of negative adjectives
no. of negative adverbs
no. of cheap/expensive
no. of computers
no. of features
no. of cost ratings
no. of cost suggestions
no. of excuses
no. of high price suggestions
no. of low price suggestions
total cost
total profit
126
Chapter 10 Putting It All Together
ARRAYS
OB$(OB)
objects
AJ$(AJ)
adjectives
NJ$(NJ)
negative addresses
AV$(AV)
adverbs
NV$(NV)
negative adverbs
LI$(LI)
likes
DL$(DL)
dislikes
Q$(Q)
question objects
QP$(QP)
question sentences
CR(Q)
cost rate
PR(Q)
profit rate
IC(Q)
total cost
IP(Q)
total profit
HM$(HM)
cheap/expensive
R(R)
rules
CO$(FE)
computer names
FE(CO,FE)
feature names
C(CT)
cost ratings
CS$(CS)
cost suggestions
EX$(EX)
excuses
HI$(HI)
high messages
LO$(LO)
low messages
‘positive’ adjective or adverb adds to the rule, whilst a ‘negative’ adjective or
adverb subtracts from the rule. Separating the words into different classes
allows you to make more than one change to the rule at the same time.
Thus:
YES adds one
YES BASIC adds two
YES BASIC NECESSARY adds three
YES GOOD BASICNECESSARY adds four
Whilst:
NO subtracts one
NO MEMORY subtracts two
127
Artificial Intelligence on the Commodore 64
Furthermore, verbs are grouped as Mikes’ and ‘dislikes’, the last of which
reverses the action of the rest of the words.
Thus:
I DETEST MACRODRIVES subtracts one
Both ‘NO-’ and ‘N’T’ are recognised, and most double negatives are
interpreted correctly.
Thus:
I DON’T LIKE SOUND subtracts two
I DON’T DISLIKE SOUND adds one
If anything appears at the start of a sentence and is followed by a comma, it
is usually cut off and effectively ignored.
Thus:
NO, I DON’T WANT GOOD SOUND subtracts three
The exception is when ‘AND’ or‘BUT are included, when both parts of the
sentence are acted on independently.
Thus if the question is:
DO YOU WANT GRAPHICS?
and the answer is:
NO, BUT I WANT GOOD SOUND
then one is subtracted from the graphics rule and two is added to the sound
rule.
If the program does not find any keywords in the input, it politely asks
you to try again:
PARDON, EXCUSE ME BUT...
The program can only cope with one feature at a time, so if you try to ask
for‘SOUND and GRAPHICS’ at the same time, for example, you will get
a request for a repeat of the question.
HANG ON — ONE THING AT A TIME
However, it is possible to make comments about single features that you
are not being asked about at the time, and these entries will still update the
rules (as in the ‘BUT’ example above).
128
Chapter 10 Putting It All Together
129
Chapter 10 Putting It All Together
( 2 )
13 !
Artificial Intelligence on the Commodore 64
132
Chapter 10 Putting It AH Together
( 4 )
133
Artificial Intelligence on the Commodore 64
Decisions
In addition to the rule array, there are two other arrays which are linked to
this. The first is the ‘cost array’, which gives an indication of the cost of this
particular option, and the second is the ‘profit array’ which indicates to the
salesman how much effort it is worth putting into selling this feature. The
values for these last two arrays are produced by multiplying the content of
the corresponding rule array element by factors entered originally as
DATA in lines 10100, etc, where the format is:
(phrase describing feature, cost, profit)
After each input, the salesman considers the consequences of your
requests. First of all he looks to see if the sum total of the cost of all your
requirements exceeds your bank balance. If so, he prints out one of a series
of caustic comments on your credit-worthiness like:
THIS SPECIFICATION SEEMS TO BE EXCEEDING YOUR
CREDIT LIMIT
He also looks at how much profit he is likely to make on the sale so far: if
this drops too low, he will start to lose interest and come up with comments
like:
I HAVE AN URGENT APPOINTMENT
or
WE CLOSE IN FIVE MINUTES
At the same time, he will be more helpful with regard to which of the available
computers will fit your requirements, drawing up a short-list by comparing
the rating given originally to this feature in the description of each
computer with the value you put on it. The format for the descriptions is:
(name, value of feature 1, value of feature 2, value of feature 3, etc)
The highest rated machine will always be picked out first but, if possible, at
least three machines (possibly with lower ratings) will be selected and the
final choice is made from these. Either the highest or lowest cost computer
(at random) will be selected for mention, for example:
IF YOU WANT A REAL ROLLS-ROYCE THEN JUST LOOK AT
THE...
134
Chapter 10 Putting It All Together
and
IF YOU ARE IN THE BUDGET MARKET THEN WHAT ABOUT
THE...
If only one machine fits the bill, the program will come up with:
YOUR ONLY OPTION IS THE...
Salesman
10 GOSUB 9300
20 GOTO 200
100 FOR IS=FT TO LENCIUO
110 IF MID*< 11$, IS,LEW 12$ >>=12$ THEN IP
=IS=RETURN
120 NEXT IS
130 IP-0’RETURN
200 PH=RND<< 1 QP+1 >>■ PH*«QP*<PH>
210 11 *»PH* : '12*= " / " ; FT= 1 : GOSUB 100’SP-IP
220 IF SP=0 THEN 300
230 IF LEFT$CQ*<Q), 1 >*"6" THEN PH$=LEFT$
< PH$,SP~1 >+"RRE"+RIGHT*< PH$, LEN< PH$ >-SP >
300 IF SP=0 THEN 4O0
310 IF LEFT$<0$<G>, 1 THEN PH$=LEFT$
< PH$, SP-1 >+ " IS" +RIGHT*< F'H$, LEN< PH$ >-SP >
400 11 $=PH$ : I2$="*" : FT 3 1 ! GOSUB 100
410 IF SP=0 THEN 440
420 PH*»LEFT*< PH$,SP-1)+" "+RIGHT*<Q*<Q>
,LENCQ$(Q > >-1>+RIGHT$<PH*,LEN<PH*>~SP)
430 GOTO 500
440 PH*«PH*+" "+RIGHT*(Q*<Q>.• LENCG$<0>>-
1 >
450 PRINT»PRINT
500 PRINT PH*;"?"
600 PRINT
700 IN*-" "
710 GET I*:PRINT "<CLEFT CURSOR]";
720 IF I*="" THEN 710
730 IF I*-CHR*<13 > THEN 300
740 IN*=IN*+I*
750 PRINT 1$;
760 GOTO 710
135
Artificial Intelligence on the Commodore 64
800 LD= 1 = 0F=-1 = FS= 1 : NP=0 ; R 1.1=0' M=0 : OM*0 : S
1=0:S2=0
900 11$=INT : 12T=" ! FT=1 ; GOSUB 100<CM*IP
910 IF CM=0 THEN 1600
1000 11 $= I N« ; 12$=" AND " : FT= 1 = GOSUB 100 ■■ S1
*IP
1010 I2**IN*«I2$*"BUT" FT«1= GOSUB 100 ; S2
= IP
1200 IF Sl+S2=0 THEN 1500
1300 IF LEFT$< IN*,3><>" NO" THEN 1480
1310 R< Q >~PX Q >-1 : 1 C< Q >= I C( Q >-CR< Q )= I P< Q >
«ip<q>-pR':q> = G 0 To 1500
1400 R< Q >*R< Q >+1«I C< 0 )-1 C< Q >+CR< Q > = I.P< Q >
-IP< Q )+PR< Q >
1500 IN$=RIGHT*<INT,LEN<INT>-CM>
1600 11 *= IN$ I2$="YES" : FT=FS ; GOSUB 100=S
P=IP
1700 IF SP>0 THEN RU*RU+1 LD--1 = M*1 • FS*SP
+1 : GOTO 1600
1800 11*=INT:12T^"NO"sFT“FS> GOSUB 100 = SP
= IP
I960 IF SP>0 THEN LP=-1*M*1 : FS=SP+1=NP=N
P+1 : GOTO 1800
2000 11*=IN* * 12**"N'T"* FT*FS‘GOSUB 100 = S
P* IP
2100 IF SP>0 THEN LD--1 ; M^l : FS=SP+1 : NP~N
P+1 : GOTO 2000
2200 IF NP”0 THEN 2300
2210 IF I NT < NP/2 >~NP--'2 THEN RU*RU+1=LD=1
: GOTO 2300
2250. RU*RU-1 ; LD=-1
2300 FOR N=0 TO LI
2400 11$“INT : 12T=L1*<N > * FT*1'GOSUB 100 = S
P=IP
2410 IF SP~0 THEN 2500
2420 IF MID*<IN*,SP-1, 1 )»" " THEN LD*LD#
1 *M*i
2500 NEXT N
2600 FOR N“0 TO DL
2700 11$-1NT=12**DL*<N > : FT=1=GOSUB 100=S
P*IP
2710 IF SP>0 THEN IF MID*<IN*,SP-1,1>*"
" THEN LD~LDfc-l : M~1
2800 NEXT N
136
Chapter 10 Putting It AH Together
2900 FOR N-0 TO OB
3800 11$”IN$ = 12$-OB*<N >'• FT“ 1 : GOSUB 1OO = S
P~IP
3010 IF SP>0 THEN IF MIDSKIN*,SP-1 .• 1
" THEN RU~RU+LD = OF*N = M*1 ; OM*OM+1
3100 NEXT N
3200 FOR N-0 TO FlV
3300 11**IN*:I2**AV*<N > ! FT~1•GOSUB 100 = S
P=IP
3310 IF SP~0 THEN 3600
3400 IF MID$< IN*.SP-1,1 ><>" " THEN 3600
3500 RIJ-RU+LD ; M=1
3600 NEXT N
3700 FOR N”0 TO NV
3800 11 *=> I N* ■■ 12$~NV$( N) ; FT~1 ; GOSUB 100 = S
P^IP
3810 IF SP“0 THEN 4100
3908 IF MID*<IN*,SP-1,1X>" " THEN 4100
4000 LD~LD'*:-1 • RU-RIJ+LD = M* 1
4100 NEXT N
4200 FOR N-0 TO fij
4300 11 $-1 N$ I2*®AJ*< N > ; FT~ 1 • GOSUB 100 = S
P-IP
4310 IF SP-0 THEN 4680
4400 IF MID$<INT,SP-1,1><>" " THEN 4608
4500 RIJ-RU+LD • M~ 1
4600 NEXT N
4700 FOR N-0 TO NJ
4300 11 1N$ = I2*®NJ*< N > * FT-1 GOSUB 100 '• S
P=IP
4210 IF SP-0 THEN 5100
4908 IF MID*C IN*, SP-1, 1 X >" "THEN 5180
5000 LD-LDT-1: RIJ-RU+LD = M”1
5100 NEXT N
5110 FOR N==0 TO HM
5120 11$~I m •• 12**HM*< N > : FT=1 : GOSUB 180 : S
P=IP
5130 IF SP=0 THEN 5190
5140 IF MID*< I NT, SP-1 ><>" " THEN 5190
5150 XX=N : IF XX<2 THEN PRINT"CHEAP AND N
ASTY" GOTO 5190
5160 IF XX>~2 THEN PRINT"RATHER EXPENSIV
E"
5178 NEXT N
137
Artificial Intelligence on the Commodore 64
5180 PRINT
5200 IF M<1 THEN PRINT "PARDON, PLEASE E
MOUSE ME BUT" : GOTO 280
530O IF 0I1>1 THEN PRINT "HANG ON ~ ONE T
HING AT A TIME" GOTO 200
5400 IF OF--1 THEN 5440
5410 R< OF >~R< OF >+RU = I C< OF I CC OF >+C CPC OF
:>* RU >
5420 I P< OF )=■ I PC OF >+C PRC OF )*R(J >
5430 GOTO 5490
5440 RC Q >~RC Q >+RU ■ ICC 6 >-1CC Q >+C CRC Q D+iRU )
= I PC Q > I PC Q >+C PRC Q >:t:RU >
5490 GOTO590O
5500 PRINT'TCLRH"
5600 FOR N-0 TO R-PRINT RCN); 'NEXT CL PR I
NT
5700 FOR N~0 TO R PRINT ICCN=NEXT N = PR
I NT
5800 FOR N-0 TO R : PRINT I PC NX; NEXT N : PR
I NT
5900 FOR N“0 TO OB
6000 TOTC+1 CC N >
6180 TP-TP+IPCN >
6200 NEXT N
6300 IF TP<Q*5 THEN TX-RNDC0)*EX ; PRINT=P
PINT EX$C TX >
6400 IF TOBB THEN PT~RNDC 0 >*CS • PRINT • PR
INT CS$CPT>
6500 TC~0 ; TP~ 0
6700 FOR X~9 TO 0 STEP-1•PO$=""
6800 FOR N-0 TO CO
690O IF FECN.■ Q>-RCQ>>X THEN PO$=PO*+RIGH
T$C STR$C N X 1 > * M=N
7000 NEXT N
7100 IF PQ$^"" THEN NEXT X : GOTO 7200
7110 IF LENC PO$ X2 THEN NEXT X
7310 GOTO7900
7350 PRINT F'OS
7400 IF PO$^"" THEN 9200
7500 FOR N~1 TO LENCPO$>
7600 PRINT CO*C VALCMID$CPOf,N,1> > >
77O0 NEXT N
7800 PRINT
7900 TS”0 : BS"10
138
Chapter 10 Putting It All Together
8000 FOR CH~0 TO LEN<POt)-l
3100 NOVflL< MI P0$, CH+1', 1 ) >
3200 IF C< NO »~TS THEN TS~CC NO > : HI-NC
3300 IF C<NCX-BS THEN ES=C< NO ■ LO~NC
3400 NEXT CH
3410 IF HI~L0 THEN PRINT"YOUR ONLY OPT10
N IS THE" : PRINT C0$< HI> : GOTO 9200
3500 HI$=CG$<HI>•LO$“CO$<LO>
8600 SE-RNCK1>+1
3700 SL-RNDC 1 >*2
8800 IF SE“2 THEN 9100
3900 PR I NT HI $< SL >,,,, HI $
900© GOTO 9200
9100 PRINT L0$<SL ')>, , .• L0$
9200 Q-Q+l IF Q<20 THEN 200 ELSE END
9300 QP-5 •• Q-19•R-Q = OB=R•fiJ*8 : AV“5= LI“3 : D
L-2 = NJ~3 = NV~2 HM~3 = BB~ 108
9310 DIM OEfC OB >, flj$< AJ >, NJf( NJ >, AW flV >
, NV*< NV >, LI$< LI >, DL$< DL >, Q$( Q >
9320 DIM P.< R >, QP$< QP >, CR< Q ), PR< Q >, I C( 0 >,
IP< Q), HM$< HU >
9400 DATA BflSIC,GRAPHIC,SOUND,KEYBOARD,F
UNCTION,MEMORY,TAPE,MACRODRIVE,DISC
9410 DATA SOFTWARE,CARTRIDGE,JQYSTICK,AS
SEMBL,CENTRONICSRS232,EXPAND
9420 DATA NETWORK.16-BIT,MULTITASK,SERVI
CE
9500 DATA GOOD,EXCEL,SUPER,MAGNIF,FIRST,
FAST,EFFIC.ESSENT,LOT
9600 DATA BAD, RIJBBISH, POOR, SLOW, I NEFF IC,
FEW,WORS,LEAST,LESS
9700 DATA REAL,VERY,OFTEN,FREQ,NECESS,TR
U
9300 DATA NEVER,UNNECESS,INFREQ
9900 DATA WANT,LIKE,NEED,REQUIRE
1 0000 DATA HATE,DISLIKE,LOATHE,DETEST
10100 DATA &GQGD BASIC,5,2,©GRAPHICS,7,2
, LSOUND ,6,2, LA GOOD KEYBOARD, 4,2
10110 DATA ©FUNCTION KEYS,1,5,LA LARGE M
EMORY,3,6,LA TAPE INTERFACE,2,2
1 0120 DATA ©MACRODR IVES, 2,4, ©DISCS, 5,8,L
EXTENSIVE SOFTWARE,0,9
10130 DATA LA CARTRIDGE PORT, 1,6
102O0 DATA LA JOYSTICK PORT,1,7,LAN ASSE
139
Artificial Intelligence on the Commodore 64
MBLER,2,1 ,m CENTRONICS PORT,2,5
1O210 DATA >iRN RS232 PORT, 2..6.- &EXPANDABI
LTV,2,9,^NETWORKIHG,3,4
10220 DRTR &A 16-BIT CPU,1,7,^MULTITASKI
HG,5,5,&GGOD SERVICE,1,9
10300 DATA WOULD YOU LIKE,WHAT ABOUT,HOW
ABOUT,DO YOU WANT,DO YOU REQUIRE
10210 DATA •••-:♦: IMPORTANT
10320 DATA CHEAP,INEXPENSIVE
10338 DATA DEAR,EXPENSIVE
10400
FOR
N-0
TO
OB
READ
0B$<N >
NEXT
N
10500
FOR
N-0
TO
AJ
READ
AJfCN >
NEXT
N
10600
FOR
N~Q
TO
NJ
READ
NJ*<N >
NEXT
N
10700
FOR
N~0
TO
AV
READ
AV$(N >
NEXT
N
1 0800
FOR
N-0
TO
NV
READ
NVfCN >
NEXT
N
10900
FOR
N*0
TO
LI
READ
LlfC N >
NEXT
N
11000
FOR
N~0
TO
DL
READ
DLf< N >•
NEXT
H
1 1 100
>*NEXT
FOR
' N
N-0
TO
Q : F
?EflD (
l!f< N >, CF
>< H >, PR
11200
FOR
N=0
TO
QP ;
READ
QPf<N ) ;
NEXT
N
11210
FOR
N-0
TO
HM :
READ
HMf<N> :
NEXT
N
11300 PRINT"CCLR3" : Q~0
114O0 PRINT "IT IS MY PLEASURE TO WELCOM
E YOU TO THE MULTIMEGA MICROSTORE"
11410 PRINT
11509 PRINT"WE ARE UNDOUBTEDLY THE ULTIM
ATE SOURCE OF ALL COMPUTER PRODUCTS"
11505 PRINT
11510 PRINT"I SHALL HAVE PLEASURE IN HEL
PING YOU'SELECT YOUR NEW MACHINE"
11515 PRINT
116O0 PRINT"SO THAT I CAN WORK OUT THE B
EST COMPUTER"
11610 PRINT"FOR YOUR PARTICULAR NEEDS PE
RHAF'S"
11620 PRINT"YOU WOULD BE KIND ENOUGH TO
ANSWER A FEW QUESTIONS"
11650 PRINT
11700 PRINT PRINT"ARE YOU READY";
11800 CO~9 >FE=19 : CT~9 DIM CO$<FE >,FE<CO,
FE >, DF< CO, FE >, C< CT >
1190O DAT A .JCN PC: ,7,8,8,9,8,8,8,0,9, 9,7,
7,0,7,6,8,8,9,9,9
1 2000 DAT A KNACT SEPIOUS,6,7,6,8,8,8,8,0
140
Chapter 10 Putting It All Together
, 8, '3,3, 0,0,7,6,8,8, 9, 9, 7
12108 DATA CLEARSIN MT,9,9,9,7,7,8,8,9, 9
,6,7,7,0,7,6,7,9,9, 9, 1
1 2200 DATA FfCHRON ILLUSI ON, 8,7, 6,6,8, 3, 7
, 0 , 5 , 5 , 0 , 0 , 6 , 0 , 0 , 4 , 1 , 0 , 0 , 2
12300 DATA BANANA I IE,3,5,2,5,8,4,6,8,3,
«, 3,5,0,8,6, ?, 8, 0, O, 4
12400 DATA SI ELITE,3,8,8,7,7,8,8,0,7,2,
7, 4,0,0, 6, 0,0, 0,0,0
12500 DATA COLECTOVISI ON CABBAGE, 5, 5-, 5,5
,2, 5,5,5,5, 1,7,7,0,0, 6,5,0, 9,8,0
12600 DATA CANDY COLOURED COMPUTER,7,6,4
,2,0,2,7,0,4,9, 8,7,0,0,6,3,0, 0,0,6
12700 DATA COMANDEAR 64,2,8,9,7,7,6,5,8,
6 ,9,6,7,0,0,2,2,8,0,0,6
12300 DATA ATRIA'600GT,1,8,8,5,0,2,5,0,7
,7,7,7,0,0,6,6,0,8,0,5
12900 DATA 10,9,7,3,8,4,6,5,2,1
13000 FOR N-0 TO CO
13100 READ CO$<N>
13200 FOR M~0 TO FE
13308 READ FE(H,M >
13400 NEXT N,N
13500 FOR N*0 TO CT
13600 READ CXN >
13700 NEXT N
13800 GET A*=IF A$~"" THEN 1330O
13900 DATA I THINK YOU ARE GETTING OUT 0
F YOUR PRICE RANGE
13910 DATA THIS SPECIFICATION SEEMS TO B
E EXCEEDINGYOUR CREDIT LIMIT
13920 DATA I DON'T THINK THAT YOU CAN AF
FORD SUCH LUXURIES
14O00 DATA EXCUSE ME I CAN HEAR THE PHON
E RINGING,! HAVE AN URGENT APPOINTMENT
14010 DATA WE CLOSE IN FIVE MINUTES
14100 CS~2«EX~2«DIM CS*<CS) = DIM EX$<EX >
14200 FOR N=8 TO CS ; READ CS$(N > : NEXT N
14300 FOR N~0 TO EX=READ EX$<N>=NEXT N
14400 DATA IF YOU ARE IN THE BUDGET MARK
ET THEN WHAT ABOUT THE'
14410 DATA AN INEXPENSIVE CHOICE IS THE,
YOU GET GOOD VALUE FOR MONEY WITH THE
14500 DATA IF YOU WANT A FIRST-CLASS PRO
141
Artificial Intelligence on the Commodore 64
DUCT THEN YOU MUST TRY THE
14510 DATA FOR STATE OF THE ART TECH^OLO
GY YOU CAN'T BEAT THE
14520 DATA IF YOU WANT A ROLLS-ROYCE THE
N JUST LOOK AT THE
14609 HI-2 ; LO-2 : DIM HI« HI >, LO*( LO >
1470O FOR N*0 TO LO : READ LO$< N> : NEXT N
14800 FOR H-0 TO HI ; READ HIN> : NEXT N
14900 FRIHr'CCLRa 11 RETURN
Commentary
Lines 100-130: Contain an INSTR routine.
Lines 200 440: Pick the words to be used in the next question, and select the
correct conjugation.
Lines 500 800: Set up your INPUT and reset variables.
Lines 900 910: Check for a comma.
Lines 1000 1200: Check for ‘AND’ and ‘BUT’. If neither of these is present
the program jumps to line 1500.
Lines 1300-1310: Update the current rule negatively if‘AND’ or ‘BUT’ are
present and the first word is ‘NO’.
Line 1400: Updates the current rule positively if‘AND’ or‘BUT’are present
and the first word is not ‘NO’.
Line 1500: Deletes anything preceding a comma.
Line 1600-2100: Check for ‘YES’, ‘NO’ and ‘N’T’ and update the current
rule accordingly.
Line 2200: Checks for a double negative.
Lines 2300-2500: Check for ‘likes’.
Lines 2600 2800: Check for ‘dislikes’.
Lines 2900 5100: Similarly check for objects, adjectives and adverbs.
Lines 5110-5190: Check matches for high and low cost key words.
142
Chapter 10 Putting It All Together
Line 5200: Checks for no match and reports.
Line 5300: Checks for more than one object.
Lines 5400-5440: Update the current rule, or another rule, according to
whether or not the object matches the current question.
Line 5490: Jumps over the print-out of the rules.
Lines 5500-5800: Print out the rules.
Lines 5900-6200: Update the total cost and total profit values.
Line 6300: Prints an excuse if the profit seems too low.
Line 6400: Prints a warning if the spending is too high.
Line 6500: Zeros the total cost and profit values.
Line 6700-7120: Search for computers which match your requirements.
Line 7310: Jumps over the print-out of matching machines.
Lines 7350 -7800: Print out the matches.
Lines 7900-8400: Pick the highest and lowest priced machines which match
the specification.
Line 8140: Checks if only one machine was selected.
Lines 8500-9100: Print out the name of either the highest or lowest priced
machine.
Line 9200: Updates the feature to be checked and returns for another input.
Lines 9300-11300: Enter the information on features, keywords, costs and
profits.
Lines 11400 11700: Provide an introduction.
Lines 11800 13800: Enter the information on the names and virtues of
particular machines.
Lines 13900 14300: Provide warnings and excuses.
143
Artificial Intelligence on the Commodore 64
Lines 14400-14900: Contain the words for high and low cost messages.
The rest is up to you
Artificial Intelligence is a fascinating subject, and we trust that we have
given you enough information to get you started on your own experiments
in this area. We have certainly enjoyed making our own explorations whilst
putting this book together, but we have started to wonder how long it
will be before someone designs an expert system program which writes
books ...
144
Artificial Intelligence on the Commodore 64 shows
you how to implement Al routines on your home micro
and turn it into an intelligent machine which can hold
a conversation with you, give you rational advice,
learn from you (and teach you) and even write
programs for you.
The book explains Al from first principles and
assumes no previous knowledge of the subject. All
the important aspects of Al are covered and are fully
illustrated with example programs.
For many years science fiction books and films have
contained ‘intelligent’ computers which appear to be
at least the equal of man. Although some of the
features described in these remain illusions,
extensive research into Al has brought many of the
ideas much nearer reality.
Keith and Steven Brain are a father and son team and
have already published the bestselling Dragon 32
Games Master and Advanced Sound and Graphics for
the Dragon computer. They are both regular
contributors to Popular Computing Weekly.
SUNSHINE
ISBN 0 946408 29 7
£6.95 net