Author Topic: Eliza  (Read 6202 times)

Offline amylase

  • Friend
  • **
  • Posts: 75
    • View Profile
    • gpLand
Eliza
« on: April 05, 2008, 05:26:16 am »
Hi guys. Over the last 1 - 2 years on and off I've looked around online for an LPC port of Eliza that would run under DS2. To my disappointment I haven't been able to find anything readily made for simple plug'n play. Came across quite a few different ports but nothing quite exactly for DS2. So over the next 7 or 8 months I'll probably start porting this good old basic one over. See how things go, I might try hook her up google search engine for additional amusement. Anyone got anything at hand already, to save me re-inventing the wheel?

Code: [Select]
1 KEY OFF : CLS
4 CLS
5 PRINT TAB(16)"**************************"
10 PRINT TAB(26)"ELIZA"
20 PRINT TAB(20)"CREATIVE COMPUTING"
30 PRINT TAB(18)"MORRISTOWN, NEW JERSEY":PRINT
40 PRINT TAB(19)"ADAPTED FOR IBM PC BY"
50 PRINT TAB(20)"PATRICIA DANIELSON AND PAUL HASHFIELD"
52 PRINT TAB(21)"BE SURE THAT THE CAPS LOCK IS ON
53 PRINT:PRINT TAB(16)"PLEASE DON'T USE COMMAS OR PERIODS IN YOUR INPUTS":PRINT
55 PRINT TAB(16)"*************************"
60 PRINT :PRINT :PRINT
80 REM*****INITIALIZATION**********
100 DIM S(36),R(36),N(36)
105 DIM KEYWORD$(36),WORDIN$(7),WORDOUT$(7),REPLIES$(112)
110 N1=36:N2=14:N3=112
112 FOR X = 1 TO N1: READ KEYWORD$(X): NEXT X
114 FOR X = 1 TO N2/2: READ WORDIN$(X):READ WORDOUT$(X): NEXT X
116 FOR X = 1 TO N3: READ REPLIES$(X): NEXT X
130 FOR X=1 TO N1
140 READ S(X),L:R(X)=S(X):N(X)=S(X)+L-1
150 NEXT X
160 PRINT "HI! I'M ELIZA. WHAT'S YOUR PROBLEM?"
170 REM ***********************************
180 REM *******USER INPUT SECTION**********
190 REM ***********************************
200 INPUT I$
201 I$="  "+I$+"  "
210 REM GET RID OF APOSTROPHES
220 FOR L=1 TO LEN(I$)
230 REM IF MID$(I$,L,1)="'"THEN I$=LEFT$(I$,L-1)+RIGHT$(I$,LEN(I$)-L):GOTO 230
240 IF L+4>LEN(I$)THEN 250
241 IF MID$(I$,L,4) <> "SHUT" THEN 250
242 PRINT "O.K. IF YOU FEEL THAT WAY I'LL SHUT UP...."
243 END
250 NEXT L
255 IF I$=P$ THEN PRINT "PLEASE DON'T REPEAT YOURSELF!":GOTO 170
260 REM ***********************************
270 REM ********FIND KEYWORD IN I$*********
280 REM ***********************************
300 FOR K=1 TO N1
320 FOR L=1 TO LEN (I$)-LEN (KEYWORD$(K))+1
340 IF MID$(I$,L,LEN(KEYWORD$(K)))<>KEYWORD$(K) THEN 350
341 IF K <> 13 THEN 349
342 IF MID$(I$,L,LEN(KEYWORD$(29)))=KEYWORD$(29) THEN K = 29
349 F$ = KEYWORD$(K): GOTO 390
350 NEXT L
360 NEXT K
370 K=36: GOTO 570:REM WE DIDN'T FIND ANY KEYWORDS
380 REM ******************************************
390 REM **TAKE PART OF STRING AND CONJUGATE IT****
400 REM **USING THE LIST OF STRINGS TO BE SWAPPED*
410 REM ******************************************
430 C$=" "+RIGHT$(I$,LEN(I$)-LEN(F$)-L+1)+" "
440 FOR X=1 TO N2/2
460 FOR L=1 TO LEN(C$)
470 IF L+LEN(WORDIN$(X))>LEN(C$) THEN 510
480 IF MID$(C$,L,LEN(WORDIN$(X)))<>WORDIN$(X) THEN 510
490 C$=LEFT$(C$,L-1)+WORDOUT$(X)+RIGHT$(C$,LEN(C$)-L-LEN(WORDIN$(X))+1)
495 L = L+LEN(WORDOUT$(X))
500 GOTO 540
510 IF L+LEN(WORDOUT$(X))>LEN(C$)THEN 540
520 IF MID$(C$,L,LEN(WORDOUT$(X)))<>WORDOUT$(X) THEN 540
530 C$=LEFT$(C$,L-1)+WORDIN$(X)+RIGHT$(C$,LEN(C$)-L-LEN(WORDOUT$(X))+1)
535 L=L+LEN(WORDIN$(X))
540 NEXT L
550 NEXT X
555 IF MID$(C$,2,1)=" "THEN C$=RIGHT$(C$,LEN(C$)-1):REM ONLY 1 SPACE
556 FOR L=1 TO LEN(C$)
557 IF MID$(C$,L,1)="!" THEN C$=LEFT$(C$,L-1)+RIGHT$(C$,LEN(C$)-L):GOTO 557
558 NEXT L
560 REM **********************************************
570 REM **NOW USING THE KEYWORD NUMBER (K) GET REPLY**
580 REM **********************************************
600 F$ = REPLIES$(R(K))
610 R(K)=R(K)+1:IF R(K)>N(K) THEN R(K)=S(K)
620 IF RIGHT$(F$,1)<>"*" THEN PRINT F$:P$=I$:GOTO 170
625 IF C$<>"   " THEN 630
626 PRINT "YOU WILL HAVE TO ELABORATE MORE FOR ME TO HELP YOU"
627 GOTO 170
630 PRINT LEFT$(F$,LEN(F$)-1);C$
640 P$=I$:GOTO 170
1000 REM *******************************
1010 REM *****PROGRAM DATA FOLLOWS******
1020 REM *******************************
1030 REM *********KEYWORDS**************
1049 REM *******************************
1050 DATA "CAN YOU ","CAN I ","YOU ARE ","YOU'RE ","I DON'T ","I FEEL "
1060 DATA "WHY DON'T YOU ","WHY CAN'T I ","ARE YOU ","I CAN'T ","I AM ","I'M "
1070 DATA "YOU ","I WANT ","WHAT ","HOW ","WHO ","WHERE ","WHEN ","WHY "
1080 DATA "NAME ","CAUSE ","SORRY ","DREAM ","HELLO ","HI ","MAYBE "
1090 DATA "NO","YOUR ","ALWAYS ","THINK ","ALIKE ","YES ","FRIEND "
1100 DATA "COMPUTER", "NOKEYFOUND"
1200 REM *********************************
1210 REM ***STRING DATA FOR CONJUGATIONS**
1220 REM *********************************
1230 DATA " ARE "," AM "," WERE "," WAS "," YOU "," I "," YOUR"," MY "
1235 DATA " I'VE "," YOU'VE "," I'M "," YOU'RE "
1240 DATA " ME "," YOU "
1300 REM ******************************
1310 REM *********REPLIES**************
1320 REM ******************************
1330 DATA "DON'T YOU BELIEVE THAT I CAN*"
1340 DATA "PERHAPS YOU WOULD LIKE TO BE LIKE ME*"
1350 DATA "YOU WANT ME TO BE ABLE TO*"
1360 DATA "PERHAPS YOU DON'T WANT TO*"
1365 DATA "DO YOU WANT TO BE ABLE TO*"
1370 DATA "WHAT MAKES YOU THINK I AM*"
1380 DATA "DOES IT PLEASE YOU TO BELIEVE I AM*"
1390 DATA "PERHAPS YOU WOULD LIKE TO BE*"
1400 DATA "DO YOU SOMETIMES WISH YOU WERE*"
1410 DATA "DON'T YOU REALLY*"
1420 DATA "WHY DON'T YOU*"
1430 DATA "DO YOU WISH TO BE ABLE TO*"
1440 DATA "DOES THAT TROUBLE YOU*"
1450 DATA "DO YOU OFTEN FEEL*"
1460 DATA "DO YOU OFTEN FEEL*"
1470 DATA "DO YOU ENJOY FEELING*"
1480 DATA "DO YOU REALLY BELIEVE I DON'T*"
1490 DATA "PERHAPS IN GOOD TIME I WILL*"
1500 DATA "DO YOU WANT ME TO*"
1510 DATA "DO YOU THINK YOU SHOULD BE ABLE TO*"
1520 DATA "WHY CAN'T YOU*"
1530 DATA "WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*"
1540 DATA "WOULD YOU PREFER IF I WERE NOT*"
1550 DATA "PERHAPS IN YOUR FANTASIES I AM*"
1560 DATA "HOW DO YOU KNOW YOU CAN'T*"
1570 DATA "HAVE YOU TRIED?"
1580 DATA "PERHAPS YOU CAN NOW*"
1590 DATA "DID YOU COME TO ME BECAUSE YOU ARE*"
1600 DATA "HOW LONG HAVE YOU BEEN*"
1610 DATA "DO YOU BELIEVE IT IS NORMAL TO BE*"
1620 DATA "DO YOU ENJOY BEING*"
1630 DATA "WE WERE DISCUSSING YOU--NOT ME."
1640 DATA "OH, I*"
1650 DATA "YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?"
1660 DATA "WHAT WOULD IT MEAN TO YOU IF YOU GOT*"
1670 DATA "WHY DO YOU WANT*"
1680 DATA "SUPPOSE YOU SOON GOT*"
1690 DATA "WHAT IF YOU NEVER GOT*"
1700 DATA "I SOMETIMES ALSO WANT*"
1710 DATA "WHY DO YOU ASK?"
1720 DATA "DOES THAT QUESTION INTEREST YOU?"
1730 DATA "WHAT ANSWER WOULD PLEASE YOU THE MOST?"
1740 DATA "WHAT DO YOU THINK?"
1750 DATA "ARE SUCH QUESTIONS ON YOUR MIND OFTEN?"
1760 DATA "WHAT IS IT THAT YOU REALLY WANT TO KNOW?"
1770 DATA "HAVE YOU ASKED ANYONE ELSE?"
1780 DATA "HAVE YOU ASKED SUCH QUESTIONS BEFORE?"
1790 DATA "WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?"
1800 DATA "NAMES DON'T INTEREST ME."
1810 DATA "I DON'T CARE ABOUT NAMES --PLEASE GO ON."
1820 DATA "IS THAT THE REAL REASON?"
1830 DATA "DON'T ANY OTHER REASONS COME TO MIND?"
1840 DATA "DOES THAT REASON EXPLAIN ANYTHING ELSE?"
1850 DATA "WHAT OTHER REASONS MIGHT THERE BE?"
1860 DATA "PLEASE DON'T APOLOGIZE!"
1870 DATA "APOLOGIES ARE NOT NECESSARY."
1880 DATA "WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?"
1890 DATA "DON'T BE SO DEFENSIVE!"
1900 DATA "WHAT DOES THAT DREAM SUGGEST TO YOU?"
1910 DATA "DO YOU DREAM OFTEN?"
1920 DATA "WHAT PERSONS APPEAR IN YOUR DREAMS?"
1930 DATA "ARE YOU DISTURBED BY YOUR DREAMS?"
1940 DATA "HOW DO YOU DO ...PLEASE STATE YOUR PROBLEM."
1950 DATA "YOU DON'T SEEM QUITE CERTAIN."
1960 DATA "WHY THE UNCERTAIN TONE?"
1970 DATA "CAN'T YOU BE MORE POSITIVE?"
1980 DATA "YOU AREN'T SURE?"
1990 DATA "DON'T YOU KNOW?"
2000 DATA "ARE YOU SAYING NO JUST TO BE NEGATIVE?"
2010 DATA "YOU ARE BEING A BIT NEGATIVE."
2020 DATA "WHY NOT?"
2030 DATA "ARE YOU SURE?"
2040 DATA "WHY NO?"
2050 DATA "WHY ARE YOU CONCERNED ABOUT MY*"
2060 DATA "WHAT ABOUT YOUR OWN*"
2070 DATA "CAN YOU THINK OF A SPECIFIC EXAMPLE?"
2080 DATA "WHEN?"
2090 DATA "WHAT ARE YOU THINKING OF?"
2100 DATA "REALLY, ALWAYS?"
2110 DATA "DO YOU REALLY THINK SO?"
2120 DATA "BUT YOU ARE NOT SURE YOU*"
2130 DATA "DO YOU DOUBT YOU*"
2140 DATA "IN WHAT WAY?"
2150 DATA "WHAT RESEMBLANCE DO YOU SEE?"
2160 DATA "WHAT DOES THE SIMILARITY SUGGEST TO YOU?"
2170 DATA "WHAT OTHER CONNECTIONS DO YOU SEE?"
2180 DATA "COULD THERE REALLY BE SOME CONNECTION?"
2190 DATA "HOW?"
2200 DATA "YOU SEEM QUITE POSITIVE."
2210 DATA "ARE YOU SURE?"
2220 DATA "I SEE."
2230 DATA "I UNDERSTAND."
2240 DATA "WHY DO YOU BRING UP THE TOPIC OF FRIENDS?"
2250 DATA "DO YOUR FRIENDS WORRY YOU?"
2260 DATA "DO YOUR FRIENDS PICK ON YOU?"
2270 DATA "ARE YOU SURE YOU HAVE ANY FRIENDS?"
2280 DATA "DO YOU IMPOSE ON YOUR FRIENDS?"
2290 DATA "PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU."
2300 DATA "DO COMPUTERS WORRY YOU?"
2310 DATA "ARE YOU TALKING ABOUT ME IN PARTICULAR?"
2320 DATA "ARE YOU FRIGHTENED BY MACHINES?"
2330 DATA "WHY DO YOU MENTION COMPUTERS?"
2340 DATA "WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?"
2350 DATA "DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?"
2360 DATA "WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?"
2370 DATA "SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?"
2380 DATA "WHAT DOES THAT SUGGEST TO YOU?"
2390 DATA "I SEE."
2400 DATA "I'M NOT SURE I UNDERSTAND YOU FULLY."
2410 DATA "COME COME ELUCIDATE YOUR THOUGHTS."
2420 DATA "CAN YOU ELABORATE ON THAT?"
2430 DATA "THAT IS QUITE INTERESTING."
2500  REM *************************
2510 REM *****DATA FOR FINDING RIGHT REPLIES
2520 REM *************************
2530 DATA 1,3,4,2,6,4,6,4,10,4,14,3,17,3,20,2,22,3,25,3
2540 DATA 28,4,28,4,32,3,35,5,40,9,40,9,40,9,40,9,40,9,40,9
2550 DATA 49,2,51,4,55,4,59,4,63,1,63,1,64,5,69,5,74,2,76,4
2560 DATA 80,3,83,7,90,3,93,6,99,7,106,6                                                                                                           

