/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name:ELIZA.CPP
*
*	Purpose: Phony psychiatrist program found on the Web and translated from PASCAL
*
*********************************************************************
*/

#include "stdafx.h"

#ifdef UNICODE
#define strstr wcsstr
#define strchr wcschr
#define strtok wcstok
#define _stricmp _wcsicmp
#define _strupr _wcsupr
#endif

LPTSTR pResps [] = {
//"One-based adjustment",
_T("Don't you believe that I can*"),
_T("Perhaps you would like to be able to*"),
_T("You want me to be able to*"),
_T("Perhaps you don't want to*"),
_T("Do you want to be able to*"),
_T("What makes you think I am*"),
_T("Does it please you to believe I am*"),
_T("Perhaps you would like to be*"),
_T("Do you sometimes wish you were*"),
_T("Don't you really*"),
_T("Why don't you*"),
_T("Do you wish to be able to*"),
_T("Does that trouble you?"),
_T("Tell me more about such feelings."),
_T("Do you often feel*"),
_T("Do you enjoy feeling*"),
_T("Do you really believe I don't*"),
_T("Perhaps in good time I will@"),
_T("Do you want me to*"),
_T("Do you think you should be able to*"),
_T("Why can't you*"),
_T("Why are you interested in whether or not I am*"),
_T("Would you prefer if I were not*"),
_T("Perhaps in your fantasies I am*"),
_T("How do you know you can't*"),
_T("Have you tried?"),
_T("Perhaps you can now*"),
_T("Did you come to me because you are*"),
_T("How long have you been*"),
_T("Do you believe it is normal to be*"),
_T("Do you enjoy being*"),
_T("We were discussing you --not me."),
_T("Oh,*"),
_T("You're not really talking about me, are you?"),
_T("What would it mean to you if you got*"),
_T("Why do you want*"),
_T("Suppose you got*"),
_T("What if you never got*"),
_T("I sometimes also want@"),
_T("Why do you ask?"),
_T("Does that question interest you?"),
_T("What answer would please you the most?"),
_T("What do you think?"),
_T("Are such questions on your mind often?"),
_T("What is it that you really want to know?"),
_T("Have you asked anyone else?"),
_T("Have you asked such questions before?"),
_T("What else comes to mind when you ask that?"),
_T("Names don't interest me."),
_T("I don't care about names --please go on."),
_T("Is that the real reason?"),
_T("Don't any other reasons come to mind?"),
_T("Does that reason explain anything else?"),
_T("What other reasons might there be?"),
_T("Please don't apologise!"),
_T("Apologies are not necessary."),
_T("What feelings do you have when you apologise?"),
_T("Don't be so defensive!"),
_T("What does that dream suggest to you?"),
_T("Do you dream often?"),
_T("What persons appear in your dreams?"),
_T("Are you disturbed by your dreams?"),
_T("How do you...please state your problem."),
_T("You don't seem quite certain."),
_T("Why the uncertain tone?"),
_T("Can't you be more positive?"),
_T("You aren't sure?"),
_T("Don't you know?"),
_T("Are you saying no just to be negative?"),
_T("You are being a bit negative."),
_T("Why not?"),
_T("Are you sure?"),
_T("Why no?"),
_T("Why are you concerned about my*"),
_T("What about your own*"),
_T("Can you think of a specific example?"),
_T("When?"),
_T("What are you thinking of?"),
_T("Really, always?"),
_T("Do you really think so?"),
_T("But you are not sure you*"),
_T("Do you doubt you*"),
_T("In what way?"),
_T("What resemblence do you see?"),
_T("What does the similarity suggest to you?"),
_T("What other connections do you see?"),
_T("Cound there really be some connection?"),
_T("How?"),
_T("You seem quite positive."),
_T("Are you Sure?"),
_T("I see."),
_T("I understand."),
_T("Why do you bring up the topic of friends?"),
_T("Do your friends worry you?"),
_T("Do your friends pick on you?"),
_T("Are you sure you have any friends?"),
_T("Do you impose on your friends?"),
_T("Perhaps your love for friends worries you."),
_T("Do computers worry you?"),
_T("Are you talking about me in particular?"),
_T("Are you frightened by machines?"),
_T("Why do you mention computers?"),
_T("What do you think machines have to do with your problems?"),
_T("Don't you think computers can help people?"),
_T("What is it about machines that worries you?"),
_T("Say, do you have any psychological problems?"),
_T("What does that suggest to you?"),
_T("I see."),
_T("I'm not sure I understand you fully."),
_T("Come, come, elucidate your thoughts."),
_T("Can you elaborate on that?"),
_T("That is quite interesting."),
_T("Why did you repeat yourself?"),
_T("Do you expect a different answer by repeating yourself?"),
_T("Come, come, elucidate your thoughts."),
_T("Please don't repeat yourself!"),
_T("This session is costing $150 an hour. Repeat yourself all you want.")  } ;




