1% ===================================================================
    2% File 'logicmoo_module_aiml.pl'
    3% Purpose: An Implementation in CS-prolog of AIML
    4% Maintainer: Douglas Miles
    5% Contact: $Author: dmiles $@users.sourceforge.net ;
    6% Version: 'logicmoo_module_aiml.pl' 1.0.0
    7% Revision:  $Revision: 1.7 $
    8% Revised At:   $Date: 2002/07/11 21:57:28 $
    9% ===================================================================
   10
   11%:-module()
   12%:-include('logicmoo_utils_header.pl'). %<?
   13%:- style_check(-singleton).
   14%:- style_check(-discontiguous).
   15%:- style_check(-atom).
   16%:- style_check(-string).
   17
   18
   19
   20:-discontiguous(what/3).
   21:-discontiguous(response/2).
   22:-discontiguous(load_aiml_structure/2).
   23:-discontiguous(load_aiml_structure/3).
   24
   25:-dynamic(flagsaved/2).
   26
   27swi_flag(X,OldVal,NewVal):-var(OldVal),retract(flagsaved(X,OldVal)),
   28swi_flag(X,OldVal,NewVal).
   29swi_flag(_,4,_).
   30
   31atom_codes(A,C):-name(A,C).
   32
   33to_upper(Any,Any):-fail.
   34to_upper(Any,Any):-!.
   35
   36
   37ignore(C) :- C ; true.
   38
   39format(A,B,C):-writeq(format(A,B,C)).
   40flush_output(A):-nl.
   41
   42call_with_depth_limit(C,D,M):-C.
   43
   44%reverse([], []).
   45%reverse([Head|Tail], Result):- reverse(Tail, Reduced),append(Reduced, [Head], Result).
   46
   47
   48
   49   flatten([],[]).
   50   flatten([[]|L],L).
   51   flatten([X|L1],[X|L2]) :- atomic(X), flatten(L1,L2).
   52   flatten([X|L1],L4) :- flatten(X,L2),
   53                         flatten(L1,L3),
   54                         append(L2,L3,L4).
   55
   56 nth([F|R],1,F).
   57 nth([F|R],N,M) :- N > 1, N1 is N-1, nth(R,N1,M).
   58
   59     is_string(X):-string(X),!.
   60     is_string(X):-atom(X),!,atom_length(X,L),L>1,atom_concat('"',_,X),atom_concat(_,'"',X),!.
   61     is_string(X):-var(X),!,fail.
   62     is_string(string(_)):-!.
   63     is_string("").
   64     is_string(L):-is_charlist(L),!.
   65     is_string(L):-is_codelist(L),!.
   66
   67%%:-['aimlbotFromBoth.pl'].
   68
   69ta:-alicebot2(['HI'],X),!,writeln(X).
   70
   71
   72
   73run_chat_tests:-
   74   test_call(alicebot('Hi')),
   75   test_call(alicebot('What is your name')),
   76   test_call(alicebot('My name is Fred.')),
   77   test_call(alicebot('what is my name?')).
   78
   79test_call(G):-writeln(G),ignore(once(catch(G,E,writeln(E)))).
   80
   81main_loop1(Atom):- current_input(In),!,
   82            read_line_with_nl(In,Codes,[]),!,
   83            atom_codes(Atom,Codes),!,
   84            alicebot(Atom),!.
   85
   86aiml_main_loop:-repeat,main_loop1(Atom),catch(atom_to_term(Atom,Term,Vars),_,fail),
   87      once(callInteractive0(Term,Vars)),fail.
   88
   89% callInteractive(Term,V):-
   90callInteractive(Term,Var):-callInteractive0(Term,Var).
   91
   92callInteractive0(Term,Var):-atom(Term),!,Term,writeln(called(Term)),!.
   93callInteractive0(Term,_):-catch((call(Term),writeq(Term),nl,fail),_,fail).
   94callInteractive0(Term,_):-!.
   95
   96
   97% ===============================================================================================
   98% Save Possible Responses (Degrade them as well)
   99% ===============================================================================================
  100
  101dyn_retractall(X):- numbervars(X,0,E),call(X),retract(X),fail.
  102dyn_retractall(_).
  103
  104possibleResponse( 0.1, [very,bad]).
  105
  106:-dynamic(possibleResponse/2).
  107
  108savePosibleResponse(N,O):- call( possibleResponse(_,O) ),!.
  109savePosibleResponse(N,O):-
  110    findall(1, degraded(O), L),!,
  111   length(L,K),
  112   SN is N - (K * 0.6)  , !,
  113   asserta(possibleResponse(SN,O)).
  114
  115
  116   
  117% ===============================================================================================
  118% ALICE IN PROLOG
  119% ===============================================================================================
  120
  121
  122convert_to_string(I,ISO):-
  123                term_to_string(I,IS),!,
  124		string_to_list(IS,LIST),!,
  125		list_replace(LIST,92,[92,92],LISTM),
  126		list_replace(LISTM,34,[92,34],LISTO),
  127		string_to_atom(ISO,LISTO),!.
  128
  129list_replace(List,Char,Replace,NewList):-
  130	append(Left,[Char|Right],List),
  131	append(Left,Replace,NewLeft),
  132	list_replace(Right,Char,Replace,NewRight),
  133	append(NewLeft,NewRight,NewList),!.
  134list_replace(List,_Char,_Replace,List):-!.
  135
  136
  137term_to_string(I,IS):- catch(string_to_atom(IS,I),_,(term_to_atom(I,A),string_to_atom(IS,A))),!.
  138%well i played with a couple few differnt environment impls.. they have their pros cons.. one impl.. that was unique is that an array of "binding pairs" live in an arraylist.. to be "in" an environment it meant that you held an "index" into the arry list that as you went backwards you'd find your bindings.. each symbol had a java int field "lastBindingIndex" .. that was a "hint" to where you could fastforward the backwards search .. end named binding context also had a "index" to when you leave a named block.. you could quickly reset the top of an index.
  139
  140say(X):-format(user_output,'~q~n',X),flush_output(user_output).
  141
  142
  143alicebot(Input):-
  144   alicebot(Input,Resp),
  145   say(Resp).
  146alicebot(Input):-say('-no response-').
  147   
  148
  149removePMark(UCase,Atoms):-member(Last,[?,('.'),(',')]),append(AtomsPre,[Last],UCase),!,removePMark(AtomsPre,Atoms).
  150removePMark(Atoms,Atoms).
  151
  152
  153
  154%clean_out_atom(X,X).
  155
  156randomPick(List,Ele):-length(List,Len),Pick is random(Len),nth0(Pick,List,Ele),!.
  157
  158all_upper_atom(X):-toUppercase(X,N),N=X.
  159
  160:-dynamic(default_channel/1).
  161:-dynamic(default_user/1).
  162
  163default_channel( "#logicmoo").
  164default_user(    "unknown_partner").         
  165
  166% say(Say):-writeq(Say),nl.
  167toCodes(B,A):-cyc:stringToCodelist(B,AO),(is_list(A) -> A=AO ; string_to_list(AO,A)),!.
  168
  169
  170dumpList([]):-!.
  171dumpList([A|B]):-say(A),dumpList(B),!.
  172
  173dumpList(B):-say(  dumpList(B)).
  174
  175alicebot(Input,Resp):-
  176   getWordTokens(Input,Tokens),
  177   toUppercase(Tokens,UCase),
  178   removePMark(UCase,Atoms),
  179   alicebot2(Atoms,Resp).
  180
  181alicebot2(Atoms,[O-N]):-	
  182   computeAnswer(1,srai(Atoms),O,N),!.
  183
  184alicebot2(Atoms,Resp):-	
  185   dyn_retractall(possibleResponse(_,_)),
  186   swi_flag(a_answers,_,0),!,
  187   ignore((
  188   call_with_depth_limit(computeAnswer(1,srai(Atoms),O,N),8000,DL),
  189	 ignore((nonvar(N),nonvar(O),savePosibleResponse(N,O))),swi_flag(a_answers,X,X+1),X>3)),!,
  190   findall(NR-OR, call(possibleResponse(NR,OR)) ,L),!,
  191   %format('~n-> ~w~n',[L]),
  192   keysort(L,S),!,
  193   dumpList(S),!,
  194   reverse(S,[Resp|RR]),!,
  195   degrade(Resp),!,
  196   rememberSaidIt(Resp),!.
  197
  198% ===============================================================================================
  199% Degrade Response
  200% ===============================================================================================
  201
  202:-dynamic(degraded/1).
  203degraded([]).
  204
  205degrade(_-OR):- degraded(OR),!.
  206degrade(OR):- asserta(degraded(OR)).
  207
  208
  209% ===============================================================================================
  210% Compute Answer Probilities
  211% ===============================================================================================
  212from_atom_codes(Atom,Atom):-atom(Atom),!.
  213from_atom_codes(Atom,Codes):-convert_to_string(Codes,Atom),!.
  214from_atom_codes(Atom,Codes):-atom_codes(Atom,Codes).
  215
  216computeAnswer(Votes,[],[],Votes):-!.
  217
  218
  219computeAnswer(Votes,['.'],[],Votes):-!.
  220computeAnswer(Votes,I,_,_):-(Votes>20;Votes<0.3),!,fail.
  221computeAnswer(Votes,srai(Input),O,VotesO):- !,flatten([Input],Flat),computeSRAI(Votes,Flat,Mid,VotesM),computeAnswer(VotesM,Mid,O,VotesO).
  222computeAnswer(Votes,nick,A,Votes):-!,default_user(B),!,from_atom_codes(A,B),!.
  223computeAnswer(Votes,person,A,Votes):-!,default_user(B),!,from_atom_codes(A,B),!.
  224computeAnswer(Votes,botnick,'jllykifsh',Votes):-!.
  225computeAnswer(Votes,mynick,'jllykifsh',Votes):-!.
  226computeAnswer(Votes,name=name,'jllykifsh',Votes):-!.
  227computeAnswer(Votes,mychan,A,Votes):-!,default_channel(B),!,from_atom_codes(A,B),!.
  228computeAnswer(Votes,randomsentence,O,VotesO):-!, choose_randomsentence(X),!,computeAnswer(Votes,X,O,VotesO).
  229computeAnswer(Votes,Resp,Resp,Votes):-atomic(Resp),!.
  230computeAnswer(Votes,li(List),AA,VotesO):-!,computeAnswer(Votes,List,AA,VotesO).
  231computeAnswer(Votes,random(List),AA,VotesO):-!,randomPick(List,Pick),computeAnswer(Votes,Pick,AA,VotesO).
  232computeAnswer(Votes,condition(List),AA,VotesO):-!,member(Pick,List),computeAnswer(Votes,Pick,AA,VotesO).
  233computeAnswer(Votes,String,Atom,Votes):-string(String),!,string_to_atom(String,Atom).
  234computeAnswer(Votes,String,Atom,Votes):-is_string(String),toCodes(String,Codes),!,from_atom_codes(Atom,Codes).
  235computeAnswer(Votes,'$stringCodes'(List),AA,Votes):-!,from_atom_codes(AA,List).
  236computeAnswer(Votes,gossip(Thought),O,VotesO):-!,computeAnswer(Votes,Thought,O,VotesO).
  237computeAnswer(Votes,think(Thought),[],VotesO):-!,computeAnswer(Votes,Thought,O,VotesO).
  238computeAnswer(Votes,get([X]),Resp,VotesO):-getAliceMem(X,E),!,computeAnswer(Votes,E,Resp,VotesM),VotesO is VotesM * 1.1.
  239computeAnswer(Votes,get(X),Resp,VotesO):-getAliceMem(X,E),!,computeAnswer(Votes,E,Resp,VotesM),VotesO is VotesM * 1.1.
  240computeAnswer(Votes,get(_),_,_):-!,fail.
  241computeAnswer(Votes,_-A,A,Votes):-!.
  242computeAnswer(Votes,set(X,E),Resp,VotesO):-!,computeAnswer(Votes,E,Resp,VotesM),setAliceMem(X,Resp),!,VotesO is VotesM * 1.1.
  243%computeAnswer(Votes,B,Out,VotesO):-append(BB,['.','.'|BBB],B),append(BB,['.'|BBB],RB),!,computeAnswer(Votes,RB,Out,VotesO).
  244computeAnswer(Votes,B,Out,VotesO):-append(BB,['.'|BBB],B),append(BB,BBB,RB),!,computeAnswer(Votes,RB,Out,VotesO).
  245computeAnswer(Votes,[A|L],OO,VotesO):-!,
  246	 computeAnswer(Votes,A,AA,VotesM),
  247	 computeAnswer(VotesM,L,LL,VotesO),
  248	 once(flatten([AA,LL],OO)).
  249computeAnswer(Votes,Resp,Resp,Votes).
  250
  251
  252
  253
  254
  255% ===============================================================================================
  256% Apply Input Match
  257% ===============================================================================================
  258
  259computeSRAI(Votes,[],_,_):-!,fail.
  260computeSRAI(Votes,Input,Output,VotesO):-append(Left,[Last],Input),
  261         member(Last,[('.'),('!'),('?')]),!,
  262         computeSRAI(Votes,Left,Output,VotesO).
  263
  264computeSRAI(Votes,Input,TopicStarO,VotesO):-
  265	 getLastSaid(WhatSaid),
  266	 set_matchit(Input,MatchIt),get_aiml_what(What,MatchIt,Out),
  267	 rateMatch(What,WhatSaid,What,NewTopic,TopicVote,TopicStar), 
  268	 rateMatch(MatchIt,Input,Out,Next,Voted,_), 
  269	 flatten([Next],NextO),
  270	 subst(NextO,topicstar,TopicStar,TopicStarO),
  271	 VotesO is Votes * (Voted + TopicVote).
  272
  273
  274
  275
  276
  277% this next line is what it does on fallback
  278%computeSRAI(Votes,[B|Flat],[B|TopicStarO],VotesO):-computeSRAI(Votes,Flat,TopicStarO,VotesO).
  279
  280set_matchit([Input|_],[Input|_]).
  281set_matchit([Input|_],[_,Input|_]).
  282set_matchit([_,Input|_],[_,Input|_]).
  283
  284%get_aiml_what(What,Match,OOut):-get_aiml_cyc(What,Match,Out),(([srai(Out)] = OOut);OOut=Out).
  285get_aiml_what(What,Match,Out):-what(What, Match,Out).
  286get_aiml_what([*],Match,Out):-response(Match,Out).
  287
  288%get_aiml_cyc([*],[String|ListO],[Obj,*]):-poStr(Obj,[String|List]),append(List,[*],ListO).
  289%get_aiml_cyc([*],[String,*],[Obj,*]):-poStr(Obj,String).
  290
  291
  292% ===============================================================================================
  293% Rate Match
  294% ===============================================================================================
  295rateMatch([],[],Out,Out,1,[]):-!.
  296
  297rateMatch(Match,Match,Out,Out,1.3,[]):-!.
  298
  299rateMatch([This|More],[This|More2],Out,OOut,Vote2,Grabbed):-!,
  300      rateMatch(More,More2,Out,OOut,Vote,Grabbed),!,
  301      Vote2 is Vote * (1.11).
  302
  303rateMatch([*],More,Out,OOut,0.77,More):-!,subst(Out,*,More,OOut),!.
  304rateMatch(['_'],More,Out,OOut,0.87,More):-!,subst(Out,*,More,OOut),!.
  305
  306rateMatch([*|Rest],More,Out,OOut,VoteO,Grabbed):-!,
  307      append(Grabbed,Rest,More),
  308      rateMatch(More,More2,Out,OOut,Vote,_),
  309      subst(Out,*,Grabbed,OOut),
  310      VoteO is Vote * (0.72),!.
  311
  312rateMatch(['_'|Rest],More,Out,OOut,VoteO,Grabbed):-!,
  313      append(Grabbed,Rest,More),
  314      rateMatch(More,More2,Out,OOut,Vote,_),
  315      subst(Out,*,Grabbed,OOut),
  316      VoteO is Vote * (0.82),!.
  317            
  318
  319
  320% ===============================================================================================
  321% Run answer procs
  322% ===============================================================================================
  323
  324choose_randomsentence(X):-
  325	repeat,
  326		retract(random_sent(Y)),
  327		assertz(random_sent(Y)),
  328		4 is random(10),!,
  329		Y=X.
  330
  331getAliceMem(X,E):-isAliceMem(X,E),!.
  332 
  333setAliceMem(X,[E]):-!,setAliceMem(X,E),!.
  334setAliceMem(X,'nick').
  335setAliceMem(X,E):-dyn_retractall(isAliceMem(X,_)),asserta(isAliceMem(X,E)),writeln(debug(isAliceMem(X,E))),!.
  336:-dynamic(isAliceMem/2).
  337
  338% ===============================================================================================
  339% Get and rember Last Said
  340% ===============================================================================================
  341
  342:-dynamic(getLastSaid/1).
  343getLastSaid([*]).
  344
  345rememberSaidIt([]):-!.
  346rememberSaidIt(_-R1):-!,rememberSaidIt(R1).
  347rememberSaidIt(R1):-append(New,['.'],R1),!,rememberSaidIt(New).
  348rememberSaidIt(R1):-ignore(retract(getLastSaid(_))),toUppercase(R1,SR1),!,asserta(getLastSaid(SR1)).
  349
  350
  351% =================================================================================
  352% AIML Loading
  353% =================================================================================
  354load_aiml_files:-load_aiml_files('*.aiml'),!.
  355
  356load_aiml_files([]).
  357load_aiml_files([H|T]):-
  358   load_aiml_files(H),!,
  359   load_aiml_files(T).
  360load_aiml_files(F):-atom(F),
  361   expand_file_name(F,[F]),!,
  362   load_aiml_file(F).
  363load_aiml_files(F):-atom(F),expand_file_name(F,FILES),!,load_aiml_files(FILES).
  364
  365aiml_files(F,Files):-atom_concat(F,'/',WithSlashes),expand_file_name(WithSlashes,WithOneSlash,[relative_to('./')]),
  366                    atom_concat(WithOneSlash,'/*.aiml',Mask),expand_file_name(Mask,Files).
  367
  368load_aiml_file(F):- exists_directory(F), aiml_files(F,Files),!,load_aiml_files(Files).
  369load_aiml_file(F):- file_name_extension(F,'aiml',Aiml).
  370
  371
  372create_aiml_file(F):-
  373   atom_concat(F,'.pl',PLNAME),
  374   time_file(PLNAME,PLTime), % fails on non-existent
  375   time_file(F,FTime),
  376   PLTime > FTime,!,
  377   [PLNAME],!.
  378
  379create_aiml_file(F):-
  380   atom_concat(F,'.pl',PLNAME),
  381   tell(PLNAME),
  382   (format(user_error,'%~w~n',[F])),
  383   load_structure(F,X,[space(remove)]),!,
  384   load_aiml_structure(notopic,X),!,
  385   told,[PLNAME],!.
  386
  387
  388load_aiml_structure(_,O):-ignore_aiml(O),!.
  389load_aiml_structure(N,[X|L]):-load_aiml_structure(N,X),!,load_aiml_structure(N,L),!.
  390   
  391load_aiml_structure(N,element(aiml,L,T)):-!,load_aiml_structure(N,T).
  392load_aiml_structure(N,element(a,L,T)):-!,load_aiml_structure(N,T).
  393load_aiml_structure(N,element(substitute,[name=Catalog, find=Find, replace=Replace],[])):-!,
  394	 load_aiml_structure(N,substitute(Catalog,Find,Replace)).
  395load_aiml_structure(N,element(substitute,[name=Catalog, find=Find, replace=Replace],Stuff)):-!,
  396	 load_aiml_structure(N,substitute(Catalog,Find,Replace,Stuff)).
  397load_aiml_structure(N,element(topic,[name=Name],T)):-!,load_topic(Name,T),!.
  398
  399load_topic(_,L):-ignore_aiml(L).
  400load_topic(Name,[H|T]):-
  401      load_aiml_structure(Name,H),!,
  402      load_topic(Name,T).
  403
  404load_aiml_structure(N,element(category,[],T)):-!,load_category(N,T),!.
  405load_aiml_structure(N,element(startup,_,T)):-!.
  406
  407load_aiml_structure(N,substitute(Dict,Find,Replace)):-
  408      atomSplit(Find,F),atomSplit(Replace,Resp),!,
  409      load_aiml_structure(N,dict(Dict,F,Resp)).
  410
  411load_aiml_structure(N,X):-format('~q.~n',[X]).
  412%      saveFAttribute(F,A),
  413     % 
  414      %(catch(X,_,fail);asserta(X)),!.
  415
  416:-dynamic(saveDFAttribute/2).
  417:-dynamic(replace_t/5).
  418:-dynamic(response_t/5).
  419                
  420%saveFAttribute(F,A):-saveDFAttribute(F,A),!.
  421%saveFAttribute(F,A):-asserta(saveDFAttribute(F,A)),dynamic(F/A).
  422
  423% ===============================================================================================
  424% ===============================================================================================
  425
  426ignore_aiml([]).
  427ignore_aiml(A):-atom(A),atom_codes(A,C),clean_codes(C,[]).
  428
  429%clean_codes(X,X).
  430
  431
  432aiml_classify([],[]).
  433aiml_classify(Find,[atom]):-atomic(Find).
  434aiml_classify([H|T],Out):-
  435      classifySingle(H,Class),
  436      aiml_classify(T,More),
  437      sort([Class|More],OutM),!,
  438      classify2(OutM,Out).
  439aiml_classify(T,[unk]).
  440
  441classify2([in,out|Resp],[out|Resp]).
  442classify2(Out,Out).
  443
  444classifySingle('_',var('_')).
  445classifySingle(*,var('*')).
  446classifySingle(Atom,in):-atom(Atom),all_upper_atom(Atom).
  447classifySingle(Atom,out):-atom(Atom).
  448classifySingle(Atom,spec(F)):-compound(Atom),functor(Atom,F,_).
  449classifySingle(Atom,unknown).
  450
  451                                        
  452      
  453varize(Find,Replace,FindO,ReplaceO):-
  454      subst((Find,Replace),'_','$VAR'(0),(FindM,ReplaceM)),
  455      subst((FindM,ReplaceM),'*','$VAR'(0),(FindO,ReplaceO)),!.
  456      
  457
  458load_category(_,L):-ignore_aiml(L).
  459load_category(N,L):-
  460      ignore(member(element(that,IA,IB),L)),
  461      ignore((member(element(justbeforethat,[],[]),L),(IA= [index='1,2'],IB=[]))),
  462      ignore(member(element(pattern,PA,PB),L)),
  463      ignore(member(element(template,TA,TB),L)),!,
  464      load_category(N,IA,IB,PA,PB,TA,TB),!.
  465
  466load_category(Topic,IA,IB,PA,PB,TA,TB):-
  467      ignore(ignore_aiml(IA)),
  468      convert_template(IB,I),
  469      convert_template(PB,P),
  470      convert_template(TB,T),
  471      parse_category(Topic,IA,I,PA,P,TA,T).
  472load_category(Topic,IA,IB,PA,PB,TA,TB):-trace.
  473
  474parse_category(notopic,[],[],[],PB,[],TB):-!,
  475      load_aiml_structure(N,response(PB,TB)).
  476
  477parse_category(notopic, [],What, [], A, [], B):-!,
  478      load_aiml_structure(N,what(What,A,B)).
  479
  480parse_category(Topic,[],[],[],PB,[],TB):-!,
  481   load_aiml_structure(N,topic_resp(Topic,PB,TB)).
  482
  483parse_category(Topic,IA,IB,PA,PB,TA,TB):-!,
  484   load_aiml_structure(N,category(Topic,IA,IB,PA,PB,TA,TB)).
  485      
  486
  487
  488convert_template(Input,Out):-
  489   convert_template1(Input,M),
  490   flatten(M,MM),
  491   convert_template1(MM,O),
  492   flatten(O,Out).
  493
  494
  495convert_template1([],[]).
  496convert_template1([I|P],L):-
  497      ignore_aiml(I),!,convert_template1(P,L).
  498convert_template1([I|P],[O|L]):-
  499      convert_element(I,O),!,
  500      convert_template1(P,L).
  501convert_template1(P,P).
  502
  503      
  504convert_element(Input,Out):-convert_ele(Input,M),!,convert_ele(M,Out),!.
  505
  506
  507convert_ele(li(A),li(AA)):-convert_template(A,AA).
  508convert_ele(get(A,[]),get(AA)):-convert_template(A,AA).
  509convert_ele(element(set, [name=N], V),set(N,VV)):-convert_template(V,VV).
  510convert_ele(element(get, [name=N], V),get(N,VV)):-convert_template(V,VV).
  511convert_ele(element(SET_ATOM, [], V),set(N,VV)):-atom_concat('set_',N,SET_ATOM),convert_template(V,VV).
  512convert_ele(element(GET_ATOM, [], V),get(N,VV)):-atom_concat('get_',N,GET_ATOM),convert_template(V,VV).
  513convert_ele(element(BOT_ATOM, [], V),match(N,VV)):-atom_concat('bot_',N,BOT_ATOM),convert_template(V,VV).
  514convert_ele(element(bot, [N=V], []),N=V).
  515convert_ele(element(srai, [], B),srai(BB)):-convert_template(B,BB).
  516convert_ele(element(random, [], B),random(BB)):-convert_template(B,BB).
  517convert_ele(element(li, [], B),li(BB)):-convert_template(B,BB).
  518convert_ele(element(star, [], []),(*)).
  519convert_ele(element(a, [Target, Link], Name),A):-sformat(S,'<a ~q ~q>~w</a>',[Target, Link, Name]),string_to_atom(S,A).
  520convert_ele(element(a, [Link], Name),A):-sformat(S,'<a ~q>~w</a>',[Link, Name]),string_to_atom(S,A).
  521
  522convert_ele(element(A, [], []),A):-!.
  523convert_ele(element(A, [], B),T):-!,convert_template(B,BB), T=..[A,BB].
  524convert_ele(element(A, B, []),T):-!,convert_template(B,BB), T=..[attrib,A,BB].
  525convert_ele(element(A, B, C),T):-!,
  526      convert_template(B,BB),
  527      convert_template(C,CC),!, 
  528      T=..[A,BB,CC].
  529convert_ele(attrib(get, name=Var),get(Var)):-!.
  530convert_ele(attrib(learn, filename=F),load_any_file(F)):-!.
  531convert_ele(sr,[srai([*])]).
  532convert_ele(star,*).
  533
  534convert_ele(L,LO):-is_list(L),flatten(L,M),!,
  535	    (L==M -> LO=M ; convert_template(M,LO)).
  536
  537convert_ele(A,W):-atom(A),clean_out_atom(A,B),
  538	    atomSplit(B,W).
  539convert_ele(O,O).
  540
  541
  542
  543
  544%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%PROBLY SHOULD E IN CYC
  545toUppercase(VAR,VAR):-var(VAR),!.
  546toUppercase([],[]):-!.
  547toUppercase(V,V2):-string(V),!,atom_codes(V,VC),toUppercase(VC,CVC),string_to_atom(V2,CVC),!.
  548toUppercase(95,45):-!.
  549toUppercase(I,O):-integer(I),!,to_upper(I,O).
  550toUppercase([A|L],[AO|LO]):-
  551   toUppercase(A,AO),!,
  552   toUppercase(L,LO),!.
  553toUppercase(MiXed,UPPER):-atom(MiXed),!,
  554   atom_codes(MiXed,Codes),
  555   toUppercase(Codes,UCodes),
  556   atom_codes(UPPER,UCodes),!.
  557toUppercase(MiXed,UPPER):-compound(MiXed),MiXed=..MList,toUppercase(MList,UList),!,UPPER=..UList.
  558toUppercase(A,A).
  559
  560toLowercase(VAR,VAR):-var(VAR),!.
  561toLowercase(V,V2):-string(V),!,atom_codes(V,VC),toLowercase(VC,CVC),string_to_atom(V2,CVC),!.
  562toLowercase([],[]):-!.
  563toLowercase(95,45):-!.
  564toLowercase(I,O):-integer(I),!,to_lower(I,O).
  565toLowercase([A|L],[AO|LO]):-
  566   toLowercase(A,AO),!,
  567   toLowercase(L,LO),!.
  568toLowercase(MiXed,UPPER):-atom(MiXed),!,
  569   atom_codes(MiXed,Codes),
  570   toLowercase(Codes,UCodes),
  571   atom_codes(UPPER,UCodes),!.
  572toLowercase(MiXed,UPPER):-compound(MiXed),MiXed=..MList,toLowercase(MList,UList),!,UPPER=..UList.
  573toLowercase(A,A).
  574
  575
  576subst(A,B,C,D):- 
  577   nd_subst(A,B,C,D),!.
  578subst(A,B,C,A).
  579
  580nd_subst(  Var, VarS,SUB,SUB ) :- Var==VarS,!.
  581nd_subst(  P, X,Sk, P1 ) :- functor(P,_,N),nd_subst1( X, Sk, P, N, P1 ).
  582
  583nd_subst1( _,  _, P, 0, P  ).
  584nd_subst1( X, Sk, P, N, P1 ) :- N > 0, P =.. [F|Args], 
  585            nd_subst2( X, Sk, Args, ArgS ),
  586            nd_subst2( X, Sk, [F], [FS] ),  
  587            P1 =.. [FS|ArgS].
  588
  589nd_subst2( _,  _, [], [] ).
  590nd_subst2( X, Sk, [A|As], [Sk|AS] ) :- X == A, !, nd_subst2( X, Sk, As, AS).
  591nd_subst2( X, Sk, [A|As], [A|AS]  ) :- var(A), !, nd_subst2( X, Sk, As, AS).
  592nd_subst2( X, Sk, [A|As], [Ap|AS] ) :- nd_subst( A,X,Sk,Ap ),nd_subst2( X, Sk, As, AS).
  593nd_subst2( X, Sk, L, L ).
  594
  595
  596atomSplit(Atom,Words):-var(Atom),!,
  597   concat_atom(Words,' ',Atom).
  598atomSplit(Atom,Words):-
  599   concat_atom(Words1,' ',Atom),
  600   atomSplit2(Words1,Words),!.
  601
  602atomSplit2([],[]).
  603atomSplit2([W|S],[A,Mark|Words]):- member(Mark,['.',',','?']),atom_concat(A,Mark,W),not(A=''),!,atomSplit2(S,Words).
  604atomSplit2([W|S],[Mark,A|Words]):- member(Mark,['.',',','?']),atom_concat(Mark,A,W),not(A=''),!,atomSplit2(S,Words).
  605atomSplit2([W|S],[W|Words]):-atomSplit2(S,Words).
  606
  607
  608
  609:-['cynd/bootstrap.aiml.pl'].
  610
  611
  612%:-load_aiml_files.
  613
  614
  615%:-debug,run_chat_tests.
  616
  617%:-main_loop.