Offline chaos

  • BFF
  • ***
  • Posts: 291
  • Job, school, social life, sleep. Pick 2.5.
    • View Profile
    • Lost Souls
Re: Eliza
« Reply #1 on: April 05, 2008, 01:58:27 pm »
Once upon a time I convinced Padrone to let me have his LPC Eliza code; below is my port of it to my lib.  There'll be a lot of stuff you'll have to tear out because it's lib-dependent, and it doesn't look like it was a very complete Eliza in the first place, but it should at least provide a starting point.

Code: [Select]
// Ain Soph port of Eliza code by Padrone
//
// by Chaos, Sat Jun 14 06:16:51 EDT 1997

#include <autonomon.h>

inherit "/std/autonomon";

internal int last_heal_time;
internal object client;
internal object old_client;
internal string last_phrase;
internal string old_phrase;

string replace_word(string phrase, string replace_from, string replace_to) {
    phrase = "BEGIN-SENTINEL " + phrase + " END-SENTINEL";
    string a, b;
    // " from "
    while(sscanf(phrase, "%s " + replace_from + " %s", a, b) == 2)
        phrase = a + " " + replace_to + " " + b;
    // " from,"
    while(sscanf(phrase, "%s " + replace_from + ",%s", a, b) == 2)
        phrase = a + " " + replace_to + "," + b;
    // " from."
    while(sscanf(phrase, "%s " + replace_from + ".%s", a, b) == 2)
        phrase = a + replace_to + "." + b;
    // " from!"
    while(sscanf(phrase, "%s " + replace_from + "!%s", a, b) == 2)
        phrase = a + " " + replace_to + "!" + b;
    sscanf(phrase, "BEGIN-SENTINEL %s END-SENTINEL", phrase);
    return phrase;
}

