--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/eliza.php Mon Aug 25 12:34:26 2008 -0400
@@ -0,0 +1,626 @@
+<?php
+
+/**
+ * Implementation of ELIZA in PHP. Ported from Javascript by Dan Fuhry
+ * Chat Bot by George Dunlop, www.peccavi.com
+ * May be used/modified if credit line is retained
+ * @author George Dunlop <http://www.peccavi.com/>
+ * @author Dan Fuhry <dan@enanocms.org>
+ * @copyright (c) 1997-2008 George Dunlop. All rights reserved, portions copyright (C) 2008 Dan Fuhry.
+ */
+
+class Psychotherapist
+{
+ private $maxKey = 36;
+ private $keyNotFound = 0;
+ private $keyword = array();
+ private $maxresponses = 116;
+ private $response = array();
+
+ private $maxConj = 19;
+ private $max2ndConj = 7;
+
+ private $conj1 = Array();
+ private $conj2 = Array();
+ private $conj3 = Array();
+ private $conj4 = Array();
+
+ private $punct = Array(".", ",", "!", "?", ":", ";", "&", '"', "@", "#", "(", ")" );
+
+ /**
+ * Constructor.
+ */
+
+ public function __construct()
+ {
+ $this->keyNotFound = $this->maxKey - 1;
+ $this->keyword = $this->create_array($this->maxKey);
+ $this->response = $this->create_array($this->maxresponses);
+ $this->conj1 = $this->create_array($this->maxConj);
+ $this->conj2 = $this->create_array($this->maxConj);
+ $this->conj3 = $this->create_array($this->max2ndConj);
+ $this->conj4 = $this->create_array($this->max2ndConj);
+
+ $this->table_setup();
+ }
+
+ /**
+ * Replacement for str_replace that provides more options.
+ * if type == 0 straight string replacement
+ * if type == 1 assumes padded strings and replaces whole words only
+ * if type == 2 non case sensitive assumes padded strings to compare whole word only
+ * if type == 3 non case sensitive straight string replacement
+ * @param string Haystack
+ * @param string Needle
+ * @param string Replacement
+ * @param int Mode - defaults to 0
+ */
+
+ private function replaceStr($strng, $substr1, $substr2, $type = 0)
+ {
+ if ( $type == 0 )
+ {
+ return str_replace($substr1, $substr2, $strng);
+ }
+ else if ( $type == 1 )
+ {
+ return str_replace(" $substr1 ", " $substr2 ", $strng);
+ }
+ else if ( $type == 2 || $type == 3 )
+ {
+ if ( $type == 2 )
+ {
+ $substr1 = " $substr1 ";
+ $substr2 = " $substr2 ";
+ }
+ return preg_replace('/' . preg_quote($substr1) . '/i', $substr2, $strng);
+ }
+ else
+ {
+ throw new Exception("Invalid parameter");
+ }
+ }
+
+ /**
+ * Function to pad a string. head, tail & punctuation
+ * @param string
+ * @return string
+ */
+
+ private function padString($strng)
+ {
+ $punct =& $this->punct;
+
+ $aString = " " . $strng . " ";
+ for ( $i = 0; $i < count($punct); $i++ )
+ {
+ $aString = $this->replaceStr( $aString, $punct[$i], " " . $punct[$i] . " ", 0 );
+ }
+ return $aString;
+ }
+
+ /**
+ * Function to strip padding
+ */
+
+ private function unpadString($strng)
+ {
+ $punct =& $this->punct;
+
+ $aString = $strng;
+ $aString = $this->replaceStr( $aString, " ", " ", 0 ); // compress spaces
+
+ $aString = trim($aString, ' ');
+
+ for ( $i = 0; $i < count($punct); $i++ )
+ {
+ $aString = $this->replaceStr( $aString, " " . $punct[$i], $punct[$i], 0 );
+ }
+ return $aString;
+ }
+
+ /**
+ * Dress Input formatting i.e leading & trailing spaces and tail punctuation
+ * @param string
+ * @return string
+ */
+
+ function strTrim($strng)
+ {
+ static $ht = 0;
+
+ if ( $ht == 0 )
+ {
+ $loc = 0;
+ } // head clip
+ else
+ {
+ $loc = strlen($strng) - 1;
+ } // tail clip ht = 1
+ if ( substr($strng, $loc, 1) == " " )
+ {
+ $aString = substr($strng, - ( $ht - 1 ), strlen($strng) - $ht);
+ $aString = $this->strTrim($aString);
+ }
+ else
+ {
+ $flg = false;
+ for ( $i = 0; $i <= 5; $i++ )
+ {
+ $flg = $flg || ( substr($strng, $loc, 1) == $this->punct[$i]);
+ }
+ if ( $flg )
+ {
+ $aString = substr($strng, - ( $ht - 1 ), strlen($strng) - $ht);
+ }
+ else
+ {
+ $aString = $strng;
+ }
+ if ( $aString != $strng )
+ {
+ $aString = $this->strTrim($aString);
+ }
+ }
+ if ( $ht == 0 )
+ {
+ $ht = 1;
+ $aString = $this->strTrim($aString);
+ }
+ else
+ {
+ $ht = 0;
+ }
+ return $aString;
+ }
+
+ /**
+ * adjust pronouns and verbs & such
+ * @param string
+ * @return string
+ */
+
+ private function conjugate($sStrg)
+ {
+ $sString = $sStrg;
+ for ( $i = 0; $i < $this->maxConj; $i++ )
+ { // decompose
+ $sString = $this->replaceStr( $sString, $this->conj1[$i], "#@&" . $i, 2 );
+ }
+ for( $i = 0; $i < $this->maxConj; $i++ )
+ { // recompose
+ $sString = $this->replaceStr( $sString, "#@&" . $i, $this->conj2[$i], 2 );
+ }
+ // post process the resulting string
+ for( $i = 0; $i < $this->max2ndConj; $i++ )
+ { // decompose
+ $sString = $this->replaceStr( $sString, $this->conj3[$i], "#@&" . $i, 2 );
+ }
+ for( $i = 0; $i < $this->max2ndConj; $i++ )
+ { // recompose
+ $sString = $this->replaceStr( $sString, "#@&" . $i, $this->conj4[$i], 2 );
+ }
+ return $sString;
+ }
+
+ /**
+ * Build our response string
+ * get a random choice of response based on the key
+ * Then structure the response
+ * @param string
+ * @param int Key index
+ * @return string
+ */
+
+ function phrase( $sString, $keyidx )
+ {
+ $idxmin = $this->keyword[$keyidx]->idx;
+ $idrange = $this->keyword[$keyidx]->end - $idxmin + 1;
+ while ( $pass < 5 )
+ {
+ $choice = $this->keyword[$keyidx]->idx + mt_rand(0, $idrange);
+ if ( $choice == $this->keyword[$keyidx]->last )
+ {
+ $pass++;
+ continue;
+ }
+ break;
+ }
+ $this->keyword[$keyidx]->last = $choice;
+ $rTemp = $this->response[$choice];
+ $tempt = substr($rTemp, strlen($rTemp) - 1, 1);
+ if ( ( $tempt == "*" ) || ( $tempt == "@" ) )
+ {
+ $sTemp = $this->padString($sString);
+ $wTemp = strtoupper($sTemp);
+ $strpstr = intval(strpos($wTemp, " {$this->keyword[$keyidx]->key} "));
+
+ $strpstr += strlen($this->keyword[$keyidx]->key) + 1;
+ $thisstr = $this->conjugate( substr($sTemp, $strpstr, strlen($sTemp)) );
+ $thisstr = $this->strTrim( $this->unpadString($thisstr) );
+ if( $tempt == "*" )
+ {
+ $sTemp = $this->replaceStr( $rTemp, "<*", " " . $thisstr . "?", 0 );
+ }
+ else
+ {
+ $sTemp = $this->replaceStr( $rTemp, "<@", " " . $thisstr . ".", 0 );
+ }
+ }
+ else
+ {
+ $sTemp = $rTemp;
+ }
+ return $sTemp;
+ }
+
+ /**
+ * returns array index of first key found
+ * @param string
+ */
+
+ private function testkey($wString)
+ {
+ for ( $keyid = 0; $keyid < count($this->keyword); $keyid++ )
+ {
+ if ( strpos($wString, " {$this->keyword[$keyid]->key} ") !== false )
+ {
+ return $keyid;
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ */
+
+ private function findkey($wString)
+ {
+ $keyid = $this->testkey($wString);
+ if( !$keyid )
+ {
+ $keyid = $this->keyNotFound;
+ }
+ return $keyid;
+ }
+
+ /**
+ * Process a line from the user.
+ * @param string User input
+ * @return string AI output
+ */
+
+ function listen($User)
+ {
+ static $wTopic = ""; // Last worthy responce
+ static $sTopic = ""; // Last worthy responce
+ static $greet = false;
+ static $wPrevious = ""; // so we can check for repeats
+
+ $sInput = $User;
+ $sInput = $this->strTrim($sInput); // dress input formating
+
+ if ( $sInput != "" )
+ {
+ $wInput = $this->padString(strtoupper($sInput)); // Work copy
+ $foundkey = $this->maxKey; // assume it's a repeat input
+ if ( $wInput != $wPrevious )
+ { // check if user repeats himself
+ $foundkey = $this->findkey($wInput); // look for a keyword.
+ }
+ if( $foundkey == $this->keyNotFound )
+ {
+ if( !$greet )
+ {
+ $greet = true;
+ return "Don't you ever say Hello?";
+ }
+ else
+ {
+ $wPrevious = $wInput; // save input to check repeats
+ if (( strlen($sInput) < 10 ) && ( $wTopic != "" ) && ( $wTopic != $wPrevious ))
+ {
+ $lTopic = $this->conjugate( $sTopic );
+ $sTopic = "";
+ $wTopic = "";
+ return 'OK... "' + $lTopic + '". Tell me more.';
+ }
+ else
+ {
+ if ( strlen($sInput) < 15 )
+ {
+ return "Tell me more...";
+ }
+ else
+ {
+ return $this->phrase( $sInput, $foundkey );
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( strlen($sInput) > 12 )
+ {
+ $sTopic = $sInput;
+ $wTopic = $wInput;
+ }
+ $greet = true;
+ $wPrevious = $wInput; // save input to check repeats
+ return $this->phrase( $sInput, $foundkey ); // Get our response
+ }
+ }
+ else
+ {
+ return "I can't help if you will not chat with me!";
+ }
+ }
+
+ /**
+ * Creates an array of the specified length, and fills it with null values.
+ * @param int Array size
+ * @return array
+ */
+
+ function create_array($len)
+ {
+ $ret = array();
+ for ( $i = 0; $i < $len; $i++ )
+ {
+ $ret[] = null;
+ }
+ return $ret;
+ }
+
+ /**
+ * Sets up the tables of phrases, etc.
+ */
+
+ private function table_setup()
+ {
+ // build our data base here
+
+ $this->conj1[0] = "are"; $this->conj2[0] = "am";
+ $this->conj1[1] = "am"; $this->conj2[1] = "are";
+ $this->conj1[2] = "were"; $this->conj2[2] = "was";
+ $this->conj1[3] = "was"; $this->conj2[3] = "were";
+ $this->conj1[4] = "I"; $this->conj2[4] = "you";
+ $this->conj1[5] = "me"; $this->conj2[5] = "you";
+ $this->conj1[6] = "you"; $this->conj2[6] = "me";
+ $this->conj1[7] = "my"; $this->conj2[7] = "your";
+ $this->conj1[8] = "your"; $this->conj2[8] = "my";
+ $this->conj1[9] = "mine"; $this->conj2[9] = "your's";
+ $this->conj1[10] = "your's"; $this->conj2[10] = "mine";
+ $this->conj1[11] = "I'm"; $this->conj2[11] = "you're";
+ $this->conj1[12] = "you're"; $this->conj2[12] = "I'm";
+ $this->conj1[13] = "I've"; $this->conj2[13] = "you've";
+ $this->conj1[14] = "you've"; $this->conj2[14] = "I've";
+ $this->conj1[15] = "I'll"; $this->conj2[15] = "you'll";
+ $this->conj1[16] = "you'll"; $this->conj2[16] = "I'll";
+ $this->conj1[17] = "myself"; $this->conj2[17] = "yourself";
+ $this->conj1[18] = "yourself"; $this->conj2[18] = "myself";
+
+ // array to post process correct our tenses of pronouns such as "I/me"
+
+ $this->conj3[0] = "me am"; $this->conj4[0] = "I am";
+ $this->conj3[1] = "am me"; $this->conj4[1] = "am I";
+ $this->conj3[2] = "me can"; $this->conj4[2] = "I can";
+ $this->conj3[3] = "can me"; $this->conj4[3] = "can I";
+ $this->conj3[4] = "me have"; $this->conj4[4] = "I have";
+ $this->conj3[5] = "me will"; $this->conj4[5] = "I will";
+ $this->conj3[6] = "will me"; $this->conj4[6] = "will I";
+
+
+ // Keywords
+
+ $this->keyword[ 0]=new Psychotherapist_Key( "CAN YOU", 1, 3);
+ $this->keyword[ 1]=new Psychotherapist_Key( "CAN I", 4, 5);
+ $this->keyword[ 2]=new Psychotherapist_Key( "YOU ARE", 6, 9);
+ $this->keyword[ 3]=new Psychotherapist_Key( "YOU'RE", 6, 9);
+ $this->keyword[ 4]=new Psychotherapist_Key( "I DON'T", 10, 13);
+ $this->keyword[ 5]=new Psychotherapist_Key( "I FEEL", 14, 16);
+ $this->keyword[ 6]=new Psychotherapist_Key( "WHY DON'T YOU", 17, 19);
+ $this->keyword[ 7]=new Psychotherapist_Key( "WHY CAN'T I", 20, 21);
+ $this->keyword[ 8]=new Psychotherapist_Key( "ARE YOU", 22, 24);
+ $this->keyword[ 9]=new Psychotherapist_Key( "I CAN'T", 25, 27);
+ $this->keyword[10]=new Psychotherapist_Key( "I AM", 28, 31);
+ $this->keyword[11]=new Psychotherapist_Key( "I'M", 28, 31);
+ $this->keyword[12]=new Psychotherapist_Key( "YOU", 32, 34);
+ $this->keyword[13]=new Psychotherapist_Key( "I WANT", 35, 39);
+ $this->keyword[14]=new Psychotherapist_Key( "WHAT", 40, 48);
+ $this->keyword[15]=new Psychotherapist_Key( "HOW", 40, 48);
+ $this->keyword[16]=new Psychotherapist_Key( "WHO", 40, 48);
+ $this->keyword[17]=new Psychotherapist_Key( "WHERE", 40, 48);
+ $this->keyword[18]=new Psychotherapist_Key( "WHEN", 40, 48);
+ $this->keyword[19]=new Psychotherapist_Key( "WHY", 40, 48);
+ $this->keyword[20]=new Psychotherapist_Key( "NAME", 49, 50);
+ $this->keyword[21]=new Psychotherapist_Key( "CAUSE", 51, 54);
+ $this->keyword[22]=new Psychotherapist_Key( "SORRY", 55, 58);
+ $this->keyword[23]=new Psychotherapist_Key( "DREAM", 59, 62);
+ $this->keyword[24]=new Psychotherapist_Key( "HELLO", 63, 63);
+ $this->keyword[25]=new Psychotherapist_Key( "HI", 63, 63);
+ $this->keyword[26]=new Psychotherapist_Key( "MAYBE", 64, 68);
+ $this->keyword[27]=new Psychotherapist_Key( "NO", 69, 73);
+ $this->keyword[28]=new Psychotherapist_Key( "YOUR", 74, 75);
+ $this->keyword[29]=new Psychotherapist_Key( "ALWAYS", 76, 79);
+ $this->keyword[30]=new Psychotherapist_Key( "THINK", 80, 82);
+ $this->keyword[31]=new Psychotherapist_Key( "ALIKE", 83, 89);
+ $this->keyword[32]=new Psychotherapist_Key( "YES", 90, 92);
+ $this->keyword[33]=new Psychotherapist_Key( "FRIEND", 93, 98);
+ $this->keyword[34]=new Psychotherapist_Key( "COMPUTER", 99, 105);
+ $this->keyword[35]=new Psychotherapist_Key( "NO KEY FOUND", 106, 112);
+ $this->keyword[36]=new Psychotherapist_Key( "REPEAT INPUT", 113, 116);
+
+
+ $this->response[ 0]="ELIZA - PHP version ported from Javascript (George Dunlop) code by Dan Fuhry";
+ $this->response[ 1]="Don't you believe that I can<*";
+ $this->response[ 2]="Perhaps you would like to be able to<*";
+ $this->response[ 3]="You want me to be able to<*";
+ $this->response[ 4]="Perhaps you don't want to<*";
+ $this->response[ 5]="Do you want to be able to<*";
+ $this->response[ 6]="What makes you think I am<*";
+ $this->response[ 7]="Does it please you to believe I am<*";
+ $this->response[ 8]="Perhaps you would like to be<*";
+ $this->response[ 9]="Do you sometimes wish you were<*";
+ $this->response[ 10]="Don't you really<*";
+ $this->response[ 11]="Why don't you<*";
+ $this->response[ 12]="Do you wish to be able to<*";
+ $this->response[ 13]="Does that trouble you?";
+ $this->response[ 14]="Tell me more about such feelings.";
+ $this->response[ 15]="Do you often feel<*";
+ $this->response[ 16]="Do you enjoy feeling<*";
+ $this->response[ 17]="Do you really believe I don't<*";
+ $this->response[ 18]="Perhaps in good time I will<@";
+ $this->response[ 19]="Do you want me to<*";
+ $this->response[ 20]="Do you think you should be able to<*";
+ $this->response[ 21]="Why can't you<*";
+ $this->response[ 22]="Why are you interested in whether or not I am<*";
+ $this->response[ 23]="Would you prefer if I were not<*";
+ $this->response[ 24]="Perhaps in your fantasies I am<*";
+ $this->response[ 25]="How do you know you can't<*";
+ $this->response[ 26]="Have you tried?";
+ $this->response[ 27]="Perhaps you can now<*";
+ $this->response[ 28]="Did you come to me because you are<*";
+ $this->response[ 29]="How long have you been<*";
+ $this->response[ 30]="Do you believe it is normal to be<*";
+ $this->response[ 31]="Do you enjoy being<*";
+ $this->response[ 32]="We were discussing you, not me.";
+ $this->response[ 33]="Oh... <*";
+ $this->response[ 34]="You're not really talking about me, are you?";
+ $this->response[ 35]="What would it mean to you if you got<*";
+ $this->response[ 36]="Why do you want<*";
+ $this->response[ 37]="Suppose you got<*";
+ $this->response[ 38]="What if you never got<*";
+ $this->response[ 39]="I sometimes also want<@";
+ $this->response[ 40]="Why do you ask?";
+ $this->response[ 41]="Does that question interest you?";
+ $this->response[ 42]="What answer would please you the most?";
+ $this->response[ 43]="What do you think?";
+ $this->response[ 44]="Are such questions on your mind often?";
+ $this->response[ 45]="What is it that you really want to know?";
+ $this->response[ 46]="Have you asked anyone else?";
+ $this->response[ 47]="Have you asked such questions before?";
+ $this->response[ 48]="What else comes to mind when you ask that?";
+ $this->response[ 49]="Names don't interest me.";
+ $this->response[ 50]="I don't care about names, please go on.";
+ $this->response[ 51]="Is that the real reason?";
+ $this->response[ 52]="Don't any other reasons come to mind?";
+ $this->response[ 53]="Does that reason explain anything else?";
+ $this->response[ 54]="What other reasons might there be?";
+ $this->response[ 55]="Please don't apologise!";
+ $this->response[ 56]="Apologies are not necessary.";
+ $this->response[ 57]="What feelings do you have when you apologise?";
+ $this->response[ 58]="Don't be so defensive!";
+ $this->response[ 59]="What does that dream suggest to you?";
+ $this->response[ 60]="Do you dream often?";
+ $this->response[ 61]="What persons appear in your dreams?";
+ $this->response[ 62]="Are you disturbed by your dreams?";
+ $this->response[ 63]="How are you today.. What would you like to discuss?";
+ $this->response[ 64]="You don't seem quite certain.";
+ $this->response[ 65]="Why the uncertain tone?";
+ $this->response[ 66]="Can't you be more positive?";
+ $this->response[ 67]="You aren't sure?";
+ $this->response[ 68]="Don't you know?";
+ $this->response[ 69]="Are you saying no just to be negative?";
+ $this->response[ 70]="You are being a bit negative.";
+ $this->response[ 71]="Why not?";
+ $this->response[ 72]="Are you sure?";
+ $this->response[ 73]="Why no?";
+ $this->response[ 74]="Why are you concerned about my<*";
+ $this->response[ 75]="What about your own<*";
+ $this->response[ 76]="Can you think of a specific example?";
+ $this->response[ 77]="When?";
+ $this->response[ 78]="What are you thinking of?";
+ $this->response[ 79]="Really, always?";
+ $this->response[ 80]="Do you really think so?";
+ $this->response[ 81]="But you are not sure you<*";
+ $this->response[ 82]="Do you doubt you<*";
+ $this->response[ 83]="In what way?";
+ $this->response[ 84]="What resemblence do you see?";
+ $this->response[ 85]="What does the similarity suggest to you?";
+ $this->response[ 86]="What other connections do you see?";
+ $this->response[ 87]="Could there really be some connection?";
+ $this->response[ 88]="How?";
+ $this->response[ 89]="You seem quite positive.";
+ $this->response[ 90]="Are you Sure?";
+ $this->response[ 91]="I see.";
+ $this->response[ 92]="I understand.";
+ $this->response[ 93]="Why do you bring up the topic of friends?";
+ $this->response[ 94]="Do your friends worry you?";
+ $this->response[ 95]="Do your friends pick on you?";
+ $this->response[ 96]="Are you sure you have any friends?";
+ $this->response[ 97]="Do you impose on your friends?";
+ $this->response[ 98]="Perhaps your love for friends worries you.";
+ $this->response[ 99]="Do computers worry you?";
+ $this->response[100]="Are you talking about me in particular?";
+ $this->response[101]="Are you frightened by machines?";
+ $this->response[102]="Why do you mention computers?";
+ $this->response[103]="What do you think machines have to do with your problems?";
+ $this->response[104]="Don't you think computers can help people?";
+ $this->response[105]="What is it about machines that worries you?";
+ $this->response[106]="Say, do you have any psychological problems?";
+ $this->response[107]="What does that suggest to you?";
+ $this->response[108]="I see.";
+ $this->response[109]="I'm not sure I understand you fully.";
+ $this->response[110]="Come, come, elucidate your thoughts.";
+ $this->response[111]="Can you elaborate on that?";
+ $this->response[112]="That is quite interesting.";
+ $this->response[113]="Why did you repeat yourself?";
+ $this->response[114]="Do you expect a different answer by repeating yourself?";
+ $this->response[115]="Come, come, elucidate your thoughts.";
+ $this->response[116]="Please don't repeat yourself!";
+ }
+
+}
+
+/**
+ * Keyword class
+ */
+
+class Psychotherapist_Key
+{
+ /**
+ * Phrase to match
+ * @var string
+ */
+
+ public $key = '';
+
+ /**
+ * First response to use
+ * @var int
+ */
+
+ public $idx = 0;
+
+ /**
+ * Last response to use
+ * @var int
+ */
+
+ public $end = 0;
+
+ /**
+ * Response last used time
+ * @var int
+ */
+
+ public $last = 0;
+
+ /**
+ * Constructor.
+ * @param string Key
+ * @param int Index
+ * @param int End
+ */
+
+ public function __construct($key, $idx, $end)
+ {
+ $this->key = $key;
+ $this->idx = $idx;
+ $this->end = $end;
+ }
+}
+
+