/*
{=========================================================}
{      Keywords                                           }
{=========================================================}
*/

#define MAXKEY	37 

TCHAR PrevStr [1024] ;

const TCHAR *KeyWords [] = {
               _T("CAN YOU"),
			   _T("CAN I"),
			   _T("YOU ARE"),
			   _T("YOU'RE"),
			   _T("I DON'T"),
               _T("I FEEL"),
			   _T("WHY DON'T YOU"),
			   _T("WHY CAN'T I"),
			   _T("ARE YOU"),
               _T("I CAN'T"),
			   _T("I AM"),
			   _T("I'M"),
			   _T("YOU"),
			   _T("I WANT"),
			   _T("WHAT"),
               _T("HOW"),
			   _T("WHO"),
			   _T("WHERE"),
			   _T("WHEN"),
			   _T("WHY"),
			   _T("NAME"),
			   _T("CAUSE"),
               _T("SORRY"),
			   _T("DREAM"),
			   _T("HELLO"),
			   _T("HI"),
			   _T("MAYBE"),
			   _T("NO"),
               _T("YOUR")
			   ,_T("ALWAYS"),
			   _T("THINK"),
			   _T("ALIKE"),
			   _T("YES"),
			   _T("FRIEND"),
               _T("COMPUTER"),
			   _T("NO KEY FOUND"),
			   _T("REPEAT INPUT")};

/*
{=========================================================}
{     Data for finding the right responses                }
{=========================================================}
*/

const TCHAR *RespFile = _T("RESPONSE.DAT");  // {response data file}
int MaxRespNum = 116;


int RspIndex [] = 
		{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,113};  //  {- working response pointer array -}

/*
{- this array contains the start index to the response strings -}
*/

const int KeyIndex [] =
        {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,113};

/*
{- this array contains the end index to the response strings -}
*/
const int KeyEnd [] =
        {3, 5, 9, 9,13,16,19,21,24,27,
        32,32,34,39,48,48,48,48,48,48,
        50,54,58,62,68,63,68,73,75,79,
        82,89,92,98,105,112,117};



/*
{=========================================================}
{     Other misc information needed by the program        }
{=========================================================}

{- possible punctuation -}
*/

const TCHAR *PuncSet = _T(" .!?,");
/*
{- misc error messages -}
*/

const TCHAR *NoFileMsg = _T("Sorry, I seem to have mis-placed the response files.");
const TCHAR *LogicErrMsg = _T("Hmmm, I seem to be having problems myself.");

void ReadResp(TCHAR *Rstr, int RespNum)
{
	
/*
invalid response number given
*/
	if (RespNum > MaxRespNum)
	{
		lstrcpy (Rstr, LogicErrMsg) ;
		return ;
	}

/*
find the desired response in the response file
*/
  	lstrcpy (Rstr, pResps[RespNum]) ;

}


/*
{=========================================================}
{        Find keyword in Wstr                             }
{=========================================================}
{- a keyword is a relational word that we can respond to }
{- see the keyword table to see the types of relational words}
{- that are used. Returns "Key" pointing to keyword in table,}
{- returns "Kpos" pointing to first char after keyword in Wstr}
{- Returns function true if keyword found, or false if not}
{- if no keyword found Key = pred(MaxKey), repeated string = MaxKey}
*/

BOOL FindKey(TCHAR *Wstr, int *Kpos, int *Key)
{
	int i ;
	TCHAR *pKey ;
	
	for (i = 0 ; i < MAXKEY ; i ++)
	{
		if ((pKey = strstr (Wstr, KeyWords [i])) != NULL)
		{
			*Kpos = (pKey - Wstr) + lstrlen (KeyWords [i]) ;
			*Key = i ;
			return TRUE ;	
		}
	}  
 
  	return FALSE ;
}



/*
{=========================================================}
{   Take the right part of the string and conjugate it    }
{   using the list of strings to be swapped               }
{=========================================================}
*/

void Ctrim(TCHAR *Xstr)
{
	TCHAR *cp ;

/*
remove spaces and punctuation from the head of the string
*/
    while (strchr (PuncSet, *Xstr))
    {
    	memmove (Xstr, Xstr + 1, lstrlen (Xstr)) ;
	}

/*
remove spaces and puncuation from end of string
*/
	cp = Xstr + lstrlen (Xstr) - 1 ;

    while (strchr (PuncSet, *cp)) 
	{
      	*cp = 0x00 ;
      	cp -- ;
	}
}

/*
{=========================================================}
{      String data for conjugations                       }
{=========================================================}
*/

const MaxCon = 7;
const TCHAR *Con1 []  =
    {_T("are"),_T("we're"),_T("you"),_T("your"),_T("I've"),_T("I'm"),_T("me")};
const TCHAR *Con2 []  =
    {_T("am"),_T("was"),_T("I"),_T("my"),_T("you've"),_T("you're"),_T("you")};