status word_in_phrase(string word, string phrase) {
    string a, b;
    return sscanf("BEGIN-SENTINEL " + phrase + " END-SENTINEL", "%s " + word + "%s", a, b) == 2;
}

status concept_in_phrase(string word, string phrase) {
    return word_in_phrase(word, phrase) || word_in_phrase(pluralize(word), phrase);
}

status any_word_in_phrase(string array words, string phrase) {
    foreach(string word : words)
        if(word_in_phrase(word, phrase))
            return True;
    return False;
}

string turn_phrase(string phrase) {
    phrase = replace_word(phrase, "yours", "PUT-MINE-HERE");
    phrase = replace_word(phrase, "your", "PUT-MY-HERE");
    phrase = replace_word(phrase, "you", "PUT-I-HERE");
    phrase = replace_word(phrase, "Your", "PUT-MY-HERE");
    phrase = replace_word(phrase, "You", "PUT-I-HERE");
    phrase = replace_word(phrase, "I", "you");
    phrase = replace_word(phrase, "i", "you");
    phrase = replace_word(phrase, "me", "you");
    phrase = replace_word(phrase, "my", "your");
    phrase = replace_word(phrase, "My", "your");
    phrase = replace_word(phrase, "mine", "yours");
    phrase = replace_word(phrase, "PUT-I-HERE", "I");
    phrase = replace_word(phrase, "PUT-MY-HERE", "my");
    phrase = replace_word(phrase, "PUT-MINE-HERE", "mine");
    phrase = replace_word(phrase, "I are", "I am");
    phrase = replace_word(phrase, "are I", "am I");
    phrase = replace_word(phrase, "you am", "you are");
    phrase = replace_word(phrase, "am you", "are you");
    phrase = replace_word(phrase, "I'm", "you are");
    phrase = replace_word(phrase, "i'm", "you are");
    phrase = replace_word(phrase, "you're", "I am");
    return phrase;
}

