/*****************************************************************************/ /* ELIZA in Prolog */ /* */ /* Viren Patel */ /* Artificial Intelligence Programs */ /* University of Georgia, Athens, Georgia */ /* Email: vpatel@aisun1.ai.uga.edu */ /* */ /* minor changes by Frank Schilder (FS) */ /* Email: schilder@informatik.uni-hamburg.de */ /* Reference */ /* */ /* Weizenbaum, J., (1966) ELIZA - A computer program for the study of */ /* natural language communication between man and machine. Communications */ /* of the ACM, 9.1:36-45. */ /* */ /* Acknowledgments */ /* */ /* read_atomics/1 and suporting clauses are courtesy of Dr. Michael A. */ /* Covington, AI Programs, University of Georgia, Athens, Georgia from */ /* his forthcoming book, Natural language processing for Prolog */ /* programmers. */ /* */ /* match/2 and its supporting clauses make up the pattern matcher. The */ /* basic code for the pattern matcher was obtained from the book by */ /* R. A. O'Keefe, The craft of Prolog. */ /* */ /* Requires: Quintus Prolog */ /* changed version runs on SWI-PROLOG */ /* */ /* To run: ?- consult(eliza). */ /* To stop: > quit (`>' is the Eliza prompt) */ /* */ /* Last Revised: April 10, 1992 */ /* */ /*****************************************************************************/ /*****************************************************************************/ % simplification rules sr([do,not|X],[dont|Y],X,Y). sr([can,not|X],[cant|Y],X,Y). sr([cannot|X],[cant|Y],X,Y). sr([will,not|X],[wont|Y],X,Y). sr([dreamed|X],[dreamt|Y],X,Y). sr([dreams|X],[dream|Y],X,Y). sr([how|X],[what|Y],X,Y). sr([when|X],[what|Y],X,Y). sr([alike|X],[dit|Y],X,Y). sr([same|X],[dit|Y],X,Y). sr([certainly|X],[yes|Y],X,Y). sr([maybe|X],[perhaps|Y],X,Y). sr([deutsch|X],[xfremd|Y],X,Y). sr([francais|X],[xfremd|Y],X,Y). sr([espanol|X],[xfremd|Y],X,Y). sr([machine|X],[computer|Y],X,Y). sr([machines|X],[computer|Y],X,Y). sr([computers|X],[computer|Y],X,Y). sr([am|X],[are|Y],X,Y). sr([your|X],[my|Y],X,Y). sr([were|X],[was|Y],X,Y). sr([me|X],[you|Y],X,Y). sr([you,are|X],[im|Y],X,Y). % im = i'm = i am sr([i,am|X],[youre|Y],X,Y). % youre = you're = you are =\= your sr([myself|X],[yourself|Y],X,Y). sr([yourself|X],[myself|Y],X,Y). sr([mom|X],[mother|Y],X,Y). sr([dad|X],[father|Y],X,Y). sr([i|X],[you|Y],X,Y). sr([you|X],[i|Y],X,Y). sr([my|X],[your|Y],X,Y). sr([everybody|X],[everyone|Y],X,Y). sr([nobody|X],[everyone|Y],X,Y). /*****************************************************************************/ % Make the rule base modifiable % this is specific to Quintus Prolog :- dynamic(rules/1). /*****************************************************************************/ % The rule base % The format of the rules is: % % rules([[keyword, importance of keyword],[ % [pattern #, [the pattern], last response used, % [response 1], % [response 2], % ... % [response n]]]]). rules([[sorry,0],[ [1,[_],0, [please,do,not,apologize,.], [apologies,are,not,necessary,.], [what,feelings,do,you,have,when,you,apologize,?], ['I',have,told,you,that,apologies,are,not,required,.]]]]). rules([[remember,5],[ [1,[_,you,remember,Y],0, [do,you,often,think,of,Y,?], [does,thinking,of,Y,bring,anything,else,to,mind,?], [what,else,do,you,remember,?], [why,do,you,remember,Y,just,now,?], [what,in,the,present,situation,reminds,you,of,Y,?], [what,is,the,connection,between,me,and,Y,?]], [2,[_,do,i,remember,Y],0, [did,you,think,'I',would,forget,Y,?], [why,do,you,think,i,should,recall,Y,now,?], [what,about,Y,?], [equal,[what,0]], [you,mentioned,Y,.]], [3,[_],0, [newkey]]]]). rules([[if,3],[ [1,[_,if,Y],0, [do,you,think,it,is,likely,that,Y,?], [do,you,wish,that,Y,?], [what,do,you,think,about,Y,?], [really,',',if,Y,?]]]]). rules([[dreamt,4],[ [1,[_,you,dreamt,Y],0, [really,',',Y,?], [have,you,ever,fantasied,Y,while,you,were,awake,?], [have,you,dreamt,Y,before,?], [equal,[dream,3]], [newkey]]]]). rules([[dream,3],[ [1,[_],0, [what,does,that,dream,suggest,to,you,?], [do,you,dream,often,?], [what,persons,appear,in,your,dreams,?], [do,you,believe,that,dreaming,has,something,to,do,with,your,problem,?], [newkey]]]]). rules([[none,0],[ [1,[_],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,?]]]]). rules([[perhaps,0],[ [1,[_],0, [you,do,not,seem,quite,certain,.], [why,the,uncertain,tone,?], [can,you,not,be,more,positive,?], [you,are,not,sure,?], [do,you,not,know,?]]]]). rules([[name,15],[ [1,[_],0, ['I',am,not,interested,in,names,.], ['I',have,told,you,before,',','I',do,not,care,about,names,.], [please,continue,.]]]]). rules([[xfremd,75],[ [1,[_],0, ['I',am,sorry,',','I',only,speak,'English',.]]]]). rules([[hello,0],[ [1,[_],0, [how,do,you,do,'.','Please',state,your,problem,.]]]]). rules([[computer,50],[ [1,[_],0, [do,computers,worry,you,?], [why,do,you,mention,computers,?], [what,do,you,think,machines,have,to,do,with,your,problem,?], [do,you,not,think,computers,can,help,people,?], [what,about,machines,worries,you,?], [what,do,you,think,about,machines,?]]]]). rules([[are,0],[ [1,[_,are,you,Y],0, [do,you,believe,you,are,Y,?], [would,you,want,to,be,Y,?], [you,wish,'I',would,tell,you,you,are,Y,?], [what,would,it,mean,if,you,were,Y,?], [equal,[what,0]]], [2,[_,are,i,Y],0, [why,are,you,interested,in,whether,'I',am,Y,or,not,?], [would,you,prefer,if,'I',were,not,Y,?], [perhaps,'I',am,Y,in,your,fantasies,.], [do,you,sometimes,think,'I',am,Y,?], [equal,[what,0]]], [3,[_,are,Y],0, [did,you,think,they,might,not,be,Y,?], [would,you,like,it,if,they,were,not,Y,?], [what,if,they,were,not,Y,?], [possibly,they,are,Y,.]], [4,[_],0, [why,do,you,say,am,?], ['I',do,not,understand,that,.]]]]). rules([[my,0],[ [1,[_,my,Y],0, [why,are,you,concerned,over,my,Y,?], [what,about,your,own,Y,?], [are,you,worried,about,someone,elses,Y,?], [really,',',my,Y,?]]]]). rules([[was,2],[ [1,[_,was,you,Y],0, [what,if,you,were,Y,?], [do,you,think,you,were,Y,?], [were,you,Y,?], [what,would,it,mean,if,you,were,Y,?], [what,does,Y,suggest,to,you,?], [equal,[what,0]]], [2,[_,you,was,Y],0, [were,you,really,?], [why,do,you,tell,me,you,were,Y,just,now,?], [perhaps,'I',already,knew,you,were,Y,.]], [3,[_,was,i,Y],0, [would,you,like,to,believe,'I',was,Y,?], [what,suggests,that,'I',was,Y,?], [what,do,you,think,?], [perhaps,'I',was,Y,.], [what,if,'I',had,been,Y,?]], [4,[_],0, [newkey]]]]). rules([[im,0],[ [1,[_,im,_],0, [equal,[i,0]]]]]). rules([[youre,0],[ [1,[_,youre,_],0, [equal,[you,0]]]]]). rules([[you,0],[ [1,[_,you,cant,Y],0, [how,do,you,know,you,can,not,Y,?], [have,you,tried,?], [perhaps,you,could,Y,now,?], [do,you,really,want,to,be,able,to,Y,?]], [2,[_,you,dont,Y],0, [do,you,not,really,Y,?], [why,do,you,not,Y,?], [do,you,wish,to,be,able,to,Y,?], [does,that,trouble,you,?]], [3,[_,you,feel,Y],0, [tell,me,more,about,such,feelings,.], [do,you,often,feel,Y,?], [do,you,enjoy,feeling,Y,?], [of,what,does,feeling,Y,remind,you,?]], [4,[_,you,was,_],0, [equal,[was,2]]], [5,[_,you,Y,i,_],0, [perhaps,in,your,fantasy,we,Y,each,other,?], [do,you,wish,to,Y,me,?], [you,seem,to,need,to,Y,me,.], [do,you,Y,anyone,else,?]], [6,[_,you,[*,want,need,_],Y],0, [what,would,it,mean,to,you,if,you,got,Y,?], [why,do,you,want,Y,?], [suppose,you,got,Y,soon,?], [what,if,you,never,got,Y,?], [what,would,getting,Y,mean,to,you,?], [what,does,wanting,Y,have,to,do,with,this,discussion,?]], [7,[_,you,[*,feel,think,believe,wish,_],you,Y],0, [do,you,really,think,so,?], [but,you,are,not,sure,you,Y,?], [do,you,really,doubt,you,Y,?]], [8,[_,you,_,[*,feel,think,believe,wish,_],_,i,_],0, [equal,[you,0]]], [9,[_,youre,_,[*,sad,unhappy,depressed,sick,M],_],0, ['I',am,sorry,to,hear,you,are,M,.], [do,you,think,coming,here,will,help,you,not,to,be,M,?], ['I',am,sure,it,is,not,pleasant,to,be,M,.], [can,you,explain,what,made,you,M,?]], [10,[_,youre,_,[*,happy,elated,glad,better,M],_],0, [how,have,'I',helped,you,to,be,M,?], [has,your,treatment,made,you,M,?], [what,makes,you,M,just,now,?], [can,you,explain,why,you,are,suddenly,M,?]], [11,[_,youre,Y],0, [is,it,because,you,are,Y,that,you,came,to,me,?], [how,long,have,you,been,Y,?], [do,you,believe,it,normal,to,be,Y,?], [do,you,enjoy,being,Y,?]], [12,[X],0, [you,say,X], [can,you,elaborate,on,that,?], [do,you,say,X,for,some,special,reason,?], [that,is,quite,interesting,.]]]]). rules([[i,0],[ [1,[_,i,remind,you,of,_],0, [equal,[dit,10]]], [2,[_,im,Y],0, [what,makes,you,think,'I',am,Y,?], [does,it,please,you,to,believe,'I',am,Y,?], [do,you,sometimes,wish,you,were,Y,?], [perhaps,you,would,like,to,be,Y,?]], [3,[_,i,Y,you],0, [why,do,you,think,'I',Y,you,?], [you,like,to,think,'I',Y,you,',',do,you,not,?], [what,makes,you,think,'I',Y,you,?], [really,',','I',Y,you,.], [do,you,wish,to,believe,'I',Y,you,?], [suppose,'I',did,Y,you,',',what,would,that,mean,to,you,?], [does,someone,else,believe,'I',Y,you,?]], [4,[_,i,Y],0, [we,were,discussing,you,',',not,me,.], [oh,',',i,Y,.], [you,are,not,really,talking,about,me,',',are,you,?], [what,are,your,feelings,now,?]]]]). rules([[yes,0],[ [1,[_],0, [you,seem,quite,positive,.], [you,are,sure,?], [i,see,.], [i,understand,.]]]]). rules([[no,0],[ [1,[_],0, [are,you,saying,no,just,to,be,negative,?], [you,are,being,a,bit,negative,.], [why,not,?], [why,no,?]]]]). rules([[your,2],[ [1,[_,your,_,[*,mother,father,brother,sister,children,wife,M],Z],0, [tell,me,more,about,your,family,.], [who,else,in,your,family,Z,?], [your,M,?], [what,else,comes,to,mind,when,you,think,of,your,M,?]], [2,[_,your,Y],0, [your,Y,?], [why,do,you,say,your,Y,?], [does,that,suggest,anything,else,which,belongs,to,you,?], [is,it,important,to,you,that,your,Y,?]]]]). rules([[memory,0],[ [1,[_,your,Y],0, [lets,discuss,further,why,your,Y,.], [earlier,you,said,your,Y,.], [but,your,Y,?], [does,that,have,anything,to,do,with,the,fact,that,your,Y,?]]]]). rules([[can,0],[ [1,[_,can,i,Y],0, [you,believe,'I',can,Y,',',do,you,not,?], [equal,[what,0]], [you,want,me,to,be,able,to,Y,?], [perhaps,you,would,like,to,be,able,to,Y,yourself,?]], [2,[_,can,you,Y],0, [whether,or,not,you,can,Y,depends,on,you,more,than,on,me,.], [do,you,want,to,be,able,to,Y,?], [perhaps,you,do,not,want,to,Y,.], [equal,[what,0]]]]]). rules([[what,0],[ [1,[_],0, [why,do,you,ask,?], [does,that,question,interest,you,?], [what,is,it,you,really,want,to,know,?], [are,such,questions,much,on,your,mind,?], [what,answer,would,please,you,most,?], [what,do,you,think,?], [what,comes,to,your,mind,when,you,ask,that,?], [have,you,asked,such,questions,before,?], [have,you,asked,anyone,else,?]]]]). rules([[because,0],[ [1,[_],0, [is,that,the,real,reason,?], [do,any,other,reasons,not,come,to,mind,?], [does,that,reason,seem,to,explain,anything,else,?], [what,other,reasons,might,there,be,?]]]]). rules([[why,0],[ [1,[_,why,dont,i,Y],0, [do,you,believe,'I',do,not,Y,?], [perhaps,'I',will,Y,in,good,time,.], [should,you,Y,yourself,?], [you,want,me,to,Y,?], [equal,[what,0]]], [2,[_,why,cant,you,Y],0, [do,you,think,you,should,be,able,to,Y,?], [do,you,want,to,be,able,to,Y,?], [do,you,believe,this,will,help,you,to,Y,?], [have,you,any,idea,why,you,can,not,Y,?], [equal,[what,0]]]]]). rules([[everyone,2],[ [1,[_,[*,everyone,everybody,nobody,noone,M],_],0, [really,',',M,?], [surely,not,M,?], [can,you,think,of,anyone,in,particular,?], [who,',',for,example,?], [you,are,thinking,of,a,very,special,person,?], [who,',',may,i,ask,?], [someone,special,perhaps,?], [you,have,a,paticular,person,in,mind,',',do,you,not,?], [who,do,you,think,you,are,talking,about,?]]]]). rules([[always,1],[ [1,[_],0, [can,you,think,of,a,specific,example,?], [when,?], [what,incident,are,you,thinking,of,?], [really,',',always,?]]]]). rules([[like,10],[ [1,[_,[*,im,youre,am,is,are,was,_],_,like,_],0, [equal,[dit,10]]], [2,[_],0, [newkey]]]]). rules([[dit,10],[ [1,[_],0, [in,what,way,?], [what,resemblance,do,you,see,?], [what,does,that,similarity,suggest,to,you,?], [what,other,connections,do,you,see,?], [what,so,you,suppose,that,resemblance,means,?], [what,is,the,connection,',',do,you,suppose,?], [could,there,really,be,some,connection,?], [how,?]]]]). rules([[quit,100],[ [1,[_],0, [goodbye,.,'My',secretary,will,send,you,a,bill,.]]]]). /*****************************************************************************/ % my_char_type(+Char,?Type) % Char is an ASCII code. % Type is whitespace, punctuation, numeric, alphabetic, or special. my_char_type(46,period) :- !. my_char_type(X,alphanumeric) :- X >= 65, X =< 90, !. my_char_type(X,alphanumeric) :- X >= 97, X =< 123, !. my_char_type(X,alphanumeric) :- X >= 48, X =< 57, !. my_char_type(X,whitespace) :- X =< 32, !. my_char_type(X,punctuation) :- X >= 33, X =< 47, !. my_char_type(X,punctuation) :- X >= 58, X =< 64, !. my_char_type(X,punctuation) :- X >= 91, X =< 96, !. my_char_type(X,punctuation) :- X >= 123, X =< 126, !. my_char_type(_,special). /*****************************************************************************/ % lower_case(+C,?L) % If ASCII code C is an upper-case letter, then L is the % corresponding lower-case letter. Otherwise L=C. lower_case(X,Y) :- X >= 65, X =< 90, Y is X + 32, !. lower_case(X,X). /*****************************************************************************/ % read_lc_string(-String) % Reads a line of input into String as a list of ASCII codes, % with all capital letters changed to lower case. read_lc_string(String) :- get0(FirstChar), lower_case(FirstChar,LChar), read_lc_string_aux(LChar,String). read_lc_string_aux(10,[]) :- !. % end of line read_lc_string_aux(-1,[]) :- !. % end of file read_lc_string_aux(LChar,[LChar|Rest]) :- read_lc_string(Rest). /*****************************************************************************/ % extract_word(+String,-Rest,-Word) (final version) % Extracts the first Word from String; Rest is rest of String. % A word is a series of contiguous letters, or a series % of contiguous digits, or a single special character. % Assumes String does not begin with whitespace. extract_word([C|Chars],Rest,[C|RestOfWord]) :- my_char_type(C,Type), extract_word_aux(Type,Chars,Rest,RestOfWord). extract_word_aux(special,Rest,Rest,[]) :- !. % if Char is special, don't read more chars. extract_word_aux(Type,[C|Chars],Rest,[C|RestOfWord]) :- my_char_type(C,Type), !, extract_word_aux(Type,Chars,Rest,RestOfWord). extract_word_aux(_,Rest,Rest,[]). % if previous clause did not succeed. /*****************************************************************************/ % remove_initial_blanks(+X,?Y) % Removes whitespace characters from the % beginning of string X, giving string Y. remove_initial_blanks([C|Chars],Result) :- my_char_type(C,whitespace), !, remove_initial_blanks(Chars,Result). remove_initial_blanks(X,X). % if previous clause did not succeed. /*****************************************************************************/ % digit_value(?D,?V) % Where D is the ASCII code of a digit, % V is the corresponding number. digit_value(48,0). digit_value(49,1). digit_value(50,2). digit_value(51,3). digit_value(52,4). digit_value(53,5). digit_value(54,6). digit_value(55,7). digit_value(56,8). digit_value(57,9). /*****************************************************************************/ % string_to_number(+S,-N) % Converts string S to the number that it % represents, e.g., "234" to 234. % Fails if S does not represent a nonnegative integer. string_to_number(S,N) :- string_to_number_aux(S,0,N). string_to_number_aux([D|Digits],ValueSoFar,Result) :- digit_value(D,V), NewValueSoFar is 10*ValueSoFar + V, string_to_number_aux(Digits,NewValueSoFar,Result). string_to_number_aux([],Result,Result). /*****************************************************************************/ % string_to_atomic(+String,-Atomic) % Converts String into the atom or number of % which it is the written representation. string_to_atomic([C|Chars],Number) :- string_to_number([C|Chars],Number), !. string_to_atomic(String,Atom) :- name(Atom,String). % assuming previous clause failed. /*****************************************************************************/ % extract_atomics(+String,-ListOfAtomics) (second version) % Breaks String up into ListOfAtomics % e.g., " abc def 123 " into [abc,def,123]. extract_atomics(String,ListOfAtomics) :- remove_initial_blanks(String,NewString), extract_atomics_aux(NewString,ListOfAtomics). extract_atomics_aux([C|Chars],[A|Atomics]) :- extract_word([C|Chars],Rest,Word), string_to_atomic(Word,A), % <- this is the only change extract_atomics(Rest,Atomics). extract_atomics_aux([],[]). /*****************************************************************************/ % clean_string(+String,-Cleanstring) % removes all punctuation characters from String and return Cleanstring clean_string([C|Chars],L) :- my_char_type(C,punctuation), clean_string(Chars,L), !. clean_string([C|Chars],[C|L]) :- clean_string(Chars,L), !. clean_string([C|[]],[]) :- my_char_type(C,punctuation), !. clean_string([C|[]],[C]). /*****************************************************************************/ % read_atomics(-ListOfAtomics) % Reads a line of input, removes all punctuation characters, and converts % it into a list of atomic terms, e.g., [this,is,an,example]. read_atomics(ListOfAtomics) :- read_lc_string(String), clean_string(String,Cleanstring), extract_atomics(Cleanstring,ListOfAtomics). /****************************************************************************/ % isalist(+List) % checks if List is actually a list isalist([_|_]). /****************************************************************************/ % member(?Element,+List) % checks if Element is in List % (FS) SWI-Prolog built-in predicate %member(X,[X|_]). %member(X,[_|T]) :- member(X,T). /****************************************************************************/ % append(?List1, ?List2, ?List3) % appends List2 on the end of List1 and returns it as List3 % (FS) SWI-Prolog built-in predicate %append([],L,L). %append([X|L1],L2,[X|L3]) :- append(L1,L2,L3). /****************************************************************************/ % flatten(+List,-FlatList) % flattens List with sublists into FlatList % (FS) SWI-Prolog built-in predicate %flatten([],[]). %flatten([H|T],[H|T2]) :- \+ isalist(H), % flatten(T,T2). %flatten([H|T],L) :- isalist(H), % flatten(H,A), % flatten(T,B), % append(A,B,L). /****************************************************************************/ % last_member(-Last,+List) % returns the last element of List in Last last_member(End,List) :- append(_,[End],List). /****************************************************************************/ % findnth(+List,+Number,-Element) % returns the Nth member of List in Element findnth([E|_],1,E). findnth([_|T],N,T1) :- V is N - 1, findnth(T,V,T1). /****************************************************************************/ % replace(+Element1,+List1,+Element2,-List2) % replaces all instances of Element1 in List1 with Element2 and returns % the new list as List2 % does not replace variables in List1 with Element1 replace(_,[],_,[]). replace(X,[H|T],A,[A|T2]) :- nonvar(H), H = X, !, replace(X,T,A,T2). replace(X,[H|T],A,[H|T2]) :- replace(X,T,A,T2). /****************************************************************************/ % simplify(+List,-Result) % implements non-overlapping simplification % simplifies List into Result simplify(List,Result) :- sr(List,Result,X,Y), !, simplify(X,Y). simplify([W|Words],[W|NewWords]) :- simplify(Words,NewWords). simplify([],[]). /****************************************************************************/ % match(+MatchRule,+InputList) % matches the MatchRule with the InputList. If they match, the variables % in the MatchRule are instantiated to one of three things: % an empty list % a single word % a list of words match(A,C) :- match_aux1(A,C),!. match(A,C) :- match_aux2(A,C). match_aux1(A,C) :- member([*|T],A), nonvar(T), member(Tm,T), nonvar(Tm), replace([*|T],A,Tm,B), match_aux2(B,C), !, last_member(L,T), L = Tm. match_aux2([],[]). match_aux2([Item|Items],[Word|Words]) :- match_aux3(Item,Items,Word,Words),!. match_aux2([Item1,Item2|Items],[Word|Words]) :- var(Item1), nonvar(Item2), Item2 == Word,!, match_aux2([Item1,Item2|Items],[[],Word|Words]). match_aux2([Item1,Item2|Items],[Word|Words]) :- var(Item1), var(Item2),!, match_aux2([Item1,Item2|Items],[[],Word|Words]). match_aux2([[]],[]). match_aux3(Word,Items,Word,Words) :- match_aux2(Items,Words), !. match_aux3([Word|Seg],Items,Word,Words0) :- append(Seg,Words1,Words0), match_aux2(Items,Words1). /****************************************************************************/ % makecomment(+KeyWordList,+InputList,-Comment) % returns ELIZA's Comment to the InputList based on the KeyWordList % takes care of special keywords 'your', and 'memory', which require % additional processing before a comment can be generated makecomment([[your,2]|T],InputList,Comment) :- assertz(mem(InputList)), rules([[your,2],Reassembly]), mc_aux([[your,2]|T],Reassembly,InputList,Comment),!. makecomment([[memory,0]|T],_,Comment) :- retract(mem(I2)), retractall(mem(I2)), rules([[memory,0],Reassembly]), mc_aux([[memory,0]|T],Reassembly,I2,Comment),!. makecomment([[memory,0]|T],InputList,Comment) :- \+ retract(mem(_)),!, makecomment(T,InputList,Comment). makecomment([Keyword|T],InputList,Comment) :- rules([Keyword,Reassembly]), mc_aux([Keyword|T],Reassembly,InputList,Comment),!. makecomment([_|T],InputList,Comment) :- makecomment(T,InputList,Comment),!. mc_aux(KeyWordList,[[DRuleNum,MatchRule,N|T]|_],InputList,Comment) :- match(MatchRule,InputList), mc_aux2(KeyWordList,DRuleNum,N,T,InputList,Comment),!. mc_aux(KeyWordList,[_|T],InputList,Comment) :- mc_aux(KeyWordList,T,InputList,Comment). mc_aux(_,[],_,_) :- !,fail. mc_aux2(KeyWordList,DRuleNum,N,T,InputList,Comment) :- length(T,TLen), N < TLen, !, NewN is N + 1, findnth(T,NewN,Mn), mc_aux3(KeyWordList,DRuleNum,N,NewN,Mn,InputList,Comment). mc_aux2(KeyWordList,DRuleNum,N,T,InputList,Comment) :- member(Mn,T), mc_aux3(KeyWordList,DRuleNum,N,0,Mn,InputList,Comment). mc_aux3([Keyword|T],DRuleNum,N,NewN,[equal,MnT],InputList,Comment) :- !, updaterule(Keyword,DRuleNum,N,NewN), makecomment([MnT|T],InputList,Comment). mc_aux3([Keyword|T],DRuleNum,N,NewN,[newkey],InputList,Comment) :- !, updaterule(Keyword,DRuleNum,N,NewN), makecomment(T,InputList,Comment). mc_aux3([Keyword|_],DRuleNum,N,NewN,Mn,_,Mn) :- updaterule(Keyword,DRuleNum,N,NewN). /****************************************************************************/ % process_input(+Input_List,+[],?Output) % returns part of input after a comma, or % part of input before a period process_input([],L,L). process_input(['.'|_],L,L) :- findkeywords(L,K), length(K,Kl), Kl >= 3,!. process_input(['.'|T],_,L) :- !, process_input(T,[],L). process_input([','|_],L,L) :- findkeywords(L,K), length(K,Kl), Kl >= 3,!. process_input([','|T],_,L) :- !, process_input(T,[],L). process_input([H|T],S,L) :- append(S,[H],S2), process_input(T,S2,L). /****************************************************************************/ % findkeywords(+InputList,?KeyWordList) % returns a list with the keywords in the input list % if no keywords are found returns a list with keywords 'memory' and 'none' findkeywords([],[[memory,0],[none,0]]). findkeywords([H|T],[[H,I]|T1]) :- rules([[H,I]|_]), !, findkeywords(T,T1). findkeywords([_|T],T1) :- findkeywords(T,T1). /****************************************************************************/ % sortkeywords(+KeyWordList,?SortedList) % returns a list with the keywords sorted according to their importance % this routine implements a simple bubble sort, customized for this % application sortkeywords(X,Y) :- sort_aux(X,A,1), !, sortkeywords(A,Y). sortkeywords(X,Y) :- sort_aux(X,Y,_). sort_aux([],[],0). sort_aux([X],[X],0). sort_aux([[A,X],[B,Y]|T],[[B,Y],[A,X]|T],1) :- X < Y. sort_aux([X,Y|T],[X|T2],S) :- sort_aux([Y|T],T2,S). /****************************************************************************/ % updaterule(+KeyList,+DRuleNum,+N,+NewN) % updates a rule by changing the number of the reassembly rule associated % with a decomposition rule. The main rule to modify is indicated by % KeyList. The decomposition rule within the main rule is indicated by % DRuleNum. N is the previous reassembly rule used. NewN is the new % one used. N is updated to NewN so that next time a different reassembly % (actually the next in sequence) in used. updaterule(KeyList,DRuleNum,N,NewN) :- retract(rules([KeyList,Rt])), replace([DRuleNum,A,N|T],Rt,[DRuleNum,A,NewN|T],Rt2), assertz(rules([KeyList,Rt2])). /****************************************************************************/ % writecomment(+CommentList) % prints the elements of CommentList. First Characater of first element is % converted to uppercase befor printing writecomment([]). writecomment(['I'|T]) :- !, write('I'), writecomment_aux(T). writecomment([H|T]) :- !, name(H,[C|L]), D is C - 32, name(Z,[D|L]), write(Z), writecomment_aux(T). writecomment_aux([]). writecomment_aux([H|T]) :- name(H,[C]), my_char_type(C,punctuation), !, write(H), writecomment_aux(T). writecomment_aux([H|T]) :- write(' '), write(H), writecomment_aux(T). /****************************************************************************/ % quittime(+InputList) % checks if the atom 'quit' is in the InputList quittime(X) :- member('quit',X). /****************************************************************************/ % eliza % main routine of ELIZA eliza :- % reconsult('eliza.rls'), retractall(mem(_)),nl,nl, write('Hello. I am ELIZA. How can I help you?'),nl,write('> '), repeat, read_atomics(Input),nl, process_input(Input,[],Input2), simplify(Input2,Input3), findkeywords(Input3,KeyWords), sortkeywords(KeyWords,KeyWords2), makecomment(KeyWords2,Input3,Comment), flatten(Comment,Comment2), writecomment(Comment2),nl,write('> '), quittime(Input3), !. :- eliza,nl,nl.