void Conjugate (TCHAR *Wstr, TCHAR *Cstr, int Kpos)
{
	int i;
	TCHAR TempStart [256], TempFinal [256], *cp ;

    lstrcpy(TempStart, Wstr+Kpos);    //{pull out the right part}
	TempFinal [0] = 0x00 ;

	cp = strtok	(TempStart, PuncSet) ;

	while (cp != NULL)
	{
/*
for each word, check for conjugation changes. 
*/
    	for (i = 0 ; i < MaxCon ; i ++)
    	{
			if (_stricmp (cp, Con1 [i]) == 0)
			{
				lstrcat (TempFinal, _T(" ")) ;
				lstrcat (TempFinal, Con2 [i]) ;
				break ;
			}
			else if	(_stricmp (cp, Con2 [i]) == 0)
			{
				lstrcat (TempFinal, _T(" ")) ;
				lstrcat (TempFinal, Con1 [i]) ;
				break ;
			}
    	}

/*
no conjugation change, copy original word into dest string
*/
		if (i == MaxCon)
		{
			lstrcat (TempFinal, _T(" ")) ;
			lstrcat (TempFinal, cp) ;
		}

		cp = strtok (NULL, PuncSet) ;
	}


/*
special case fixup for trailing 'I's 
*/
    /*if Cstr[length(Cstr)] = 'I' then
    {
      //dec(Cstr[0]);
      strcat (Cstr, "me";
    }
*/

	lstrcpy (Wstr, TempFinal) ;
}


/*
{============================================================}
{ Get a response based on the keyword number in variable Key }
{============================================================}
*/

void GetResponse(TCHAR *Rstr, int Key)
{
	TCHAR Fstr [120] ;
	TCHAR temp [256] ;
	
/*
{get the desired response from data file}
subtract 1 to correct for difference between 0-based arrays in C and 1-based
arrays in Pascal
*/

  	ReadResp(Fstr, RspIndex[Key] - 1); 

/*
  {-Point to the next response so that no two are the same}
*/
  
  	RspIndex[Key] ++ ;

  	if (RspIndex[Key] == KeyEnd[Key])
  	{
  		RspIndex[Key] = KeyIndex[Key] ;
	}

/*
  {-if no "*" or "@" at the end of the response, then just return the response}
  {-if there was an "*" at the end of the response string, then return}
  {-the response plus the conjugation word/phrase in Rstr plus a "?"}
  {-if "@" then add a period instead}
*/

  	if (*(Fstr + lstrlen (Fstr) - 1) == '*')
  	{
//{- replace the '*' with a space, append the conjugated string and add "?" -}
		*(Fstr + lstrlen (Fstr)- 1) = ' ';
		lstrcpy (temp, Fstr) ;
		lstrcat (temp, Rstr) ;
		lstrcat (temp, _T("?")) ;
		lstrcpy (Rstr, temp) ;
	  	return ;  
  	}
  	else if (*(Fstr + lstrlen (Fstr) - 1) == '@')
  	{

//{- replace the '@' with a space, append the conjugated string and add "." -}

	  	*(Fstr + lstrlen(Fstr) - 1) = ' ';
		lstrcpy (temp, Fstr) ;
		lstrcat (temp, Rstr) ;
		lstrcat (temp, _T("."))  ;
		lstrcpy (Rstr, temp) ;
  		return ;  
  	}
  	else
  	{
  		lstrcpy (Rstr,Fstr) ;
		return ;
	}
}


/*
{============================================================}
{- program Eliza -}
*/




/*
{============================================================}
{        Reads a response from the response file             }
{============================================================}
*/


void Eliza (TCHAR *InStr, TCHAR *OutStr)
{

	TCHAR CapStr [1024] ;
	int Kpos, Key ;

/*
Check first character for NULL.  If found, simply return
"Time Test Output" as the string.
*/

	if (*InStr == 0x0000)
	{
		lstrcpy (OutStr, TEXT("Time Test Output")) ;
		return ;
	}

  	Key = MAXKEY-1;                   // {- set max for repeat input -}
    
	lstrcpy (CapStr, InStr) ;
	_strupr (CapStr) ;
   	
   	if (_stricmp (InStr,PrevStr)	!= 0)
    {       	           //{- get new key if not repeat -}
    	lstrcpy (PrevStr, InStr) ;	// {- save original input string -}
    	if (FindKey(CapStr, &Kpos, &Key))
      	{
			 //{- If keyword found in Istr -}
        	Conjugate(InStr, CapStr, Kpos);  //{- then conjugate the string -}
		}
		else
		{
			Key = MAXKEY - 2 ;
		}
	}

    GetResponse(InStr, Key); 				//{- Get response based on Keyword found -}
	wsprintf (OutStr, _T("Eliza: %s%c%c"),InStr,0x0D,0x0A) ;
}

