/*   Simple ELIZA
     -- a natural language misunderstander --
     Alan Bundy 15-Nov-79, Richard O'Keefe 17-Feb-81
     Peter Ross 5-Nov-81
*/

:-(['ecmi25.util_readin']).       % load read_in + necessary support.

/* The top level: call liza (so named 'cos it's a mini-version of ELIZA)
   to get going.
   The predicate read_in reads in sentences, currently ending with a
   full stop, exclamation mark or question mark. Thus
         read_in(X)
   will read in
         hello there.
   as
         X = [hello,there,.]
   NOTE: use lower-case letters at the front of words, this is a simple
   beast!
*/

liza :-
        read_in(Input),
        make_swaps(Input, Clean),
        Clean \== [bye,.],
        rule(Given, Yield),
        match(Given, Clean),
        reply(Yield), nl, !,
        liza.
liza :-
        write('I hope I have helped you.'), nl.

/* How it works: imagine typing in "do you like me?".
   The read_in sets
         Input = [do,you,like,me,?]
   then make_swaps(Input,Clean) sets
         Clean = [do,I,like,you,.]
   (note the question mark vanished, 'cos make_swaps([?],Rest_of_yield)
    matched make_swaps([Period],[.]) ).
   Then rule(Given,Yield) will come up with
         Given = [you,are,X,.]
         Yield = [how,long,have,you,been,X,?]
   and match(Given,Clean) will fail (see below), backtracking to
   rule(Given,Yield) which comes up with
         Given = [X,i,Y,you,.]
         Yield = [what,makes,you,think,i,Y,you,?]
   whereupon match(Given,Clean) can now succeed, in the process
   instantiating X to 'do' and Y to 'like', so that Yield is now
   instantiated to [what,makes,you,think,i,like,you,?] . The predicate
   reply prints this out....

   Exercise: follow through the input "i am fed up."
   Exercise 2: what are the cuts in make_swaps, match and append for?
   Exercise 3: copy this file into one of your own, and extend the range
               of responses it can make.

*/

make_swaps(Given, Yield) :-
        swap(Phrase, Translation),
        append(Phrase, Rest_of_Given, Given),
        append(Translation, Rest_of_Yield, Yield), !,
        make_swaps(Rest_of_Given, Rest_of_Yield).
make_swaps([Period], [.]) :- !.
make_swaps([Word|Rest_of_Given], [Word|Rest_of_Yield]) :- 
        !,
        make_swaps(Rest_of_Given, Rest_of_Yield).

swap([i],      [you]).
swap([me],     [you]).
swap([we],     [you]).
swap([us],     [you]).
swap([you],    [i]).
swap([my],     [your]).
swap([mine],   [yours]).
swap([our],    [your]).
swap([ours],   [yours]).
swap([your],   [my]).
swap([yours],  [mine]).
swap([am],     [are]).
swap([you,are],[i,am]).
swap([stop],   [bye]).
swap([quit],   [bye]).
swap([goodbye],[bye]).
swap([please], []).

match([Head|Rest], Fragment) :-
        append(Head, Leftover, Fragment),
        match(Rest, Leftover).
match([Head|Rest], [Head|Leftover]) :- !,
        match(Rest, Leftover).
match([], []).

append([], List, List).
append([Head|Tail], List, [Head|Rest]) :- !,
        append(Tail, List, Rest).

reply([Head|Tail]) :-
        reply(Head), !,
        reply(Tail).
reply([]).
reply(Proper_Word) :-
        tab(1),
        write(Proper_Word).

rule([you,are,X,.],     [how,long,have,you,been,X,?]).
rule([X,i,Y,you,.],     [what,makes,you,think,i,Y,you,?]).
rule([you,like,Y,.],    [does,anyone,else,in,your,family,like,Y,?]).
rule([you,feel,X,.],    [do,you,often,feel,that,way,?]).
rule([X],               [please,go,on,.]).