Eliza

This file is part of and SINCUS Exchange Tape 101 - Entertainment. Download the collection to get this file.
Type: Program
Platform(s): TS 2068
Tags: Game

This program implements a conversational psychiatrist simulation based on the classic ELIZA concept, adapted for the Timex Sinclair 2068. It uses a machine code routine loaded via POKE statements at address 64552 to perform fast keyword searching through the user’s input string, replacing the slow BASIC string-scanning that would otherwise be required. The program maintains two string arrays — C$(35,52) for 35 canned response phrases and G$(12,8) for 12 conjugation substitution strings — along with parallel numeric arrays B(35) and C(12) that store the character lengths of the corresponding keywords. Input preprocessing strips a leading “BECAUSE” clause and appends a sentinel “ZZZZZZZZ” suffix before the machine code search runs. The save/load routine at lines 9998–9999 stores the machine code block separately as CODE at address 63514 and reloads it on startup via a LOAD “”CODE command followed by a GO TO 10 jump.


Program Analysis

Program Structure

The program is organized into a main loop with several subroutine layers. Lines 1–18 handle the title screen and keypress wait. Lines 50–180 form the main conversation loop: a greeting sequence, then a repeated cycle of accepting user input (via GO SUB 4000), optionally prefixing the user’s name (line 160), processing input and printing a reply (via GO SUB 190), and looping back. The initialization subroutine at line 660 allocates all arrays and loads DATA into them. Lines 814–1140 hold the response strings and conjugation words as DATA, and lines 1400–1410 hold keyword-length DATA. Random fallback replies occupy lines 2440–2580, and machine code setup subroutines are at lines 5000–7000.

Machine Code Integration

The heart of the program’s speed is a machine code search routine residing at address 64552. BASIC alone would be too slow to scan 35 keyword entries against user input on every turn. The subroutine at line 5000 configures the machine code by POKEing six parameter bytes starting at address 64612: a pointer to the search string (variable P), a count of entries to search (E), and a base address of the table to search (F). After calling USR 64552, the results are read back via PEEK: K (match index) from addresses 64616–64617 and J (matched keyword length) from 64626–64627.

The subroutine at line 6000 POKEs the user’s input string character-by-character into RAM starting at address R (initially 64657), building a raw byte buffer the machine code can scan directly. This pattern — staging a string into a fixed RAM buffer before calling machine code — is a common technique when machine code must access string data without navigating BASIC’s string descriptor structures.

The machine code block itself is saved and loaded separately: line 9998 saves the CODE block at 63514 with length 1120 bytes, and on autostart (line 9999), after a CLEAR 63500, it loads that block back before jumping to line 10 (which effectively falls through to line 11).

Keyword Search Logic

The main response routine (lines 190–340) performs two machine code searches in sequence:

  1. A primary search over 35 entries (E=35) at address F=63515, which is the response-phrase table loaded into the bottom of the reserved RAM area. The match index K selects a reply string from C$(K).
  2. A secondary search over 12 conjugation entries (E=12) at address F=64075 to find pronoun/verb substitutions (e.g., “I” → “YOU”, “ARE” → “YOU ARE”). The match selects from G$(K) for grammatical transformation of the echoed user fragment.

If the primary search returns K outside range 1–35, the program falls through to the random-reply subroutine at line 2440. If the secondary search returns K outside 0–10, it prints the remaining input fragment without substitution.

Reply Construction and Conjugation

Lines 270–340 handle composing the actual printed response. The program prints the response prefix from C$(K) up to position A+1 (where A is determined by subroutine 7000, which finds the last non-space character). If the reply string ends there (i.e., C$(K,A) < "A"), it simply returns. Otherwise it appends a conjugation-transformed fragment of the user’s input. Line 281 trims the user input string A$ by removing the matched keyword portion. Line 316 reconstructs a response fragment J$ combining input up to the conjugation word with the conjugation replacement. J=8 is used as a sentinel value indicating the match landed on the trailing “ZZZZZZZZ” padding, signaling no further content to append.

Subroutine 7000 — String Length Trimmer

Subroutine 7000 (lines 7010–7030) scans H$ from its end backward to find the last non-space character, returning the position in A. Since all string arrays are fixed-width (padded with spaces), this avoids printing trailing spaces in responses. It is called multiple times before printing a reply segment. Note that A is reused as both a loop variable in this subroutine and as the array-fill loop counter in the initialization routine — callers must be aware that A is overwritten on return.

Array Dimensions and DATA Layout

ArrayDimensionsContentsDATA start
C$(35,52)35 strings × 52 charsResponse phrasesline 814
G$(12,8)12 strings × 8 charsConjugation substitutionsline 1155
B(35)35 elementsKeyword lengths for C$ tableline 1400
C(12)12 elementsKeyword lengths for G$ tableline 1410

The DATA is read non-sequentially: RESTORE 1150 at line 730 positions the DATA pointer for the conjugation strings (which actually begin at line 1155 due to the REM at 1140), and RESTORE 1400 at line 790 reads the two numeric length arrays. The response-phrase DATA beginning at line 814 is read sequentially from the program start without an explicit RESTORE, relying on the default DATA pointer state after initialization.

Random Fallback Dispatch

Lines 2440–2580 implement 11 fallback responses using a computed GO SUB: GO SUB 2470+(Z*10) where Z is 1–11. Each handler is exactly 10 lines apart (2480, 2490, …, 2580), with a dummy RETURN at line 2470 acting as an entry guard. This is a classic Sinclair BASIC dispatch table idiom, avoiding a long IF-THEN chain.

Input Preprocessing

Subroutine 4000 reads user input into A$, echoes it to screen, prepends a space (" "+A$), and appends " ZZZZZZZZ" as a sentinel. It strips a leading “BECAUSE” clause (line 4060) so responses to justifications are handled as if the user stated the core thought directly. A BYE check at line 4050 looks at the first four characters of the padded string (" BYE") and halts with a farewell message.

Bugs and Anomalies

  • Line 820 contains a typo: "CERTIAN" should be "CERTAIN".
  • Line 8000 is a diagnostic/debug routine (prints all G$ entries with lengths and C values) that was apparently left in the final listing; it is not called from anywhere in the main program flow.
  • The variable A is used as both the string-trimming result variable in subroutine 7000 and as the loop counter in the DATA-loading loops during initialization. Callers of subroutine 7000 that subsequently use A as an index (e.g., lines 270, 316, 320) rely on the subroutine setting A to the last non-space position, which is the intended behavior, but the shared name could cause confusion.
  • The secondary search result check at line 307 tests K<0 OR K>10 — since K is an index into a 12-element array G$(1 TO 12), a value of 0 or 11–12 would be out of range. However, valid indices are 1–12, so the upper bound of 10 potentially skips entries 11 and 12 of G$, treating them as no-match cases.
  • POKE 23658,8 at line 40 sets the TS2068 FLAGS2 system variable to enable CAPS LOCK, ensuring user input is entered in uppercase to match the uppercase keyword strings.

Content

Appears On

Pure fun — land on the moon, herd sheep, hunt submarines, race cricketers, eat dots as Pac-Man, and dodge alien swarms across a nighttime skyline. SINCUS Tape 101 is a deep bench of TS 2068 arcade action, card games, and sports simulations.

Related Products

Related Articles

Related Content

Image Gallery

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: STOP 
 9999 CLEAR 63500: PRINT AT 9,4;"Now loading ""Eliza"" data",,,"     LEAVE RECORDER RUNNING": LOAD ""CODE 63514,1120: GO TO 10

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

People

No people associated with this content.

Scroll to Top