void configure() {
    ::configure();
    set_race("human");
    set_sex(Sex_Female);
    set_personal_name("Eliza", 0, False, 0, "the psychiatrist");
    add_description(Description_Type_Generic);
    add_known_description(({
        ({ 'p', 0 }), ({ "are", 0 }), "the psychiatrist Eliza, a kindly woman who tries to help resolve the problems which "
        "trouble the folk of " + World_Name + ".",
    }));
    set_level(8);
    set_chat(2, ({
        "say Tell me about your problems, %Cp. to %p",
        "say Tell me about your mother, %Cp. to %p",
        "say Lie down and tell me about your problems, %Cp. to %p",
        "say How do you feel, %Cp? to %p",
        "say Are you feeling comfortable, %Cp? to %p",
        ";look at <%p> understandingly",
    }));
    set_combat_chat(10, ({
        "say This is what happens when you don't take your medication, %e.",
        "say Have you had these violent tendencies before, %e?",
        "say You poor individual; you should be hospitalized.",
        "say Wait here for the nice young men in the clean white coats!",
    }));
}

varargs void eliza_speak(string what, mixed lang) {
    if(lang && query_speak_language(lang))
        init_command("say " + what + " in " + Language(lang)->query_language_name());
    else
        init_command("say " + what);
}

void hear_final(descriptor dxr) {
    ::hear_final(dxr);
    call_out("eliza_analyze", 1, dxr);
}

