Eliza

Date: 198x
Type: Program
Platform(s): TS 2068

This is an ELIZA-style natural language psychiatrist simulation that uses a combination of BASIC and machine code to perform keyword searching within user input. The program stores 35 response strings and 12 pronoun-conjugation strings in dimensioned string arrays, reading them from DATA statements during initialisation. A machine code routine, loaded separately from tape and resident at address 63552, is called via USR to perform fast string-pattern matching; BASIC then reads the result back through PEEKs at fixed addresses. Pronoun conjugation is handled by replacing matched tokens (e.g. “YOU” → “I”, “ARE” → “AM”) using offset values stored in the numeric arrays B() and C(). The program requires a two-part tape load: the BASIC file and a separate CODE block at 63514 containing the machine code search routine, plus an optional saved SCREEN$.


Program Structure

The program is organised into clearly delineated phases:

  1. Lines 11–17: Title screen and keypress wait
  2. Lines 40–125: Initialisation (GO SUB 660) and greeting
  3. Lines 150–180: Main conversation loop
  4. Lines 190–340: Input processing and reply generation
  5. Lines 660–812: Initialisation subroutine — dimensions arrays, reads DATA
  6. Lines 814–1240: DATA for response strings and conjugation tokens
  7. Lines 1400–1410: DATA for keyword/token length offsets stored in B() and C()
  8. Lines 2440–2580: Random fallback replies (11 options, dispatched by computed GO SUB)
  9. Lines 4000–4070: Input acceptance and pre-processing
  10. Lines 5000–5110: Machine code search interface
  11. Lines 6000–6050: POKEing the query string for the machine code routine
  12. Lines 7000–7030: String trimming (trailing spaces)
  13. Lines 8000–8999: Diagnostic/debug routine (not called from main flow)
  14. Line 9998–9999: Save/load bootstrap

Machine Code Integration

The most technically significant feature is the keyword-search machine code block loaded from tape into address 63514 (decimal), with the entry point at USR 64552. The BASIC at line 5000 configures the routine by POKEing parameters into a fixed memory map:

AddressPurpose
64612–64613Pointer to start of string/data (set to 64612, 252 — likely a string descriptor)
64614–64615Length parameter P (length of query string)
64616–64617On entry: count E; on return: matched index K
64618–64619Base address F of the string table to search
64626–64627On return: position J of match within the keyword

After calling USR 64552, the results are retrieved with PEEK at lines 5090–5100. This approach sidesteps BASIC’s slow string scanning for a hot inner loop, which is critical given that 35 response strings and 12 conjugation tokens must be checked on every user turn.

The query string is written character-by-character via POKE into RAM starting at address R=64657 (line 6030), effectively building a C-style byte array that the machine code can scan directly.

Keyword Matching and Conjugation

The conversation engine performs two passes of machine code search per user input:

  • First pass (line 230): searches E=35 entries in C$() starting at address F=63515, returning matched index K and match position J.
  • Second pass (line 300): searches E=12 entries in G$() starting at F=64075, to find a pronoun/conjugation token within the user’s input fragment.

The numeric array B(35) stores the byte-length of each keyword in C$(), and C(12) stores lengths for each conjugation token in G$(). These are used to slice the user’s input string to extract the portion following the matched keyword for inclusion in the reply.

Pronoun conjugation uses the DATA at lines 1155–1240: pairs such as “MYSELF”/”YOURSELF”, “ARE”/”YOU ARE”, “YOU”/”YOU’RE”, “I”/”MY”, “WAS”/”AM” allow the program to reflect the user’s words back in first/second person as appropriate.

