Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

2024 Participants: Hannah Ackermans * Sara Alsherif * Leonardo Aranda * Brian Arechiga * Jonathan Armoza * Stephanie E. August * Martin Bartelmus * Patsy Baudoin * Liat Berdugo * David Berry * Jason Boyd * Kevin Brock * Evan Buswell * Claire Carroll * John Cayley * Slavica Ceperkovic * Edmond Chang * Sarah Ciston * Lyr Colin * Daniel Cox * Christina Cuneo * Orla Delaney * Pierre Depaz * Ranjodh Singh Dhaliwal * Koundinya Dhulipalla * Samuel DiBella * Craig Dietrich * Quinn Dombrowski * Kevin Driscoll * Lai-Tze Fan * Max Feinstein * Meredith Finkelstein * Leonardo Flores * Cyril Focht * Gwen Foo * Federica Frabetti * Jordan Freitas * Erika FülöP * Sam Goree * Gulsen Guler * Anthony Hay * SHAWNÉ MICHAELAIN HOLLOWAY * Brendan Howell * Minh Hua * Amira Jarmakani * Dennis Jerz * Joey Jones * Ted Kafala * Titaÿna Kauffmann-Will * Darius Kazemi * andrea kim * Joey King * Ryan Leach * cynthia li * Judy Malloy * Zachary Mann * Marian Mazzone * Chris McGuinness * Yasemin Melek * Pablo Miranda Carranza * Jarah Moesch * Matt Nish-Lapidus * Yoehan Oh * Steven Oscherwitz * Stefano Penge * Marta Pérez-Campos * Jan-Christian Petersen * gripp prime * Rita Raley * Nicholas Raphael * Arpita Rathod * Amit Ray * Thorsten Ries * Abby Rinaldi * Mark Sample * Valérie Schafer * Carly Schnitzler * Arthur Schwarz * Lyle Skains * Rory Solomon * Winnie Soon * Harlin/Hayley Steele * Marylyn Tan * Daniel Temkin * Murielle Sandra Tiako Djomatchoua * Anna Tito * Introna Tommie * Fereshteh Toosi * Paige Treebridge * Lee Tusman * Joris J.van Zundert * Annette Vee * Dan Verständig * Yohanna Waliya * Shu Wan * Peggy WEIL * Jacque Wernimont * Katherine Yang * Zach Whalen * Elea Zhong * TengChao Zhou
CCSWG 2024 is coordinated by Lyr Colin (USC), Andrea Kim (USC), Elea Zhong (USC), Zachary Mann (USC), Jeremy Douglass (UCSB), and Mark C. Marino (USC) . Sponsored by the Humanities and Critical Code Studies Lab (USC), and the Digital Arts and Humanities Commons (UCSB).

[Code Critique] What does the original ELIZA code offer us.

ELIZA was developed in 1966 using the MAD computer programming language and the SLIP Application Programming Interface (API). The ELIZA code has several parts to it in execution;

  • ELIZA is the control program. It has an editor for interactive editing of a script, and it has the control program for interacting with a user.
  • SLIP is an API which provides functionality suitable for a graph, i.e., a recursive structure modeled as a list.
  • A script is a piece of data which assumes a persona when interacting with a person. That is, ELIZA uses the script as data when analyzing (disassembly) user input and generating output (assembly).

Using current standards, the code is simply awful. However looking at code at that time it is a wonder. Going back to this time we see that programs, languages, compilers, and data were all developed with a particular computer in mind. In the general sense, nothing was portable between computers or between operating systems, on the same or different computers. Portability often consisted of a rewrite, sometimes in the same computer language, often in another.

There was no need to construct some general API because programs were stand-alone creatures. A generalized API would serve no purpose, and in addition, other developers on the same computer using the same operating were typically unaware of some generalized interface and would probably not use one if aware. SLIP was a departure. It was a generalized API used, and rewritten, for multiple computers and in multiple languages. Although different implementations were different, the general functionality of the original SLIP was preserved. This was an innovation.

The concept of a a computer storing (and executing) a program from memory was relatively new. The idea that a program was a 'dumb' calculator that used data as its preemptive force was novel. The ELIZA control logic is the 'dumb' program. It has no mechanism for dealing with user input other than that provided by it's data, the script. Using a piece of data to define the interactive, or non-interactive, execution of a program was novel. Programs at that time were stand-alone creatures which had an internal state which controlled behavior, not externally supplied data.