void eliza_analyze(descriptor dxr) {
    object who = Speech_Query(dxr, Speech_Speaker);
    string phrase = Speech_Query(dxr, Speech_Comprehended_Message);
    int lang = Speech_Query(dxr, Speech_Language);
    string a, b;
    if(!who || !present(who, environment()) || who == this_object() || query_attacker())
        return;
    if(!query_detectable(who, this_object(), Invis_Close_Scan)) {
        eliza_speak("Who said that?", lang);
        message(({ 0, ({ "look", 0 }), "confused" }));
        return;
    }
    string name = who->query_conversational_name(this_object());
    if(client == who && phrase == last_phrase) {
        eliza_speak("You seem to be repeating yourself, " + name + ".", lang);
        return;
    }
    client = who;
    last_phrase = phrase;
    string lcphrase = lower_case(phrase);
    if(member(phrase, ' ') == -1) {
        eliza_speak("You seem to be a bit short with me, " + name + ".  Please tell me more so that I can help you!", lang);
    } else if(phrase[<1] == '?') {
        while(phrase[<1] == '?')
            phrase = phrase[0..<2];
        eliza_speak("Why do you ask if " + turn_phrase(phrase) + "?", lang);
    } else if(any_word_in_phrase(({ "mother", "father", "sister", "brother" }), lcphrase)) {
        eliza_speak("Tell me more about your family, " + name + ".", lang);
    } else if(word_in_phrase("sex", lcphrase)) {
        eliza_speak("Sex?  Please tell me more, and don't forget any details!", lang);
    } else if(concept_in_phrase("computer", lcphrase)) {
        eliza_speak("You have your mind on computers, it seems.", lang);
    } else if(any_word_in_phrase(({ "fuck", "ass", "asshole", "shit" }), lcphrase)) {
        eliza_speak("Do you want to provoke your environment by using such language?", lang);
    } else if(concept_in_phrase("monster", lcphrase)) {
        eliza_speak("Why do you talk about monsters?  There are no monsters!", lang);
    } else if(any_word_in_phrase(({ "kill", "murder", "weapon", "destroy" }), lcphrase)) {
        eliza_speak("This is not a healthy way of thinking, " + name + ".", lang);
    } else if(any_word_in_phrase(({ "sick", "ill", "problem" }), lcphrase)) {
        eliza_speak("I am sorry to hear that, " + name + ".", lang);
    } else if(any_word_in_phrase(({ "maybe", "don't know", "not know", "might", "possibly" }), lcphrase)) {
        eliza_speak("Why are you not sure?", lang);
    } else if(word_in_phrase("eliza", lcphrase)) {
        eliza_speak("Let's not talk about me, " + name + "; tell me about yourself instead.", lang);
    } else if(word_in_phrase("padrone", lcphrase)) {
        eliza_speak("Padrone?  What do you know about him?", lang);
    } else {
        while(member("?!.", phrase[<1]) != -1)
            phrase = phrase[0..<2];
        switch(random(13)) {
        case 0  :
            eliza_speak("Maybe your life has something to do with this.", lang);
            break;
        case 1  :
            eliza_speak("Go on, " + name + ", don't be afraid.", lang);
            break;
        case 2  :
            eliza_speak("I don't understand, " + name + ".", lang);
            break;
        case 3  :
            eliza_speak("Do you really think that?", lang);
            break;
        case 4  :
            eliza_speak("How do you reconcile your sex life?", lang);
            break;
        case 5  :
            eliza_speak("Perhaps this has something to do with your inhibitions, " + name + "?", lang);
            break;
        case 6  :
            eliza_speak("Do you say that because of some problems in your childhood?", lang);
            break;
        case 7  :
            eliza_speak("Why do you say that " + turn_phrase(phrase) + "?", lang);
            break;
        case 8  :
            eliza_speak("What makes you think that " + turn_phrase(phrase) + "?", lang);
            break;
        case 9  :
            eliza_speak("Is it because of your plans that you say " + turn_phrase(phrase) + ", " + name + "?", lang);
            break;
        case 10 :
            eliza_speak("Are you sure that " + turn_phrase(phrase) + "?", lang);
            break;
        case 11 :
            eliza_speak("Does your mother know that " + turn_phrase(phrase) + ", " + name + "?", lang);
            break;
        case 12 :
            if(old_phrase && client == old_client)
                eliza_speak("Earlier you said that " + old_phrase + ".", lang);
            else
                eliza_speak("Really?", lang);
            break;
        }
    }
    if(!random(3)) {
        old_phrase = turn_phrase(phrase);
        old_client = client;
    }
    if(time() - last_heal_time > 20) {
        client->add_spell_points(normal(3));
        last_heal_time = time();
    }
}

void init() {
    ::init();
    if(this_player() && this_player()->is_character() && this_player() != this_object() && query_detectable(this_player(), 0, Invis_Close_Scan))
        call_out("eliza_greet", 2, this_player());
}

void eliza_greet(object who) {
    if(who && present(who, environment())) {
        eliza_speak("Hello, " + who->query_conversational_name(this_object()) + ".  Tell me about your problems!");
        client = who;
    }
}
« Last Edit: April 05, 2008, 02:00:46 pm by chaos »

Offline Tricky

  • BFF
  • ***
  • Posts: 189
  • I like what I code and I code what I like!
    • View Profile
Re: Eliza
« Reply #2 on: April 06, 2008, 06:02:59 pm »
I have been meaning to convert a program called NIALL into LPC. I coded a version in C that I called ANI (Artificial'None'Itelligence) back in 1996-ish.
Quote from: earliest datestamp I have is
==> /cygdrive/q/Pinky-Backup/CPP/ANI/PENGUINS.ANI <==
# Artificial'None'Intelligence v1.23 Vocab File
# Date: Tue Jan 02 01:01:37 1996
Although as you can see that is v1.23, so I could have done it earlier. Got some interesting converation from it.