Key BASIC Idioms

  • Computed GO SUB (line 2460): GO SUB 2470+(Z*10) dispatches to one of 11 fallback reply routines, each 10 lines apart. This avoids a long IF/THEN chain.
  • POKE 23658,8 (line 40): Sets the system variable FLAGS2 to enable CAPS LOCK, ensuring user input is stored in uppercase for reliable keyword matching.
  • Sentinel string (line 4030): The user input is padded with " ZZZZZZZZ" at the end, providing a guaranteed non-matching guard sequence for the machine code scanner.
  • RESTORE before READ (lines 730, 790): Used to reset the DATA pointer to specific line numbers before reading conjugation tokens and offset tables into separate arrays.
  • String slicing for reply construction (lines 270, 310, 316, 320): The program concatenates fixed reply prefixes from C$(K) with fragments extracted from user input A$ and conjugation strings G$(K).
  • RND-based name prefix (line 160): With 20% probability the user’s first name Z$ is prepended to the reply, adding a personalisation touch.

Notable Techniques

Line 7000 implements a trailing-space trimmer: it scans H$ backwards to find the last non-space character, storing the result implicitly via the loop variable A. The caller then uses H$(TO A+1) or similar slices. Since DIM C$(35,52) pads all strings to 52 characters and DIM G$(12,8) pads to 8, this trimming is essential for clean output.

The tape bootstrap at line 9999 uses CLEAR 63500 to protect the machine code area before loading; it also loads a saved SCREEN$ to restore the title screen. Line 9998 saves all three components (BASIC, CODE, SCREEN$) in sequence with BEEPs between each to signal the user to keep the recorder running.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

Eliza