So, why was the code awful (by current standards)? Except for the MAD conditional (WHENEVER, OR WHENEVER, OTHERWISE, END WHENEVER) the concept of a block does not exist. Idealization of code into code 'blocks' is absent, instead, if you wanted to execute some piece of code within a function, you branched to it (TRANSFER(. And much like FORTRAN at this time, ELIZA contains an uncontrolled collection of branches. This makes the understanding of what is happening problematical, and for us here and now, very difficult. Modern computer science understands this, and advises against just these constructs.

So, what makes this code worthwhile? Other than the novelty of using input data to drive program language, the entire ELIZA program is about 420 lines long. It created and impact when written; it had an impact after it was written; it remains with an impact now. How could such a small program have such a large influence? And that makes it worthwhile as a subject of investigation. It can be looked at with respect to historical computer science; it can be looked at to see if there are any societal interests contained as part of its program - it's program style.

The attachment has the original ELIZA program written in MAD and commented on by Anthony Hay. Note that MAD is not a free-form language. On a punched card, columns 1 - 7 is reserved for a label, column 8 is reserved for a comment 'R' or a continuation mark, and columns 73 - 80 are typically used to contain a card number, the compiler ignores them.

Comments

  • Great @aschwarz Though its lengthy, I'm going to just paste the commented code in here hopefully to speed along commentary:

    ELIZA Code annotation Sheet
    
    
    ;
    ; ELIZA by Joseph Weizenbaum.
    ;
    ; Any line beginning with a semicolon is commentary and was not part of
    ; the original ELIZA code. Each commentary block generally refers to the
    ; code just above it.
    ;
    
    
    
            CHANGE   MAD
                EXTERNAL FUNCTION (KEY,MYTRAN)                                      000010
                NORMAL MODE IS INTEGER                                              000020
                ENTRY TO CHANGE.                                                    000030
                LIST.(INPUT)                                                        000040
                V'S G(1)=$TYPE$,$SUBST$,$APPEND$,$ADD$,                             000050
               1$START$,$RANK$,$DISPLA$                                             000060
                V'S SNUMB = $ I3 *$                                                 000070
                FIT=0                                                               000080
    CHANGE      PRINT COMMENT $PLEASE INSTRUCT ME$                                  001400
                LISTRD.(MTLIST.(INPUT),0)                                           001410
                JOB=POPTOP.(INPUT)                                                  001420
                T'H IDENT, FOR J=1,1, J.G. 7                                        001430
    IDENT       W'R G(J) .E. JOB, T'O THEMA                                         001440
                PRINT COMMENT $CHANGE NOT RECOGNIZED$                               001450
                T'O CHANGE                                                          001460
    THEMA       W'R J .E. 5, F'N IRALST.(INPUT)                                     001470
                W'R J .E. 7                                                         001480
                    T'H DISPLA, FOR I=0,1, I  .G. 32                                001490
                    W'R LISTMT.(KEY(I)) .E. 0, T'O DISPLA                           001500
                    S=SEQRDR.(KEY(I))                                               001510
    READ(7)         NEXT=SEQLR.(S,F)                                                001520
                    W'R F .G. 0, T'O DISPLA                                         001530
                    PRINT COMMENT $*$                                               001540
                    TPRINT.(NEXT,0)                                                 001550
                    PRINT FORMAT SNUMB,I                                            001560
                    PRINT COMENT $ $                                                001570
                    T'O READ(7)                                                     001580
    DISPLA          CONTINUE                                                        001590
                    PRINT COMMENT $ $                                               001600
                    PRINT COMMENT $MEMORY LIST FOLLOWS$                             001610
                    PRINT COMMENT $ $                                               001620
                    T'H MEMLIST, FOR I=1 , 1, I .G. 4                               001630
    MEMLST          TXTPRT.(MYTRAN(I),0)                                            001640
                    T'O CHANGE                                                      001650
                E'L                                                                 001660
                THEME=POPTOP.(INPUT)                                                001670
                SUBJECT=KEY(HASH.(THEME,5))                                         001680
                S=SEQRDR.(SUBJECT)                                                  001690
    LOOK        TERM=SEQLR.(S,F)                                                    001700
                W'R F .G. 0, T'O FAIL                                               001710
                W'R TOP.(TERM) .E. THEME, T'O FOUND                                 001720
                T'O LOOK                                                            001730
    FOUND       T'O DELTA(J)                                                        001740
    DELTA(1)    TPRINT.(TERM,0)                                                     001750
                T'O CHANGE                                                          001760
    FAIL        PRINT COMMENT $LIST NOT FOUND$                                      001770
                T'O CHANGE                                                          001780
    DELTA(2)    S=SEQRDR.(TERM)                                                     001790
                OLD=POPTOP.(INPUT)                                                  001800
    READ(1)     OBJCT=SEQLR.(S,F)                                                   001810
                W'R F .G. 0, T'O FAIL                                               001820
                W'R F .NE. 0, T'O READ(1)                                           001830
                INSIDE=SEQRDR.(OBJECT)                                              001840
    READ(2)     IT=SEQLR.(INSIDE,F)                                                 001850
                W'R F .G. 0, T'O READ(1)                                            001860
                SIT=SEQRDR.(IT)                                                     001870
                SOLD=SEQRDR.(OLD)                                                   001880
    ITOLD       TOLD=SEQLR.(SOLD,FOLD)                                              001890
                DIT=SEQLR.(SIT,FIT)                                                 001900
                W'R TOLD .E. DIT .AND. FOLD .LE. 0,T'O ITOLD                        001910
                W'R FOLD .G. 0, T'O OK(J)                                           001920
                T'O READ(2)                                                         001930
    OK(2)       SUBST.(POPTOP.(INPUT),LSPNTR.(INSIDE))                              001940
                T'O CHANGE                                                          001950
    OK(3)       NEWBOT.(POPTOP.(INPUT),OBJCT)                                       001960
                T'O CHANGE                                                          001970
    DELTA(3)    T'O DELTA(2)                                                        001980
    DELTA(4)    W'R NAMTST.(BOT.(TERM)) .E. 0                                       001990
                    BOTTOM=POPBOT.(TERM)                                            002000
                    NEWBOT.(POPTOP.(INPUT),TERM)                                    002010
                    NEWBOT.(BOTTOM,TERM)                                            002020
                O'E                                                                 002030
                    NEWBOT.(POPTOP.(INPUT),TERM)                                    002040
                E'L                                                                 002050
                T'O CHANGE                                                          002060
    DELTA(6)    S=SEQRDR.(TERM)                                                     002070
    READ(6)     OBJCT=SEQLR.(S,F)                                                   002080
                W'R F .G. 0, T'O FAIL                                               002090
                W'R F .NE. 0, T'O READ(6)                                           002100
                OBJCT=SEQLL.(S,F)                                                   002110
                W'R LNKLL.(OBJECT) .E. 0                                            002120
                    SUBST.(POPTOP.(INPUT),LSPNTR.(S))                               002130
                O'E                                                                 002140
                    NEWTOP.(POPTOP.(INPUT),LSPNTR.(S))                              002150
                E'L                                                                 002160
                T'O CHANGE                                                          002170
               R* * * * * * * * * * END OF MODIFICATION ROUTINE                     002180
                E'N                                                                 002200
            TPRINT  MAD
                EXTERNAL FUNCTION (LST)                                             000010
                NORMAL MODE IS INTEGER                                              000020
                ENTRY TO TPRINT.                                                    000030
                SA=SEQRDR.(LST)                                                     000040
                LIST.(OUT)                                                          000050
    READ        NEXT=SEQLR.(SA,FA)                                                  000060
                W'R FA .G. 0, T'O P                                                 000070
                W'R FA .E. 0, T'O B                                                 000080
                POINT=NEWBOT.(NEXT,OUT)                                             000100
                W'R SA .L. 0, MRKNEG.(POINT)                                        000110
                T'O READ                                                            000120
    B           TXTPRT.(OUT,0)                                                      000130
                SEQLL.(SA,FA)                                                       000140
    MORE        NEXT=SEQLR.(SA,FA)                                                  000150
                W'R TOP.(NEXT) .E. $=$                                              000160
                    TXTPRT.(NEXT,0)                                                 000170
                    T'O MORE                                                        000180
                E'L                                                                 000190
                W'R FA .G. 0, T'O DONE                                              000200
                PRINT COMMENT $ $                                                   000210
                SB=SEQRDR.(NEXT)                                                    000220
    MEHR        TERM=SEQLR.(SB,FB)                                                  000230
                W'R FB .L.0                                                         000240
                    PRINT ON LINE FORMAT NUMBER, TERM                               000250
                    V'S NUMBER = $I3 *$                                             000260
                    T'O MEHR                                                        000270
                E'L                                                                 000280
                W'R FB .G. 0, T'O MORE                                              000290
                TXTPRT.(TERM,0)                                                     000300
                T'O MEHR                                                            000310
    P           TXTPRT.(OUT,0)                                                      000320
    DONE        IRALST.(OUT)                                                        000330
                F'N                                                                 000340
                E'N                                                                 000350
            LPRINT  MAD
                EXTERNAL FUNCTION (LST,TAPE)                                        006340
                NORMAL MODE IS INTEGER                                              006350
                ENTRY TO LPRINT.                                                    006360
                BLANK = $      $                                                    006370
                EXECUTE PLACE.(TAPE,0)                                              006380
                LEFTP = 606074606060K                                               006390
                RIGHTP= 606034606060K                                               006400
                BOTH  = 607460603460K                                               006410
                EXECUTE NEWTOP.(SEQRDR.(LST),LIST.(STACK))                          006420
                S=POPTOP.(STACK)                                                    006430
    BEGIN       EXECUTE PLACE.(LEFTP,1)                                             006440
    NEXT        WORD=SEQLR.(S,FLAG)                                                 006450
                W'R FLAG .L. 0                                                      006460
                EXECUTE PLACE.(WORD,1)                                              006470
                W'R S .G. 0, PLACE.(BLANK,1)                                        006480
                T'O NEXT                                                            006490
                OR W'R FLAG .G. 0                                                   006500
                EXECUTE PLACE.(RIGHTP,1)                                            006510
                W'R LISTMT.(STACK) .E. 0, T'O DONE                                  006520
                S=POPTOP.(STACK)                                                    006530
                T'O NEXT                                                            006540
                OTHERWISE                                                           006550
                W'R LISTMT.(WORD) .E. 0                                             006560
                EXECUTE PLACE.(BOTH,1)                                              006570
                T'O NEXT                                                            006580
                OTHERWISE                                                           006590
                EXECUTE NEWTOP.(S,STACK)                                            006600
                S=SEQRDR.(WORD)                                                     006610
                T'O BEGIN                                                           006620
                E'L                                                                 006630
                E'L                                                                 006640
    DONE        EXECUTE PLACE.(0,-1)                                                006650
                EXECUTE IRALST.(STACK)                                              006660
                FUNCTION RETURN LST                                                 006670
                END OF FUNCTION                                                     006680
    ;
    ; TESTS(CAND, S) return a sequence reader if the keyword matches the user's
    ;                input text, otherwise return 0.
    ;
    ; CAND  is the keyword candidate transformation rule
    ; S     is the sequence reader for the user INPUT text
    ;
    ; This function has 3 tasks
    ;
    ;  1. Test whether the whole candidate keyword matches the whole word
    ;     in the user's input text.
    ;  2. If the words do match, make any keyword substitution specified
    ;     in the candidate transformation rule.
    ;  3. Position the candidate reader past the substitution keyword, if any.
    ;
    ; SLIP packs 6 6-bit characters into each 36-bit IBM 7094 machine word.
    ; If a word has more than 6 characters it is continued into the next SLIP
    ; cell, with the first cell having its sign bit set. ???
    ;
    ; This code abstracts this full-word matching and has the side-effect
    ; of modifying the user's input text with the substitution word, if
    ; specified.
    ;
            TESTS   MAD
                EXTERNAL FUNCTION(CAND,S)                                           000010
                NORMAL MODE IS INTEGER                                              000020
                DIMENSION FIRST(5),SECOND(5)                                        000030
                ENTRY TO TESTS.                                                     000040
                STORE=S                                                             000050
                READER=SEQRDR.(CAND)                                                000060
                T'H ONE, FOR I=0,1, I .G. 100                                       000070
                FIRST(I)=SEQLR.(READER,FR)                                          000080
    ONE         W'R READER .G. 0, T'O ENDONE                                        000090
    ;
    ; Copy all 6-character chunks of the candidate keyword to the FIRST array.
    ;
    ; [As the loop termination condition is I .G. 100 (000070), this code will
    ; write past the end of the FIRST array if the keyword is longer than 36
    ; characters (because the first 36 characters will be copied to
    ; FIRST(0) .. FIRST(5), and any further characters will be written to
    ; machine words past FIRST(5)).]
    ;
    ENDONE      SEQLL.(S,F)                                                         000100
                T'H TWO, FOR J=0,1, J .G. 100                                       000110
                SECOND(J)=SEQLR.(S,F)                                               000120
    TWO         W'R S .G. 0, T'O ENDTWO                                             000130
    ;
    ; Copy all 6-character chunks of the user input word to the SECOND array.
    ; [May write past the end of SECOND.]
    ;
    ENDTWO      W'R I .NE. J, F'N 0                                                 000140
    ;
    ; If the keyword in FIRST has a different number of 6-character chunks to
    ; the word in SECOND the two words cannot be the same, so return the value 0,
    ; signifying no match.
    ;
    ; W'R is an abbreviation of WHENEVER
    ; .NE. means not equal
    ; F'N is an abbreviation of FUNCTION RETURN
    ;
                T'H LOOK, FOR K=0,1, K.G. J                                         000150
    LOOK        W'R FIRST(K) .NE. SECOND(K), F'N 0                                  000170
    ;
    ; Compare each 6-character chunk of the keyword with the corresponding chunk
    ; of the user input word. If any are different, return 0, signifying no match.
    ;
                EQL=SEQLR.(READER,FR)                                               000180
                W'R EQL .NE. $=$                                                    000190
                SEQLL.(READER,FR)                                                   000200
                F'N READER                                                          000210
                O'E                                                                 000220
    ;
    ; At this point we know that the keyword matches the user's word.
    ; Check whether the transformation rules specify a simple word substitution,
    ; signified by the presence of an "=".
    ;
    ; If it is not an "=", reposition the reader back before the element and
    ; return the reader, signifying a successful match.
    ;
                POINT=LNKL.(STORE)                                                  000230
                T'H DELETE , FOR K=0,1, K .G. J                                     000240
                REMOVE.(LSPNTR.(STORE))                                             000250
    DELETE      SEQLR.(STORE,F)                                                     000260
    INSRT       NEW=SEQLR.(READER,FR)                                               000270
                POINT=NEWTOP.(NEW,POINT)                                            000280
                MRKNEG.(POINT)                                                      000290
                W'R READER .L. 0, T'O INSRT                                         000300
                MRKPOS.(POINT)                                                      000310
                F'N READER                                                          000320
                E'L                                                                 000330
                E'N                                                                 000340
    ;
    ; An "=" was present in the transformation rule. E.g. a script
    ; transformation rule may begin
    ;
    ;           (YOUR = MY
    ;               ((0 MY 0)
    ;                   (WHY ARE YOU CONCERNED OVER MY 3)
    ;                   (WHAT ABOUT YOUR OWN 3)
    ;                   :
    ;
    ; Say at this point the keyword YOUR has been found in the user's input text
    ; and we know that in the transformation rule the keyword (YOUR) is followed
    ; by an "=". So we're now going to replace the YOUR in the input text with
    ; the word following the "=" in the transformation rule (MY, in this case).
    ; 
    ; First delete all the 6-character chunks that comprise this word, then
    ; insert all the 6-character chunks that comprise the replacement word. 
    ;
    ; Finally, return the reader, signifying a successful match.
    ;
            DOCBCD  MAD
                EXTERNAL FUNCTION (A,B)                                             000010
                NORMAL MODE IS INTEGER                                              000020
                ENTRY TO FRBCD.                                                     000030
                W'R LNKL.(A) .E. 0, T'O NUMBER                                      000040
                B=A                                                                 000050
                F'N 0                                                               000060
    NUMBER      K=A*262144                                                          000070
                B=BCDIT.(K)                                                         000080
                F'N 0                                                               000090
                E'N                                                                 000100
    
    
  • [Continued

    ; ELIZA entry point.
    ;
            ELIZA   MAD
                NORMAL MODE IS INTEGER                                              000010
                DIMENSION KEY(32),MYTRAN(4)                                         000020
    ;
    ; KEY     - A hashmap used to record keywords.
    ;           KEY(0)..KEY(31)  is the keyword->transformation rule hashmap
    ;           KEY(32)          is the "NONE" transformation rule
    ;
    ; MYTRAN  - A hashmap used to record the MEMORY rules.
    ;           MYTRAN(1)..MYTRAN(4) contain the four MEMORY rules.
    ;
    ; A note on MAD arrays: DIMENSION D(N) allocates N+1 machine-words of
    ; core memory, which are accessed using indexes 0..N.
    ;
                INITAS.(0)                                                          000030
    ;
    ; INITAS must be the first executable statement in any program using SLIP.
    ; Its purpose is to create the List of Available Space from all unused
    ; core memory. It does not require an argument, but here is given 0.
    ;
                PRINT COMMENT $WHICH SCRIPT DO YOU WISH TO PLAY$                    000060
                READ FORMAT SNUMB,SCRIPT                                            000070
    ;
    ; Display the message "WHICH SCRIPT DO YOU WISH TO PLAY".
    ;
    ; Note that the IBM 7090/7094 character set doesn't include a question
    ; mark glyph. Also $ is used to delimit character strings.
    ;
    ; SNUMB is the FORTRAN format string " I3 *", defined previously, which
    ; expects the user to enter up to 3 decimal digits. This number is assigned
    ; to the variable SCRIPT and will be used as the tape drive unit number
    ; where the ELIZA script is expected to reside.
    ;
                LIST.(TEST)                                                         000080
                LIST.(INPUT)                                                        000090
                LIST.(OUTPUT)                                                       000100
                LIST.(JUNK)                                                         000110
    ;
    ; Initialise four lists. These are:
    ; TEST    - Used to store the parts of the user's text matching a
    ;           decomposition rule.
    ; INPUT   - During ELIZA startup the selected script is read into this list,
    ;           one round-bracketed list at a time.
    ;           During the conversation phase the text entered by the user is
    ;           read into this list.
    ; OUTPUT  - ELIZA's response sentence is constructed in this list.
    ; JUNK    - A list used for temporary storage for several different purposes.
    ;
                LIMIT=1                                                             000120
    ;
    ; When Weizenbaum talks in the January 1966 CACM paper of a "certain counting
    ; mechanism", it is this to which he is referring. LIMIT has the value 1..4,
    ; in order, and then restarts at 1. The value changes to the next in the
    ; sequence at each user input. More on LIMIT below.
    ;
                LSSCPY.(THREAD.(INPUT,SCRIPT),JUNK)                                 000130
                MTLIST.(INPUT)                                                      000140
    ;
    ; The THREAD function reads text from the tape unit specified by the integer
    ; SCRIPT into the INPUT list. The LSSCPY function copies the first list in
    ; that INPUT to the list named JUNK.
    ;
    ; The first list in an ELIZA script must be the hello message, e.g.
    ; (HOW DO YOU DO.  PLEASE TELL ME YOUR PROBLEM).)
    ;
                T'H MLST, FOR I=1,1, I .G. 4                                        000150
    MLST        LIST.(MYTRAN(I))                                                    000160
    ;
    ; Initialise each of the four MYTRAN array entries as a new list.
    ;
    ; T'H is an abbreviation for THROUGH
    ; .G. is the Boolean grater than operator
    ;
    ; Set I to 1, if I is greater than 4 stop looping, otherwise execute the code
    ; up to and including the statement labelled MLST. Then add 1 to I and return
    ; to the top of the loop at the point of the test to see if I is greater than
    ; 4 and repeat.
    ;
    ;   for I in 1..4 {
    ;     call function LIST with argument a reference
    ;       to the Ith entry in the MYTRAN array
    ;   }
    ;
                MINE=0                                                              000170
                LIST.(MYLIST)                                                       000180
    ;
    ; MINE    - Set to 0 and is never changed. It's referenced once below. ???
    ; MYLIST  - As memories are made using the MYTRAN MEMORY rules they are
    ;           recorded in MYLIST. Here MYLIST is being initialised as a new
    ;           empty list.
    ;
                T'H KEYLST, FOR I=0,1, I .G. 32                                     000220
    KEYLST      LIST.(KEY(I))                                                       000230
    ;
    ; Initialise each of KEY(0) .. KEY(32) array entries as a new list.
    ;   for I in 0..32 {
    ;     call function LIST with argument a reference
    ;       to the Ith entry in the KEY array
    ;   }
    ;
               R* * * * * * * * * * READ NEW SCRIPT                                 000240
    BEGIN       MTLIST.(INPUT)                                                      000250
                NODLST.(INPUT)                                                      000260
                LISTRD.(INPUT,SCRIPT)                                               000270
    ;
    ; Empty the INPUT list. Remove the description list??? from INPUT (NODLST).
    ; Read the next round-bracket-delimited list from tape unit id SCRIPT.
    ;
                W'R LISTMT.(INPUT) .E. 0                                            000280
                    TXTPRT.(JUNK,0)                                                 000290
                    MTLIST.(JUNK)                                                   000300
                    T'O START                                                       000310
                E'L                                                                 000320
    ;
    ; W'R is an abbreviation of WHENEVER.
    ; .E. means equals.
    ; T'O is an abbreviation for TRANSFER TO.
    ; E'L is an abbreviation of END OF CONDITIONAL.
    ;
    ; An empty list signals the end of the ELIZA script. (Which is presumably
    ; why there is () on the last line of the published DOCTOR script.)
    ;
    ;   if INPUT is the empty list {
    ;     (the whole ELIZA script has now been read and processed)
    ;     print the value of JUNK, e.g. "HOW DO YOU DO.  PLEASE TELL ME YOUR PROBLEM"
    ;     clear the JUNK list
    ;     goto the START label
    ;   } 
    ;
                W'R TOP.(INPUT) .E. $NONE$                                          000330
                    NEWTOP.(LSSCPY.(INPUT,LIST.(9)),KEY(32))                        000340
                    T'O BEGIN                                                       000350
    ;
    ; If this list is the special "NONE" list, just copy it unchanged into KEY(32)
    ; and then goto BEGIN to read the next list in the script.
    ;
    ; Recall that the NONE list in the DOCTOR script is:
    ;       (NONE
    ;           ((0)
    ;               (I AM NOT SURE I UNDERSTAND YOU FULLY)
    ;               (PLEASE GO ON)
    ;               (WHAT DOES THAT SUGGEST TO YOU)
    ;               (DO YOU FEEL STRONGLY ABOUT DISCUSSING SUCH THINGS)))
    ;
                   OR W'R TOP.(INPUT) .E. $MEMORY$                                  000360
                    POPTOP.(INPUT)                                                  000370
                    MEMORY=POPTOP.(INPUT)                                           000380
                    T'H MEM, FOR I=1,1, I .G. 4                                     000390
    MEM             LSSCPY.(POPTOP.(INPUT),MYTRAN(I))                               000400
                    T'O BEGIN                                                       000410
    ;
    ; Otherwise, if this list is the special "MEMORY" list, process it into the
    ; four MYTRAN lists. Recall that the MEMORY list looks like this and is
    ; required to have exactly four transformation patterns:
    ;       (MEMORY MY
    ;           (0 YOUR 0 = LETS DISCUSS FURTHER WHY YOUR 3)
    ;           (0 YOUR 0 = EARLIER YOU SAID YOUR 3)
    ;           (0 YOUR 0 = BUT YOUR 3)
    ;           (0 YOUR 0 = DOES THAT HAVE ANYTHING TO DO WITH THE FACT THAT YOUR 3))
    ;
    ;   else if the first word in INPUT is "MEMORY" {
    ;     assign the memory keyword (e.g. "MY") to the MEMORY variable
    ;     for I in 1..4 {
    ;       copy the Ith MEMORY pattern/reconstruction to MYTRAN(I)
    ;     }
    ;     goto the BEGIN label (continue reading the ELIZA script)
    ;   }
    ;
                   O'E                                                              000420
                    NEWBOT.(LSSCPY.(INPUT,LIST.(9)),KEY(HASH.                       000430
               1    (TOP.(INPUT),5)))                                               000440
                    T'O BEGIN                                                       000450
                E'L                                                                 000460
    ;
    ; Otherwise, the first word in the INPUT list is expected to be a keyword.
    ; Insert this keyword into the KEY hashtable, so that
    ;   KEY(HASH(keyword)) -> list of transformation rules for keywords
    ;                         that hash to this entry in KEY (i.e. more than
    ;                         one keyword may hash to the same entry in KEY,
    ;                         so each entry in KEY may have zero, one or many
    ;                         keyword transformation rules associated with it.)
    ;
    ; (1 in column 11 signifies a continuation of the previous line.)
    ;
    ; The HASH function takes a word and a number (N) and returns a deterministic
    ; value between 0 and (2 to the power N)-1, in this case 0..31.
    ;
    ;   else {
    ;     HASH the keyword and append this transformation rule to the
    ;       entry in KEY with that index
    ;     goto the BEGIN label (continue reading the ELIZA script)
    ;   }
    ;
    ; This is the end of the script reading code. When the script has been
    ; read and processed the script reader explicitly jumps to the START label
    ; to begin the user conversation.
                                                              002290
    
    
  • [cont.]

    ;
               R* * * * * * * * * * BEGIN MAJOR LOOP                                000470
    START       TREAD.(MTLIST.(INPUT),0)                                            000480
    ;
    ; Wait for the user to type a sentence and read it into the INPUT list,
    ; which is first cleared. Presumably, tape unit 0 is the console.
    ;
    ; TREAD is the SLIP system text read function.
    ;
                KEYWRD=0                                                            000490
                PREDNC=0                                                            000500
    ;
    ; KEYWRD  - This will be the keyword found to have the highest precedence.
    ; PREDNC  - The precedence of the keyword. Precedence is specified in the
    ;           ELIZA script. E.g. (DREAMS = DREAM 3 (=DREAM)), the keyword
    ;           DREAMS is given the precedence value 3.
    ;
                LIMIT=LIMIT+1                                                       000510
                W'R LIMIT .E. 5, LIMIT=1                                            000520
    ;
    ; Increment the value of LIMIT. If it then equals 5, set it back to 1.
    ; If we just read the very first user input, LIMIT will now have the value 2.
    ;
                W'R LISTMT.(INPUT) .E. 0, T'O ENDPLA                                000530
    ;
    ; If the user input is a blank line, goto the ENDPLA label.
    ; A blank user input tells ELIZA the conversation is over.
    ;
                IT=0                                                                000540
    ;
    ; IT      - On exit from the scanning loop IT will either be the sequence
    ;           reader for the selected transformation rule, or it will be 0
    ;           indicating that no keyword was detected in the user's INPUT.
    ;
                W'R TOP.(INPUT) .E. $+$                                             000550
                    CHANGE.(KEY,MYTRAN)                                             000560
                    T'O START                                                       000570
                E'L                                                                 000580
    ;
    ; If first word of the user input is a "+" character, call the CHANGE
    ; function defined higher up in this code. This function allows the user
    ; to modify the current ELIZA script with the commands TYPE, SUBST,
    ; APPEND, ADD, START, RANK and DISPLA.
    ; After making any changes, return to the START label and carry on the
    ; conversation.
    ;
                W'R TOP.(INPUT) .E. $*$, T'O NEWLST                                 000590
    ;
    ; If first word of the user input is a "*" character, goto the NEWLST label.
    ; NEWLST is defined later in this code. It inserts a new transformation rule,
    ; which the user will have given after the "*", into the current in-memory
    ; script and then returns to the START label to carry on the conversation.
    ;
                S=SEQRDR.(INPUT)                                                    000600
    ;
    ; Create the Slip sequence reader, S, for the user's INPUT list.
    ;
    NOTYET      W'R S .L. 0                                                         000610
                    SEQLR.(S,F)                                                     000620
                    T'O NOTYET                                                      000630
    ;
    ; ???
    ;
                   O'E                                                              000640
                    WORD=SEQLR.(S,F)                                                000650
                    W'R WORD .E. $.$ .OR. WORD .E. $,$ .OR. WORD .E. $BUT$          000660
                        W'R IT .E. 0                                                000670
                            NULSTL.(INPUT,LSPNTR.(S),JUNK)                          000680
                            MTLIST.(JUNK)                                           000690
                            T'O NOTYET                                              000700
                           O'E                                                      000710
                            NULSTR.(INPUT,LSPNTR.(S),JUNK)                          000720
                            MTLIST.(JUNK)                                           000730
                            T'O ENDTXT                                              000740
                           E'L                                                      000750
                        E'L                                                         000760
                    E'L                                                             000770
    ;
    ; Set the variable WORD to the next word in the user's INPUT list. Then
    ; test that word to see if it's a delimiter.
    ;
    ; Note that in Weizenbaum's 1966 CACM paper, only comma and period were
    ; listed as delimiters. And yet the example conversation given in that
    ; paper could not be reproduced unless BUT is also a delimiter.
    ;
    ; Note that WORD is a 36-bit integer. Weizenbaum developed ELIZA between
    ; 1964 and 1966 on an IBM 7094, which has a 36-bit word and uses a 6-bit
    ; character encoding. Characters were packed 6 to a word. In Slip, character
    ; strings longer than six characters are stored in successive list cells.
    ; In this case WORD=SEQLR.(S,F) is assigning the first six characters of
    ; the next word in the user's INPUT text to the integer variable WORD.
    ; If the word had fewer than six characters they would be left justified
    ; with space characters padding to the right.
    ; 
    ;
    ;   else {
    ;     if WORD is one of the delimiters ".", "," or "BUT" {
    ;       if we have found no keywords in the INPUT so far (IT .E. 0) {
    ;         discard all words in INPUT to the left of, and including, this
    ;           delimiter
    ;         goto NOTYET and continue scanning the rest of the user INPUT
    ;           for keywords
    ;       }
    ;       else {
    ;         discard all words in INPUT to the right of, and including, this
    ;           delimiter
    ;         goto ENDTXT; scanning of the user INPUT is now complete
    ;       }
    ;     }
    ;   }
    ;
                    W'R F .G. 0, T'O ENDTXT                                         000780
    ;
    ; If there were no more words to read in the user INPUT list, goto the
    ; ENDTXT label; scanning of the user INPUT is now complete.
    ; (F will be 1 when the sequence reader has traversed the whole INPUT
    ; list and is back at the list header.)
    ;
                    I=HASH.(WORD,5)                                                 000790
                    SCANER=SEQRDR.(KEY(I))                                          000800
                    SF=0                                                            000810
                    T'H SEARCH, FOR J=0,0, SF .G. 0                                 000820
                    CAND= SEQLR.(SCANER,SF)                                         000830
                    W'R SF .G. 0, T'O NOTYET                                        000840
    SEARCH          W'R TOP.(CAND) .E. WORD, T'O KEYFND                             000850
    ;
    ; Is WORD a keyword? Try to locate it in the KEY hashmap.
    ;
    ; Recall that more than one keyword may hash to the same entry in KEY,
    ; so each entry in KEY is a list that may have zero, one or many keyword
    ; transformation rules associated with it. We need to look through this
    ; list to see if it contains a keyword that exactly matches WORD.
    ;
    ;   HASH the WORD to get the index I in the KEY table where this word
    ;     would have been stored, if it is a keyword
    ;   loop {
    ;     try to read the next candidate list from the hashmap entry KEY(I)
    ;     if there isn't another candidate list {
    ;       WORD didn't match any entries so it's not a keyword
    ;       goto NOTYET to continue scanning the user's input text
    ;     }
    ;     if WORD is the same as the first entry in this candidate list {
    ;       WORD is a keyword and CAND is the transformation rule for
    ;       this keyword, so goto KEYFND
    ;     }
    ;   }
    ;
    KEYFND          READER=TESTS.(CAND,S)                                           000860
                    W'R READER .E. 0, T'O NOTYET                                    000870
    ;
    ; Call the TESTS function, defined higher up in this code.
    ; 
    ; TESTS checks that the whole keyword matches the whole user INPUT word. It
    ; also performs any keyword substitution in the user INPUT. (e.g. (MY = YOUR))
    ;
    ; If TESTS returns 0 it means the keyword is not identical to the word in
    ; the user input, so goto NOTYET to continue scanning the user INPUT.
    ;
    ; [This suggests that keywords must differ in the first six characters.
    ; (Because TESTS is called only for the first keyword candidate in
    ; the KEY hashmap that matches the first six characters of the user's
    ; input word).]
    ;
                    W'R LSTNAM.(CAND) .NE. 0                                        000880
                        DL=LSTNAM.(CAND)                                            000890
    SEQ                 W'R S .L. 0                                                 000900
                            SEQLR.(S,F)                                             000910
                            T'O SEQ                                                 000920
                           O'E                                                      000930
                            NEWTOP.(DL,LSPNTR.(S))                                  000940
                        E'L                                                         000950
                       O'E                                                          000960
                    E'L                                                             000970
    ;
    ; ???
    ;
                    NEXT=SEQLR.(READER,FR)                                          000980
                    W'R FR .G. 0, T'O NOTYET                                        000990
    ;
    ; Read the next element in the rules associated with this keyword.
    ; If we are back at the rules header, the rules list was empty, so goto
    ; NOTYET to continue scanning the user INPUT.
    ;
                    W'R IT .E. 0 .AND. FR .E. 0                                     001000
    PLCKEY              IT=READER                                                   001010
                        KEYWRD=WORD                                                 001020
    ;
    ; 001000 If this is the first keyword we've encountered in the user's INPUT
    ; (IT .E. 0), and the first entry in the associated rules is a list
    ; rather than a value (FR .E. 0)???, i.e. there is no precedence associated
    ; with this keyword, then record the associated rules reader in IT and
    ; the found keyword in KEYWRD. Then goto NOTYET (001100) to continue
    ; scanning the user's input.
    ;
                       OR W'R FR .L. 0 .AND. NEXT .G. PREDNC                        001030
                        PREDNC=NEXT                                                 001040
                        NEXT=SEQLR.(READER,FR)                                      001050
                        T'O PLCKEY                                                  001060
                       0'E                                                          001070
                        T'O NOTYET                                                  001080
                    E'L                                                             001090
                    T'O NOTYET                                                      001100
                   R* * * * * * * * * * END OF MAJOR LOOP                           001110
    ;
    ; 001030 Otherwise, if the first entry in the associated rules is a value???
    ; (FR .L. 0), i.e. the precedence of this keyword, and that value is greater
    ; than the precedence of the previously found highest precedence keyword
    ; (NEXT .G. PREDNC), then record the new highest precedence value in PREDNC
    ; and move the rule reader past the precedence value, then goto PLCKEY to
    ; also record the reader in IT and the found keyword in KEYWRD. Finally, goto
    ; NOTYET (001100) to continue scanning the user's input.
    ;
    ; Note that this differs from Weizenbaum's CACM paper, where it says that
    ; keywords of higher precedence are added to the top of a keyword stack and
    ; keywords of lower precedence are added to the bottom of this stack. This
    ; also means this code does not support the "NEWKEY" functionality he
    ; describes.
    ;
    ; [Note that this code implies that keywords in the script should never
    ; specify a precedence value of 0. If they do they would never be used
    ; (because NEXT .G. PREDNC will never be true).]
    ;
    ; 001080 Otherwise, ignore this keyword and return to NOTYET to continue
    ; scanning the user's INPUT.
    ;
    ENDTXT          W'R IT .E. 0                                                    001120
                        W'R LIMIT .E. 4 .AND. LISTMT.(MYLIST) .NE. 0                001130
                            OUT=POPTOP.(MYLIST)                                     001140
                            TXTPRT.(OUT,0)                                          001150
                            IRALST.(OUT)                                            001160
                            T'O START                                               001170
                           O'E                                                      001180
                            ES=BOT.(TOP.(KEY(32)))                                  001190
                            T'O TRY                                                 001200
                        E'L                                                         001210
    ;
    ; 001120 If IT is 0 it means we did not find any keywords in the user's
    ; input, so we cannot construct a response from the user's input combined
    ; with any of the transformation rules in the script.
    ;
    ; Instead we do one of two things: either print one of the memories we
    ; previously recorded in MYLIST, if any, or we use one of the messages
    ; from the NONE list (which is recorded in KEY(32)).
    ;
    ; 001130 This is the mysterious "when a certain counting mechanism is in a
    ; particular state": recall a memory only if the memory list (MYLIST) isn't
    ; empty and LIMIT happens to have the value 4.
    ;
                       OR W'R KEYWRD .E. MEMORY                                     001220
                        I=HASH.(BOT.(INPUT),2)+1                                    001230
                        NEWBOT.(REGEL.(MYTRAN(I),INPUT,LIST.(MINE)),MYLIST)         001240
                        SEQLL.(IT,FR)                                               001250
                        T'O MATCH                                                   001260
    ;
    ; Otherwise, we did find a keyword (IT .E. 0 is false). If the keyword is
    ; the MEMORY keyword ("MY" in the DOCTOR script), then add a new memory to
    ; MYLIST before we carry on processing the transformation rules associated
    ; with the matched keyword.
    ;
    ; In the 1966 CACM paper, Weizenbaum says the selection of one of the
    ; transformations on the MEMORY list is random. The code shows that the
    ; selection is determined by the HASH value of the last word in the user's
    ; input. This means ELIZA conversations are repeatable, not random. If we
    ; have the HASH algorithm we should be able to reproduce the exact
    ; conversation. (The HASH function is part of the SLIP system.)
    ;
                       O'E                                                          001270
                        SEQLL.(IT,FR)                                               001280
    ;
    ; Otherwise, the keyword we found isn't the MEMORY keyword, so just position
    ; the transformation rule sequence reader past the keyword and fall through
    ; to the matching code.
    ;
                   R* * * * * * * * * * MATCHING ROUTINE                            001290
    MATCH               ES=SEQLR.(IT,FR)                                            001300
                        W'R TOP.(ES) .E. $=$                                        001310
                            S=SEQRDR.(ES)                                           001320
                            SEQLR.(S,F)                                             001330
                            WORD=SEQLR.(S,F)                                        001340
                            I=HASH.(WORD,5)                                         001350
                            SCANER=SEQRDR.(KEY(I))                                  001360
    SCAN                    ITS=SEQLR.(SCANER,F)                                    001370
                            W'R F .G. 0, T'O NOMATCH(LIMIT)                         001380
                            W'R WORD .E. TOP.(ITS)                                  001390
                                S=SEQRDR.(ITS)                                      001400
    SCANI                       ES=SEQLR.(S,F)                                      001410
                                W'R F .NE.0, T'O SCANI                              001420
                                IT=S                                                001430
                                T'O TRY                                             001440
                            O'E                                                     001450
                                T'O SCAN                                            001460
                            E'L                                                     001470
                        E'L                                                         001480
                        W'R FR .G. 0, T'O NOMATCH(LIMIT)                            001490
    ;
    ; If this keyword is a link to another keyword, switch to that keyword.
    ;
    ; An ELIZA script rule may have the form (HOW (=WHAT)). If the keyword
    ; HOW appears in the user's input and this transformation rule is selected,
    ; ELIZA will use the transformation rule associated with the keyword WHAT
    ; to generate its response.
    ;
    ;   read the next decomposition rule from the selected transformation rule
    ;   if the decomposition rule starts with an "=" symbol {
    ;     assign the word after the "=" to WORD
    ;     lookup WORD in the KEY hashmap
    ;     if WORD doesn't exist in the KEY hashmap {
    ;       (presumably this indicates a logical inconsistency in the script)
    ;       goto one of the NOMATCH(1) .. NOMATCH(4) labels to print
    ;         a message such as "HMMM" and back to the main conversation loop
    ;       which NOMATCH label is selected is determined by the value LIMIT
    ;         happens to have at this time
    ;     }
    ;     else {
    ;       position IT at first decomposition rule for the linked keyword
    ;       goto the TRY label to try to apply the decomposition rule
    ;     }
    ;   }
    ;   else if there were no (or no more) decomposition rules (FR .G. 0) {
    ;     (does this indicate an incorrectly formed script?)
    ;     goto one of the NOMATCH(1) .. NOMATCH(4) labels
    ;   }
    ;
    TRY                 W'R YMATCH.(TOP.(ES),INPUT,MTLIST.(TEST)) .E. 0,T'O MATCH   001500
    ;
    ; Attempt to match the current decomposition rule (TOP.(ES)) to the user's
    ; INPUT.
    ;
    ; If it doesn't match (YMATCH returns 0), goto MATCH to try the next
    ; decomposition rule in the current transformation rule set.
    ;
    ; If it does match, the list TEST will contain the decomposed matching parts
    ; of the INPUT text ready for reassembly. E.g. ???
    ;
    ; The YMATCH function is part of the SLIP system.
    ;
                        ESRDR=SEQRDR.(ES)                                           001510
                        SEQLR.(ESRDR,ESF)                                           001520
                        POINT=SEQLR.(ESRDR,ESF)                                     001530
                        POINTR=LSPNTR.(ESRDR)                                       001540
                        W'R ESF .E. 0                                               001550
                            NEWBOT.(1,POINTR)                                       001560
                            TRANS=POINT                                             001570
                            T'O HIT                                                 001580
                           O'E                                                      001590
                            T'H FNDHIT,FOR I=0,1, I .G. POINT                       001600
    FNDHIT                  TRANS=SEQLR.(ESRDR,ESF)                                 001610
                            W'R ESF .G. 0                                           001620
                                SEQLR.(ESRDR,ESF)                                   001630
                                SEQLR.(ESRDR,ESF)                                   001640
                                TRANS=SEQLR.(ESRDR,ESF)                             001650
                                SUBST.(1,POINTR)                                    001660
                                T'O HIT                                             001670
                               0'E                                                  001680
                                SUBST.(POINT+1,POINTR)                              001690
                                T'O HIT                                             001700
                            E'L                                                     001710
                        E'L                                                         001720
    ;
    ; Select one of the reassembly rules associated with this decomposition rule.
    ;
    ; Reassembly rules are used in turn. This code adds a counter (001560) to
    ; the rules and uses it to record which reassembly rule was used last (001690).
    ; When all reassembly rules have been used (001620) the counter is returned
    ; to 1 (001660) and the first rule is used again.
    ;
    HIT                 TXTPRT.(ASSMBL.(TRANS,TEST,MTLIST.(OUTPUT)),0)              001730
                        T'O START                                                   001740
                    E'L                                                             001750
    ;
    ; Finally, use the selected reassembly rule (TRANS) and list of decomposition
    ; parts (TEST) to assemble a response (in the list OUTPUT) and print it. Then
    ; goto the START label to await the next user input and continue the
    ; conversation.
    ;
    ; The ASSMBL function is part of the SLIP system.
    ;
    ; The E'L (END OF CONDITIONAL) on line 001750 closes the O'E (OTHERWISE)
    ; on line 001270. ???
    ;
                   R* * * * * * * * * * INSERT NEW KEYWORD LIST                     001760
    NEWLST          POPTOP.(INPUT)                                                  001770
                    NEWBOT.(LSSCPY.(INPUT,LIST.(9)),KEY(HASH.                       001780
                   1(TOP.(INPUT),5)))                                               001790
                    T'O START                                                       001800
                   R* * * * * * * * * * DUMP REVISED SCRIPT                         001810
    ENDPLA          PRINT COMMENT $WHAT IS TO BE THE NUMBER OF THE NEW SCRIPT$      001820
                    READ FORMAT SNUMB,SCRIPT                                        001830
                    LPRINT.(INPUT,SCRIPT)                                           001840
                    NEWTOP.(MEMORY,MTLIST.(OUTPUT))                                 001850
                    NEWTOP.($MEMORY$,OUTPUT)                                        001860
                    T'H DUMP, FOR I=1,1 I .G. 4                                     001870
    DUMP            NEWBOT.(MYTRAN(I),OUTPUT)                                       001880
                    LPRINT.(OUTPUT,SCRIPT)                                          001890
                    MTLIST.(OUTPUT)                                                 001900
                    T'H WRITE, FOR I=0,1, I .G. 32                                  001910
    POPMOR          W'R LISTMT.(KEY(I)) .E. 0, T'O WRITE                            001920
                    LPRINT.(POPTOP.(KEY(I)),SCRIPT)                                 001930
                    T'O POPMOR                                                      001940
    WRITE           CONTINUE                                                        001950
                    LPRINT.(MTLIST.(INPUT),SCRIPT)                                  001960
                    EXIT.                                                           001970
                   R* * * * * * * * * * SCRIPT ERROR EXIT                           001980
    NOMATCH(1)      PRINT COMMENT $PLEASE CONTINUE $                                002200
                    T'O START                                                       002210
    NOMATCH(2)      PRINT COMMENT $HMMM $                                           002220
                    T'O START                                                       002230
    NOMATCH(3)      PRINT COMMENT $GO ON , PLEASE $                                 002240
                    T'O START                                                       002250
    NOMATCH(4)      PRINT COMMENT $I SEE $                                          002260
                    T'O START                                                       002270
                    VECTOR VALUES SNUMB= $I3 * $                                    002280
                    E'M   
    
  • I think it's also useful to look at our project website: http://findingeliza.org. Click on "code" to see a slightly nicer formatting for the code and also you can try out a version of ELIZA.

  • This isn't an analysis of the code exactly, but one very interesting development in the history of Eliza happened ten years ago, nearly fifty years after ELIZA was released. Very, very few programs have had such enduring legacy.

    In 2014, @ElizaRBarr was created. This twitter bot, as you may have noticed from the name, was programmed to use ELIZA to come up with responses to tweets. But the novel application here was as a honeypot. You see, GamerGate was going on, which was largely a harassment campaign against several folks who were trying to bring feminist (and other) critiques against video games. One way in which this campaign played out was in endless arguments on Twitter. So, someone (I don't believe we ever found out who) decided that @ElizaRBarr would reply to people using the #gamergate hashtag. In this fashion, it was like a DDoS against the time and attention span of the harassers; every minute they'd talk to the bot would be a minute they would not be harassing a human.

    @ElizaRBarr was very successful in this endeavor, with some people engaging with it for hundreds of replies before realizing they'd been duped.

    I am wondering when ELIZA is going to pop up again.

  • Eliza has an enduring legacy; if gives the appearance of participating in a dialog, and it is fairly simple to code.

    The fascination lies in that people with no apparent effort, get 'trapped' into a dialog with a person, the Eliza Effect, and then pass this fascination on to others. The dialog becomes a game in which users communicate with others about their interactions. I wonder if the interaction is self-modifying. Whether users consciously avoid forcing Eliza into seeming to be a machine rather than a person. whether their is an avoidance of sentences and phrases which force the machine to act as a machine. This might be an interesting area to investigate.

    The other audience are the software developers who in their turn may be fascinated at both the dialog (with a 'person') and the simplicity of the code. A thought that they could create a 'person' simply. And the prospect of causing themselves and others to be fascinated at the end result.

  • Probably off topic: I asked Le Chat "Can I give you some computer code and you can explain what it does? I want a highly detailed explanation of each line" and then gave it this fragment of code from the SLIP library used by Weizenbaum for ELIZA:

            PARTN   MAD
               EXTERNAL FUNCTION(SLST,PART,SIGNAL)
               NORMAL MODE IS INTEGER
               ENTRY TO PARTN.
               TAG=SIGNAL
               COUNT=0
               READER=SEQRDR.(SLST)
    READ       COUNT=COUNT+1
               DATUM=SEQLR.(READER,FLAG)
               W'R FLAG .G. 0, T'O DONE
               W'R LNKL.(DATUM) .E. 0
               PART(COUNT) = DATUM
               T'O READ
               O'E
               W'R NAMLST.(DATUM) .NE. 0, T'O PLAIN
               W'R TOP.(DATUM) .NE. TAG, T'O PLAIN
               COUNT=COUNT-1
               LSSCPY.(DATUM,LIST.(IT))
               POPTOP.(IT)
               MAKEDL.(IT,PART(COUNT))
               IRALST.(IT)
               T'O READ
    PLAIN      NEWBOT.(DATUM,LIST.(PART(COUNT)))
    ATTCH      W'R READER .GE. 0, T'O READ
               LNKBOT.(SEQLR.(READER,FLAG),PART(COUNT))
               T'O ATTCH
               E'L
    DONE       COUNT=COUNT-1
               PART(0)=COUNT
               F'N COUNT
               E'N
    

    and this is what it gave me:

    This code appears to be written in MAD (Michigan Algorithm Decoder), which is an old programming language used mainly for list processing on IBM mainframe systems. I'll provide a detailed explanation of each line:

    1. PARTN - This is the name of the MAD program (PARTition Nodes).
    2. MAD - This indicates that the code is written in the MAD programming language.
    3. EXTERNAL FUNCTION(SLST,PART,SIGNAL) - This line declares an external function with three parameters: SLST (a list), PART (an array), and SIGNAL (a value used as a tag).
    4. NORMAL MODE IS INTEGER - This line sets the normal mode for the program to be integer, which means that the program will primarily work with integer values.
    5. ENTRY TO PARTN. - This line defines the entry point for the program, which is PARTN.
    6. TAG=SIGNAL - This line assigns the value of the SIGNAL parameter to the variable TAG.
    7. COUNT=0 - This line initializes the variable COUNT to 0.
    8. READER=SEQRDR.(SLST) - This line initializes the variable READER with the value returned by the SEQRDR function, which takes the SLST parameter as input. SEQRDR likely returns a sequential reader for the list.
    9. READ - This is a label used for branching within the program.
    10. COUNT=COUNT+1 - This line increments the value of the COUNT variable by 1.
    11. DATUM=SEQLR.(READER,FLAG) - This line assigns the value returned by the SEQLR function to the variable DATUM. SEQLR likely reads an item from the list using the READER and stores the result in DATUM. The FLAG variable is used to indicate the status of the read operation.
    12. W'R FLAG .G. 0, T'O DONE - This line checks if the FLAG variable is greater than 0. If it is, the program branches to the DONE label.
    13. W'R LNKL.(DATUM) .E. 0 - This line checks if the left link of the DATUM is equal to 0. If it is, the program continues to the next line.
    14. PART(COUNT) = DATUM - This line assigns the DATUM value to the COUNT-th element of the PART array.
    15. T'O READ - This line branches to the READ label, creating a loop that continues reading and processing items from the list.
    16. O'E - This is the "otherwise" clause for the previous conditional statements, executed if none of the previous conditions were met.
    17. W'R NAMLST.(DATUM) .NE. 0, T'O PLAIN - This line checks if the NAMLST value associated with the DATUM is not equal to 0. If it is not equal to 0, the program branches to the PLAIN label.
    18. W'R TOP.(DATUM) .NE. TAG, T'O PLAIN - This line checks if the TOP value associated with the DATUM is not equal to the TAG. If it is not equal to the TAG, the program branches to the PLAIN label.
    19. COUNT=COUNT-1 - This line decrements the value of the COUNT variable by 1.
    20. LSSCPY.(DATUM,LIST.(IT)) - This line copies the contents of the DATUM to a new list item at the index specified by the IT variable.
    21. POPTOP.(IT) - This line removes the top item from the list specified by the IT variable.
    22. MAKEDL.(IT,PART(COUNT)) - This line creates a doubly-linked list with the IT variable as the first item and the COUNT-th element of the PART array as the second item.
    23. IRALST.(IT) - This line inserts the list specified by the IT variable into the main list.
    24. T'O READ - This line branches to the READ label, continuing the loop.
    25. PLAIN - This is a label used for branching within the program.
    26. NEWBOT.(DATUM,LIST.(PART(COUNT))) - This line creates a new bottom item for the list specified by the DATUM and links it to the list item specified by the COUNT-th element of the PART array.
    27. ATTCH - This is a label used for branching within the program.
    28. W'R READER .GE. 0, T'O READ - This line checks if the READER variable is greater than or equal to 0. If it is, the program branches to the READ label.
    29. LNKBOT.(SEQLR.(READER,FLAG),PART(COUNT)) - This line links the bottom item of the list specified by the READER to the COUNT-th element of the PART array.
    30. T'O ATTCH - This line branches to the ATTCH label, creating a loop that continues linking items in the list.
    31. E'L - This is the "end loop" statement, which terminates the loop.
    32. DONE - This is a label used for branching within the program.
    33. COUNT=COUNT-1 - This line decrements the value of the COUNT variable by 1.
    34. PART(0)=COUNT - This line assigns the value of the COUNT variable to the first element of the PART array.
    35. F'N COUNT - This line returns the value of the COUNT variable as the result of the function.
    36. E'N - This is the "end" statement, which signifies the end of the program.

    This MAD program appears to process a list, partitioning its nodes based on certain conditions and storing the results in the PART array. The specific functionality may depend on the exact implementation of the list and the associated functions used in the code.

    --

    It's really not bad. I think most statements are correct, but 23 is wrong: IRALST deletes the list IT. I asked it to give a high level summary of the function and it was pretty impressive, saying in part:

    In summary, the PARTN function partitions a given linked list into multiple sublists based on specific conditions and stores the resulting sublists in an array. The input parameters include the linked list to be partitioned, an array to store the partitioned sublists, and a tag value used for comparison during the partitioning process.

  • Please do take a look at our project website for more information about our work on ELIZA findingeliza.org

Sign In or Register to comment.