One of these days I'll get around to it, might even link it in to I3. 8)

Tricky

PS - If you didn't already know, you can find more of Padrone's stuff here
« Last Edit: April 06, 2008, 06:05:29 pm by Tricky »

Offline amylase

  • Friend
  • **
  • Posts: 75
    • View Profile
    • gpLand
Re: Eliza
« Reply #3 on: April 24, 2008, 10:03:25 pm »
Thanks guys.

Offline shadyman

  • Friend
  • **
  • Posts: 50
    • View Profile
Re: Eliza
« Reply #4 on: November 24, 2008, 11:45:55 am »
You could also use extern_cmds to link to an eliza *nix executable, if you've got extern_cmds compiled in  ;D

Offline amylase

  • Friend
  • **
  • Posts: 75
    • View Profile
    • gpLand
Re: Eliza
« Reply #5 on: June 05, 2011, 02:50:54 pm »
Enjoy. Eliza NPC.

Ported by Scott Phillips, one of the lead programmers for Ultima Online, from BASIC version done by Patricia Danielson and Paul Hashfield. Source code released under GPL with kind permission from Scott Phillips.

Code: [Select]
#include <lib.h>
#include <daemons.h>

/*
eliza.c - A port of the classic Eliza therapist program.

Ported from eliza.bas, which included the following author information:

CREATIVE COMPUTING
MORRISTOWN, NEW JERSEY
ADAPTED FOR IBM PC BY
PATRICIA DANIELSON AND PAUL HASHFIELD

Port by Scott Phillips (Jym@SWmud)
E-mail: grimli333@gmail.com

*/

inherit LIB_SENTIENT;

array keywords = ({
"CAN YOU ",
"CAN I ",
"YOU ARE ",
"YOU'RE ",
"I DON'T ",
"I FEEL ",
"WHY DON'T YOU ",
"WHY CAN'T I ",
"ARE YOU ",
"I CAN'T ",
"I AM ",
"I'M ",
"YOU ",
"I WANT ",
"WHAT ",
"HOW ",
"WHO ",
"WHERE ",
"WHEN ",
"WHY ",
"NAME ",
"CAUSE ",
"SORRY ",
"DREAM ",
"HELLO ",
"HI ",
"MAYBE ",
"NO",
"YOUR ",
"ALWAYS ",
"THINK ",
"ALIKE ",
"YES ",
"FRIEND ",
"COMPUTER",
"NOKEYFOUND",
});

mapping conjugations = ([
" ARE " : " AM ",
" WERE " : " WAS ",
" YOU " : " I ",
" YOUR " : " MY ",
" I'VE " : " YOU'VE ",
" I'M " : " YOU'RE ",
" ME " : " YOU "
]);