Source Code

    1 REM       "ELIZA"
    2 REM       ▀▀▀▀▀▀▀
    3 REM  A program which will            demonstrate a form of          artificial intelligence
    4 REM 
    5 REM Based on a program from         "GIANT BOOK OF COMPUTER          GAMES",by Tim Hartnell
    6 REM 
    7 REM Adapted for the TS 2068            by G.F. Chambers
    8 REM 
    9 REM 
   10 REM 
   11 PRINT AT 3,20;"""ELIZA"""
   12 PRINT AT 4,20;"       "
   13 PRINT AT 5,16;"YOUR  FRIENDLY"
   14 PRINT AT 6,19;"COMPUTER"
   15 PRINT AT 7,17;"PSYCHIATRIST"
   16 PRINT AT 21,4;"PRESS ANY KEY TO START"
   17 IF INKEY$="" THEN GO TO 17
   18 CLS 
   20 REM   NO PUNCTUATION EXCEPT            APOSTROPHES AS IN:
   25 REM 
   30 REM  YOU'RE:I'M:I'VE:YOU'VE
   40 POKE 23658,8
   50 GO SUB 660: REM Initialize
   55 PRINT AT 0,13;"ELIZA"
   56 PRINT AT 1,13;"▀▀▀▀▀"
   60 PRINT AT 5,0;" Welcome to another session with",,"your computer psychiatrist,Eliza"
   80 PRINT ,,,,"What is your first name?"
   90 INPUT Z$
  100 CLS : PRINT AT 6,2;"Well, Hi There '";z$;"'": PRINT 
  110 PRINT : PRINT "It sure is neat to see you."
  120 PRINT : PRINT "   How can I help you today?."
  125 PRINT : PRINT "    Tell me about your problems."
  150 GO SUB 4000: REM ACCEPT USER INPUT
  160 IF RND<.2 THEN PRINT Z$;", ";
  170 GO SUB 190: REM PROCESS INPUT,PRINT REPLY
  180 PRINT : GO TO 150
  190 LET R=64657
  195 GO SUB 6000
  230 LET E=35: LET F=63515
  240 GO SUB 5000
  245 IF K<1 OR K>35 THEN GO SUB 2440: RETURN 
  250 LET H$=C$(K)
  260 GO SUB 7000
  270 PRINT C$(K, TO (A+1));
  273 IF C$(K,A)<"A" THEN PRINT : RETURN 
  278 IF J=8 THEN RETURN 
  281 LET A$=" "+A$(LEN A$-(J-1) TO )
  285 LET R=64657
  290 GO SUB 6000
  300 LET E=12: LET F=64075
  305 GO SUB 5000
  307 IF K<0 OR K>10 THEN PRINT A$( TO LEN A$-8): RETURN 
  310 PRINT A$( TO LEN A$-(J+C(K)));" ";
  311 LET H$=G$(K)
  312 GO SUB 7000
  316 LET J$=A$( TO C(K))+" "+G$(K, TO A) 
  317 LET H$=G$(K)
  318 GO SUB 7000
  320 PRINT G$(K, TO (A+1));
  322 IF J=8 THEN RETURN 
  323 IF J>8 THEN GO TO 281
  340 RETURN 
  660 REM  INITIALIZE
  670 CLS 
  680 DIM C$(35,52): DIM G$(12,8)
  690 REM FILL C$ WITH REPLIES
  700 FOR A=1 TO 35
  710 READ C$(A)
  720 NEXT A
  730 RESTORE 1150
  740 FOR A=1 TO 12
  750 READ G$(A)
  760 NEXT A
  780 REM REPLIES
  790 RESTORE 1400
  793 DIM B(35): DIM C(12)
  795 FOR A=1 TO 35
  800 READ B(A)
  803 NEXT A
  807 FOR A=1 TO 12
  808 READ C(A)
  810 NEXT A
  812 RETURN 
  814 DATA " AM I"
  816 DATA "WHY DO YOU MENTION COMPUTERS?"
  818 DATA "WHY DO YOU BRING UP THE SUBJECT OF FRIENDS?"
  820 DATA "YOU SEEM QUITE CERTIAN. WHY IS THIS SO?"
  830 DATA "DO YOU DOUBT"
  840 DATA "CAN YOU THINK OF A SPECIFIC EXAMPLE?"
  850 DATA "WHY ARE YOU CONCERNED ABOUT MY"
  860 DATA "WHY ARE YOU BEING SO NEGATIVE?"
  870 DATA "AREN'T YOU BEING A BIT TENTATIVE?"
  880 DATA "IS IT GOOD THAT YOU LIKE"
  890 DATA "WHY DID YOU BRING UP THE SUBJECT OF DREAMS?"
  900 DATA "WHY ARE YOU APOLOGIZING?"
  910 DATA "MODERATION IN ALL THINGS SHOULD BE THE RULE."
  920 DATA "YOU'RE NOT BEING VERY FIRM ON THAT!"
  930 DATA "WHAT IS IT THAT YOU REALLY WANT TO KNOW?"
  940 DATA "WHAT WOULD YOUR BEST FRIEND SAY TO THAT QUESTION?"
  950 DATA "WHY DID YOU ASK ME THAT?"
  960 DATA "HOW OFTEN DO YOU THINK OF SUCH QUESTIONS?"
  970 DATA "WHAT ANSWER WOULD PLEASE YOU THE MOST?"
  980 DATA "WHAT DO YOU THINK?"
  990 DATA "WHY DO YOU WANT"
 1000 DATA "WHY ARE YOU TELLING ME YOU'RE"
 1010 DATA "HOW LONG HAVE YOU BEEN"
 1020 DATA "I FEEL YOU SHOULD REALLY DISCUSS THIS WITH A HUMAN."
 1030 DATA "HOW DO YOU KNOW YOU CAN'T"
 1040 DATA "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM"
 1050 DATA "WHAT MAKES YOU THINK YOU SHOULD BE ABLE TO"
 1060 DATA "WHY WOULD YOU WANT ME TO"
 1070 DATA "TELL ME MORE ABOUT FEELING"
 1080 DATA "WHY DONT YOU"
 1090 DATA "WHAT IS YOUR REACTION TO MY BEING"
 1100 DATA "WHAT MAKES YOU THINK I AM"
 1110 DATA "PERHAPS YOU DON'T WANT ME TO BE ABLE TO"
 1120 DATA "YES, I"
 1130 DATA "PERHAPS YOU WOULD LIKE ME TO BE ABLE TO"
 1140 REM  CONJUGATE
 1155 DATA "MYSELF"
 1157 DATA "YOURSELF"
 1158 DATA "ARE"
 1160 DATA "YOU ARE"
 1170 DATA "YOU"
 1180 DATA "YOU'RE"
 1190 DATA "YOU'VE"
 1200 DATA "MY"
 1210 DATA "I"
 1220 DATA "WAS"
 1230 DATA "AM"
 1240 DATA "YOU"
 1400 DATA 5,9,7,4,6,7,5,3,6,7,6,6,6,8,4,5,6,4,4,5,7,4,5,4,8,8,12,14,7,7,7,8,6,7,8
 1410 DATA 8,6,4,6,4,5,6,6,5,6,5,3
 2440 REM RANDOM REPLIES, NO KEYWORD
 2450 LET Z=INT (RND*11)+1
 2460 GO SUB 2470+(Z*10)
 2470 RETURN 
 2480 PRINT "WHAT DOES THAT SUGGEST TO YOU?": RETURN 
 2490 PRINT "I SEE.....": RETURN 
 2500 PRINT "I'M NOT SURE I UNDERSTAND       YOU FULLY": RETURN 
 2510 PRINT "CAN YOU ELABORATE ON THAT?": RETURN 
 2520 PRINT "THAT IS QUITE INTERESTING!": RETURN 
 2530 PRINT "THAT'S SO...PLEASE CONTINUE...": RETURN 
 2540 PRINT "I UNDERSTAND...": RETURN 
 2550 PRINT "WELL, WELL...DO GO ON.": RETURN 
 2560 PRINT "WHY ARE YOU SAYING THAT?": RETURN 
 2570 PRINT "PLEASE EXPLAIN THE BACKGROUND   TO THAT REMARK...": RETURN 
 2580 PRINT "COULD YOU SAY THAT AGAIN, IN A  DIFFERENT WAY?": RETURN 
 4000 REM ACCEPT AND FORMAT INPUT
 4010 INPUT A$: LET K$=A$
 4015 PRINT : PRINT A$: PRINT 
 4020 IF A$="" THEN GO TO 4010
 4030 LET A$=" "+A$+" ZZZZZZZZ"
 4050 IF A$( TO 4)=" BYE" THEN PRINT "Bye Bye for now.": PRINT "See you again some time.": STOP 
 4060 IF A$( TO 8)=" BECAUSE" THEN LET A$=A$(9 TO )
 4070 RETURN 
 5000 REM SET-UP FOR M/C SEARCH
 5010 POKE 64612,146: POKE 64613,252
 5020 POKE 64614,P-256*INT (P/256)
 5030 POKE 64615,INT (P/256)
 5040 POKE 64616,E-256*INT (E/256)
 5050 POKE 64617,INT (E/256)
 5060 POKE 64618,F-256*INT (F/256)
 5070 POKE 64619,INT (F/256)
 5080 LET B=USR 64552
 5090 LET K=PEEK 64616+256*(PEEK 64617)
 5100 LET J=PEEK 64626+256*(PEEK 64627)
 5110 RETURN 
 6000 REM POKING QUERY FOR M/C SEARCH
 6010 LET P=0
 6020 FOR X=1 TO LEN A$
 6030 POKE R+X,CODE A$(X)
 6040 LET P=P+1
 6050 NEXT X: RETURN 
 7000 REM CHOP UNUSED SPACES FROM END OF A STRING
 7010 FOR A=LEN H$ TO 1 STEP -1
 7020 IF H$(A)<>" " THEN RETURN 
 7030 NEXT A: RETURN 
 8000 FOR n=1 TO 12: PRINT g$(n);TAB 13;LEN g$(n);TAB 16;c(n): NEXT n
 8999 STOP 
 9998 SAVE "ELIZA" LINE 9999: BEEP .4,15: SAVE "ELIZA"CODE 63514,1120: BEEP .4,15: SAVE "Screen$"SCREEN$ : STOP 
 9999 CLEAR 63500: PRINT AT 9,4;"Now loading ""Eliza"" data",,,"     LEAVE RECORDER RUNNING": LOAD "ELIZA"CODE : PRINT "screen$ now loading": LOAD "Screen$"SCREEN$ : GO TO 10

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top