This program implements a conversational psychotherapy simulator in the style of ELIZA, presenting itself as “Dr. T. S. Comp.” It accepts free-text input from the user, scans it for 40 keywords stored in a DATA block, then selects one of several pre-written response templates from a corresponding DATA section. When a response ends with an asterisk, the subroutine at line 310 performs pronoun-swapping (e.g. “I am” → “you are”, “my” → “your”) on the portion of the user’s input that followed the matched keyword, appending the transformed text to the response. The program also normalises input to lowercase, strips apostrophes, and detects repeated input to generate a “you are repeating yourself” response.
Program Structure
Execution begins at line 10 with GO SUB 680, which initialises data structures and then falls through to the greeting/name-entry routine (lines 730–800). The main conversation loop runs from line 20 to line 280 for up to 20 exchanges (FOR q=1 TO 20).
- Lines 10–20: Initialisation subroutine call, loop start.
- Lines 30–60: Input handling — empty input, “stop” keyword, echo input.
- Lines 70–200: Input normalisation (lowercase, apostrophe removal) and keyword scanning.
- Lines 210–270: Response selection and optional name appending.
- Lines 290–300: Session-end message (triggered either by 20 exchanges or “stop”).
- Lines 310–420: Pronoun-swap subroutine.
- Lines 430–650: DATA — keyword list, substitution pairs, response strings.
- Lines 660–670: Repeat-detection and generic fallback responses.
- Lines 680–800: Initialisation, welcome screen, name input.
Keyword Scanning
Line 680 reads the count of keywords (kn=40) and substitution pairs (sn=9) from DATA. The array r(kn) holds the DATA line number of the response group for each keyword. Scanning (lines 160–200) uses RESTORE 430 and iterates through all 40 keywords, testing every position in the normalised input string for a substring match. The first match found wins; its associated response-group line number is stored in k and scanning aborts via GO TO 220.
Response Selection
At line 220, RESTORE k points the DATA pointer at the matched response group. A FOR loop reads between 1 and 1+RND*4 (i.e. 1–5) responses, so the chosen response is pseudo-random among the group’s entries. Each group contains exactly four responses, meaning 1+RND*4 can theoretically request a 5th read, which would bleed into the next DATA block — a latent off-by-one bug.
Pronoun Substitution
When a selected response string ends with "*", the subroutine at line 310 is called. It strips the trailing "* " characters from r$, then takes the tail of the user’s input starting at position kp (just after the matched keyword) into m$. It then applies up to 9 find-and-replace pairs read from DATA at line 450, swapping first- and second-person forms:
| Find | Replace |
|---|---|
| i am | you are |
| you are | I am |
| you. | me |
| you | I |
| me. | you |
| i | you |
| am | are |
| my | your |
| your | my |
The substitution loop (lines 360–390) walks index j through m$, advancing by the replacement length after a match to avoid re-scanning substituted text.
Input Normalisation
Lines 80–110 iterate character by character through the user’s input. Uppercase letters (ASCII 65–90) are converted to lowercase by adding 32 to their CODE. Apostrophes are removed by string slicing: A$=A$(1 TO i-1)+A$(i+1 TO ). Note that the loop termination condition at line 110 checks i <> LEN A$ rather than i > LEN A$, which means the last character of the string is never processed — a minor bug that could leave a trailing uppercase letter or apostrophe unhandled.
Repeat Detection
The previous normalised input is stored in b$ (initialised to "*" at line 690, an impossible input value). At line 120, if the current input matches b$, the response group at line 660 (“You just said that”, “you are repeating yourself”, etc.) is selected. Line 130 then updates b$ for the next turn.
Name Personalisation
The user’s first name is stored in n$ (lines 760–770), with the first character forced to uppercase. At line 260, there is a 50% chance (RND > .5) that ", ";n$ is appended to a response, giving a personalised feel. The session-end message at line 290 always uses n$.
Notable Techniques and Idioms
RESTORE k(line 220) uses a variable as a DATA line pointer — a standard Spectrum BASIC technique for keyed DATA access without arrays of strings.INPUT LINEis used throughout to accept spaces and punctuation without triggering expression evaluation.- Line 440 contains a lone
DATA "f"entry acting as a sentinel/padding between the keyword DATA (line 430) and the substitution pairs (line 450); this is read as the 41st keyword butkn=40so it is never reached in normal scanning. - The DATA at lines 710–720 encodes response group line numbers paired with their keywords, allowing
r(i)lookup in O(1) after the initial READ loop. - Line 800 uses
RESTORE(no argument) to reset the DATA pointer to the beginning before returning, ensuring the main loop’sRESTORE 430works correctly on the first pass.
Content
Source Code
10 GO SUB 680
20 FOR q=1 TO 20
30 INPUT LINE A$: IF A$="" THEN PRINT "Try to tell me whats on your mind, ";n$: GO TO 270
40 IF A$="stop" THEN PRINT "That ends this session.": STOP
50 PRINT 'A$''
60 IF q=20 THEN GO TO 290
70 IF LEN A$=1 THEN LET k=670: GO TO 300
80 LET i=1
90 LET ch=CODE A$(i): IF ch<=90 AND ch>=65 THEN LET a$(i)=CHR$ (ch+32)
100 IF A$(i)="'" THEN LET A$=A$(1 TO i-1)+A$(i+1 TO )
110 LET i=i+1: IF i<>LEN A$ THEN GO TO 90
120 IF A$=b$ THEN LET k=660: GO TO 220
130 LET b$=A$
140 RESTORE 430
150 LET A$=A$+".": LET l=LEN A$
160 FOR i=1 TO kn: READ k$: LET kl=LEN k$
170 FOR j=1 TO l-kl+1
180 IF A$(j TO j+kl-1)=k$ THEN LET k=r(i): LET kp=j+kl: GO TO 220
190 NEXT j
200 NEXT i
210 LET k=670
220 RESTORE k: FOR i=1 TO 1+RND*4: READ r$: NEXT i
230 LET rl=LEN r$: IF r$(rl)="*" THEN GO SUB 310
240 IF r$(LEN r$)="." THEN LET r$=r$(1 TO LEN r$-1)
250 PRINT r$;
260 IF RND>.5 THEN PRINT ", ";n$
270 PRINT ''
280 NEXT q
290 PRINT INK 2;"Our time is about up ";n$;".","I've enjoyed talking with you. Goodby till next time."
300 STOP
310 LET r$=r$( TO rl-2): IF kp>=l THEN RETURN
320 RESTORE 450: LET m$=a$(kp TO )
330 FOR i=1 TO sn
340 READ s$,t$
350 LET sl=LEN s$: LET tl=LEN t$: LET j=1
360 IF j>LEN m$-sl+1 THEN GO TO 400
370 IF m$(j TO j+sl-1)=s$ THEN LET m$=m$(1 TO j-1)+t$+m$(j+sl TO ): LET j=j+tl-1
380 LET j=j+1
390 GO TO 360
400 NEXT i
410 LET r$=r$+m$
420 RETURN
430 DATA "do you","don't you","can you","can't you","do I","don't I","can I","can't I","I feel","I think","am I","are you","I cannot","I can't","I can","I'm","I am","I want","because","so that","who","why","when","where","how","what","kill","hit","die","deas","TS2068","TS","compu","key","tv","telev","off","stop","shut ","sorry"
440 DATA "f"
450 DATA "i am","you are","you are","I am"," you."," me","you ","I "," me."," you"," i "," you "," am "," are "," my"," your"," your"," my"
460 DATA "Why do you ask whether I *","sometimes I do *","Would you like me to *","No I do not *"
470 DATA "Would you like me to *","Can you *","Do you think Ican *","Why do you ask this"
480 DATA "Perhaps you do *","Would you like to *","What answer would you like","Do you think you will *"
490 DATA "Do you want to *","Would you like to be able to *","Is it normal to *","Have you asked anyone else this"
500 DATA "Please explain these fellings","Do you like feeling this way","Many people feel this way","Do you often feel *"
510 DATA "Are you sure","Why do you think *","You seem uncertian","What makes you think *"
520 DATA "Do you want to be *","I think you may be *","Do you often ask yourself this","Is this important to you"
530 DATA "I would prefer not to say","Tell me whether you are *","Do you like to think that I am *","Perhaps you think I am *"
540 DATA "Why can't you","Are you sure you can't *","Would you like to *","Is this normal for you"
550 DATA "Can you really","Can your friends *","Do you like being able to *","Can you always *"
560 DATA "Have you always been *","Do you dream about being *","Do you want me to be *","Do you enjoy being *"
570 DATA "Why do you want *","How long have you wanted this","Do you think it is normal to want *","How much do you want this"
580 DATA "Is this the only reason","Are there other reasons","Is this really why","Do you believe this is the real reason"
590 DATA "Let's forget that. Why are you asking questions","How would you like me to answer that","Does the question worry you","Do you want to sit in my chair"
600 DATA "Do you like violence","Do you have violent fantasies","Please calm yourself","I have a pistol in my drawer"
610 DATA "Does death interest you","Do you like graveyards","Do you have morbid dreams","Are you often morbid"
620 DATA "Do you like computers","Are you frightened of machines","What do you do when you are not here","What color are computers in your dreams"
630 DATA "Are you keen on TV","Do you find TV boring","Is your TV big","Would you prefer to be watching Crossroads"
640 DATA "I will ignore that","Your time is not yet up","Do you like being agressive","I am tring to be tolerant"
650 DATA "Thats OK","don't apologize","Why are you sorry","Not at all"
660 DATA "You just said that","you are repeating yourself","Why do you repeat yourself","Please don't repeat yourself"
670 DATA "Can you be more specific","I see - go on","That is interesting","Do you feel happy about this discussion"
680 RESTORE 710: READ kn,sn
690 DIM r(kn): LET b$="*"
700 FOR i=1 TO kn: READ r(i): NEXT i
710 DATA 40,9,460,460,470,470,480,480,490,490,500,510,520,530,540,540,550,560,560,570,580,580,590,590,590,590,590,590,600,600
720 DATA 610,610,620,620,620,620,630,630,640,640,640,650
730 PAPER 7: CLS : BORDER 7: INK 0
740 PRINT '"Welcome."''"I am Dr. T. S. Comp."''"Please make yourself comfortable"
750 PRINT '"What is your first name?"
760 INPUT LINE n$: IF n$="" THEN INPUT "Please don't be shy."; LINE n$
770 IF n$(1)>="a" THEN LET n$(1)=CHR$ (CODE n$(1)-32)
780 PRINT 'n$''
790 PRINT "What would you like to discuss",n$;"?"
800 RESTORE : RETURN
9998 SAVE "aid" LINE 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