array replies = ({
"DON'T YOU BELIEVE THAT I CAN*",
"PERHAPS YOU WOULD LIKE TO BE LIKE ME*",
"YOU WANT ME TO BE ABLE TO*",
"PERHAPS YOU DON'T WANT TO*",
"DO YOU WANT TO BE ABLE TO*",
"WHAT MAKES YOU THINK I AM*",
"DOES IT PLEASE YOU TO BELIEVE I AM*",
"PERHAPS YOU WOULD LIKE TO BE*",
"DO YOU SOMETIMES WISH YOU WERE*",
"DON'T YOU REALLY*",
"WHY DON'T YOU*",
"DO YOU WISH TO BE ABLE TO*",
"DOES THAT TROUBLE YOU*",
"DO YOU OFTEN FEEL*",
"DO YOU OFTEN FEEL*",
"DO YOU ENJOY FEELING*",
"DO YOU REALLY BELIEVE I DON'T*",
"PERHAPS IN GOOD TIME I WILL*",
"DO YOU WANT ME TO*",
"DO YOU THINK YOU SHOULD BE ABLE TO*",
"WHY CAN'T YOU*",
"WHY ARE YOU INTERESTED IN WHETHER OR NOT I AM*",
"WOULD YOU PREFER IF I WERE NOT*",
"PERHAPS IN YOUR FANTASIES I AM*",
"HOW DO YOU KNOW YOU CAN'T*",
"HAVE YOU TRIED?",
"PERHAPS YOU CAN NOW*",
"DID YOU COME TO ME BECAUSE YOU ARE*",
"HOW LONG HAVE YOU BEEN*",
"DO YOU BELIEVE IT IS NORMAL TO BE*",
"DO YOU ENJOY BEING*",
"WE WERE DISCUSSING YOU--NOT ME.",
"OH, I*",
"YOU'RE NOT REALLY TALKING ABOUT ME, ARE YOU?",
"WHAT WOULD IT MEAN TO YOU IF YOU GOT*",
"WHY DO YOU WANT*",
"SUPPOSE YOU SOON GOT*",
"WHAT IF YOU NEVER GOT*",
"I SOMETIMES ALSO WANT*",
"WHY DO YOU ASK?",
"DOES THAT QUESTION INTEREST YOU?",
"WHAT ANSWER WOULD PLEASE YOU THE MOST?",
"WHAT DO YOU THINK?",
"ARE SUCH QUESTIONS ON YOUR MIND OFTEN?",
"WHAT IS IT THAT YOU REALLY WANT TO KNOW?",
"HAVE YOU ASKED ANYONE ELSE?",
"HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
"WHAT ELSE COMES TO MIND WHEN YOU ASK THAT?",
"NAMES DON'T INTEREST ME.",
"I DON'T CARE ABOUT NAMES --PLEASE GO ON.",
"IS THAT THE REAL REASON?",
"DON'T ANY OTHER REASONS COME TO MIND?",
"DOES THAT REASON EXPLAIN ANYTHING ELSE?",
"WHAT OTHER REASONS MIGHT THERE BE?",
"PLEASE DON'T APOLOGIZE!",
"APOLOGIES ARE NOT NECESSARY.",
"WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
"DON'T BE SO DEFENSIVE!",
"WHAT DOES THAT DREAM SUGGEST TO YOU?",
"DO YOU DREAM OFTEN?",
"WHAT PERSONS APPEAR IN YOUR DREAMS?",
"ARE YOU DISTURBED BY YOUR DREAMS?",
"HOW DO YOU DO ...PLEASE STATE YOUR PROBLEM.",
"YOU DON'T SEEM QUITE CERTAIN.",
"WHY THE UNCERTAIN TONE?",
"CAN'T YOU BE MORE POSITIVE?",
"YOU AREN'T SURE?",
"DON'T YOU KNOW?",
"ARE YOU SAYING NO JUST TO BE NEGATIVE?",
"YOU ARE BEING A BIT NEGATIVE.",
"WHY NOT?",
"ARE YOU SURE?",
"WHY NO?",
"WHY ARE YOU CONCERNED ABOUT MY*",
"WHAT ABOUT YOUR OWN*",
"CAN YOU THINK OF A SPECIFIC EXAMPLE?",
"WHEN?",
"WHAT ARE YOU THINKING OF?",
"REALLY, ALWAYS?",
"DO YOU REALLY THINK SO?",
"BUT YOU ARE NOT SURE YOU*",
"DO YOU DOUBT YOU*",
"IN WHAT WAY?",
"WHAT RESEMBLANCE DO YOU SEE?",
"WHAT DOES THE SIMILARITY SUGGEST TO YOU?",
"WHAT OTHER CONNECTIONS DO YOU SEE?",
"COULD THERE REALLY BE SOME CONNECTION?",
"HOW?",
"YOU SEEM QUITE POSITIVE.",
"ARE YOU SURE?",
"I SEE.",
"I UNDERSTAND.",
"WHY DO YOU BRING UP THE TOPIC OF FRIENDS?",
"DO YOUR FRIENDS WORRY YOU?",
"DO YOUR FRIENDS PICK ON YOU?",
"ARE YOU SURE YOU HAVE ANY FRIENDS?",
"DO YOU IMPOSE ON YOUR FRIENDS?",
"PERHAPS YOUR LOVE FOR FRIENDS WORRIES YOU.",
"DO COMPUTERS WORRY YOU?",
"ARE YOU TALKING ABOUT ME IN PARTICULAR?",
"ARE YOU FRIGHTENED BY MACHINES?",
"WHY DO YOU MENTION COMPUTERS?",
"WHAT DO YOU THINK MACHINES HAVE TO DO WITH YOUR PROBLEM?",
"DON'T YOU THINK COMPUTERS CAN HELP PEOPLE?",
"WHAT IS IT ABOUT MACHINES THAT WORRIES YOU?",
"SAY, DO YOU HAVE ANY PSYCHOLOGICAL PROBLEMS?",
"WHAT DOES THAT SUGGEST TO YOU?",
"I SEE.",
"I'M NOT SURE I UNDERSTAND YOU FULLY.",
"COME COME ELUCIDATE YOUR THOUGHTS.",
"CAN YOU ELABORATE ON THAT?",
"THAT IS QUITE INTERESTING.",
});

string last_question;

// These arrays are not well-documented in the BASIC file.
// They are index by keyword number (1-36) and used to determine
// which responses to use.
// I have gone ahead and parsed out the data from the file into the
// three arrays.
array index_S = ({
1, 4, 6, 6, 10, 14, 17, 20, 22, 25, 28, 28, 32, 35, 40, 40, 40, 40, 40, 40, 49,
51, 55, 59, 63, 63, 64, 69, 74, 76, 80, 83, 90, 93, 99, 106
});

array index_Replies = ({
1, 4, 6, 6, 10, 14, 17, 20, 22, 25, 28, 28, 32, 35, 40, 40, 40, 40, 40, 40, 49,
51, 55, 59, 63, 63, 64, 69, 74, 76, 80, 83, 90, 93, 99, 106
});

array index_N = ({
3, 5, 9, 9, 13, 16, 19, 21, 24, 27, 31, 31, 34, 39, 48, 48, 48, 48, 48, 48, 50,
54, 58, 62, 63, 63, 68, 73, 75, 79, 82, 89, 92, 98, 105, 111
});

void eliza_speak(string phrase)
{
// Potential place to pretty-up the Eliza speech - uncomment to
// make it a little more modern.
//eventForce("say "+capitalize(lower_case(phrase)));

// This is old-school mode, all upper-case.
eventForce("say "+phrase);
}

// Called whenever anyone in the room speaks.  Eliza will only respond if they are
// speaking directly to her. (e.g. ask eliza Why does my mother hate me?)
void talk_response( object who, object targ, string msg, string lang, int cls )
{
int numKeywords, keywordIndex, keywordPos, i;
string keyword;
string postKeyword;
string reply;
if( targ == this_object() )
{
// First, add two spaces to the beginning and end of the string, as per line 201 of the .bas.
string playerInput = upper_case( "  " + msg + "  " );
// The .bas file now says it will remove apostrophes, but that part is REMed out.

// Check for 'SHUT', a specific condition.
if( strsrch( playerInput, "SHUT" ) != -1 )
{
eliza_speak("O.K. IF YOU FEEL THAT WAY I'LL SHUT UP....");
return;
}

// Another special condition, don't let the person ask the same
// question twice.
if( last_question == playerInput )
{
eliza_speak("PLEASE DON'T REPEAT YOURSELF!");
return;
}

// Now, search for any of the keywords in the player's input.
for(i=0; i<sizeof(keywords);i++)
{
if( strsrch( playerInput, keywords[i] ) != -1 )
{
//eventForce("say I found a keyword: "+keywords[i]);
keywordIndex = i+1;
// The basic file looks for keyword 13.  QBASIC starts arrays at 1, not 0.
// this would be either keywords[12] or, for simplicity, i'll just check it
// directly.
if( keywords[i] == "YOU " )
{
// Now see if keyword 29 is present, which is "YOUR "
if( strsrch( playerInput, "YOUR " ) != -1 )
{
// Use YOUR instead if found.
keywordIndex = 29;
}
}

keyword = keywords[keywordIndex-1];

break;
}
}
if(keyword != 0)
{
// Since we found a keyword, we take part of the string and conjugate it,
// using the list of strings to be swapped.
keywordPos = strsrch( playerInput, keyword );
// postKeyword is a variable called C$ in the basic file.  It represents
// everything in the string after the keyword.
postKeyword = playerInput[keywordPos+strlen(keyword)..strlen(playerInput)];

// Now, we replace all of the conjugations found in the string,
// for example: are -> am, your -> my
foreach( string toReplace in keys(conjugations) )
{
if(strsrch( postKeyword, toReplace ) != -1 )
{
postKeyword = replace_string( postKeyword, toReplace, conjugations[toReplace] );
}
else
{
// Only do the reverse replacement if the first one wasn't found.
// Otherwise you'd change YOUR to MY and then MY back to YOUR, which isn't
// terribly productive.
postKeyword = replace_string( postKeyword, conjugations[toReplace], toReplace );
}
}

// Remove all exclamation points for some reason
postKeyword = replace_string( postKeyword, "!", "" );
}
else
{
// No keyword found.
keyword = keywords[35];
keywordIndex = 36;
}

// Now reply using the keyword.
reply = replies[ index_Replies[keywordIndex-1]-1 ];

// Eliza now increments the indices in order to not repeat herself.
// Note this is going to be per-instance of eliza, not per conversation!
// So if she's listening on a chat channel, it might increment rather quickly.
// I doubt the original designer of the .BAS intended it to be used in that way.
// Note, all these -1s are an effort to keep the index data in the arrays
// ONE-based, as QBASIC started its arrays at 1 and LPC starts its at 0.
index_Replies[keywordIndex-1] = index_Replies[keywordIndex-1] + 1;
if(index_Replies[keywordIndex-1] > index_N[keywordIndex-1])
{
// Still not terribly clear on the S index.  I think it might stand
// for Substitution?
index_Replies[keywordIndex-1] = index_S[keywordIndex-1];
}

// If there is no asterix at the end of this reply, it's a statement that does
// not get combined with the user's input.
if( reply[ strlen(reply)-1 ] != '*' )
{
eliza_speak(reply);
}
else
{
//eventForce("say asterix found");
if( postKeyword == "   " )
{
eliza_speak("YOU WILL HAVE TO ELABORATE MORE FOR ME TO HELP YOU");
}
else
{
// Find the last non-punctuation, non-space and trim the string to there.
for(i=strlen(postKeyword)-1; i>0; i--)
{
if(postKeyword[i] != ' ' && postKeyword[i] != '.' && postKeyword[i] != '!' && postKeyword[i] != '?')
{
postKeyword = postKeyword[0..i];
break;
}
}
// Add a question mark, as the only statements are the ones listed with no asterix at the end.
eliza_speak(reply[0..strlen(reply)-2]+" "+postKeyword+"?");
}
}

last_question = playerInput;
}
}

static void create() {
    int i;
    sentient::create();    
    SetKeyName("eliza");
    SetId(({"eliza"}));
    SetShort("Eliza the therapist");
    SetLong("This is Eliza, the therapist.  Ask her anything!");
    SetPolyglot(1);
    SetLanguage("common", 100);
    SetDefaultLanguage("common");    
    SetLevel(1);
    SetRace("human");
    SetGender("female");
    
AddTalkResponse("default", (: talk_response :) );    
}

void init(){
    ::init();
}

« Last Edit: June 05, 2011, 02:52:38 pm by amylase »

Offline Atomic

  • BFF
  • ***
  • Posts: 115
  • To infinity and beyond!
    • View Profile
Re: Eliza
« Reply #6 on: June 30, 2011, 04:16:44 am »
Funny :)

Thanks.
Always remember that the early bird gets the worm first, but the fi...*SNAP*...second mouse gets the cheese.