DOCTORP.C

/**************************************************************************** 
Microsoft RPC Version 2.0
Copyright Microsoft Corp. 1992, 1993, 1994- 1996
Doctor Example

FILE: Doctorp.c

PURPOSE: Procedures that can be linked with the client side
to form a standalone application, or linked with
the server side to form a distributed RPC application

DATA: Pattern - array of strings; input patterns and responses
Substring - substrings within user input

FUNCTIONS: Analyze(*pszInOut) - top level function
Match(*string, *pattern) - compare input to patterns
Respond(*string, *response) - replace substrings in response
Synonyms(*ps1, *ps2) - replace synonyms in user input

****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "doctor.h" // header file generated by MIDL compiler

#define TRUE 1
#define FALSE 0


char *Pattern[] =
{
"0COMPUTER 1",
"0COMPUTERS 1",
"=DO 11S WORRY YOU?", // string 11 = "computer" or "machine"
"=WHY DO YOU MENTION 11S?",
"=WHAT DO YOU THINK 11S HAVE TO DO WITH YOUR PROBLEM?",
"=WHAT DO YOU THINK ABOUT 11S?",

"0RPC0",
"=WHY DO YOU MENTION RPC?",
"=DO YOU MENTION RPC BECAUSE YOU ARE FEELING REMOTE RIGHT NOW?",
"=WHAT FEELINGS DO YOU HAVE ABOUT RPC?",

"0SORRY0",
"=PLEASE DON'T APOLOGIZE.",
"=APOLOGIES ARE NOT NECESSARY.",
"=WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
"=I'VE TOLD YOU THAT APOLOGIES ARE NOT REQUIRED.",
"=APOLOGIES ARE NOT NECESSARY, PLEASE GO ON",

"0I AM SAD1",
"=I AM SORRY TO HEAR YOU ARE 14.", // string 14 = "sad", "sick", etc.
"=DO YOU THINK COMING HERE WILL HELP YOU NOT TO BE 14?",
"=I'M SURE IT'S NOT PLEASANT TO BE 14.",
"=CAN YOU EXPLAIN WHAT MADE YOU 14?",

"0I AM HAPPY1",
"=HOW HAVE I HELPED YOU TO BE 15?", // string 15 = "happy", etc.
"=HAS YOUR TREATMENT MADE YOU 15?",
"=WHAT MAKES YOU 15 JUST NOW?",
"=CAN YOU EXPLAIN WHY YOU ARE SUDDENLY 15?",

"0NAME0",
"=I AM NOT INTERESTED IN NAMES.",
"=I'VE TOLD YOU BEFORE I DON'T CARE ABOUT NAMES. PLEASE CONTINUE.",

"0 FAMILY1",
"=TELL ME MORE ABOUT YOUR 12.", // string 12 = "mother", "brother", etc.
"=WHO ELSE IN YOUR FAMILY?",
"=YOUR 12?",
"=WHAT ELSE COMES TO MIND WHEN YOU THINK OF YOUR 12?",

"0I REMEMBER 1",
"=DO YOU OFTEN THINK OF 1?",
"=WHAT IN THE PRESENT SITUATION REMINDS YOU OF 1?",

"0SAME0",
"0ALIKE0",
"0IS 0LIKE0",
"=IN WHAT WAY?",
"=WHAT RESEMBLANCE DO YOU SEE?",
"=WHAT DOES THAT SIMILARITY SUGGEST TO YOU?",
"=WHAT OTHER CONNECTIONS DO YOU SEE?",
"=WHAT DO YOU SUPPOSE THAT RESEMBLANCE MEANS?",
"=WHAT IS THE CONNECTION, DO YOU SUPPOSE?",
"=COULD THERE REALLY BE SOME CONNECTION?",
"=HOW?",

"0I REMEMBER 1",
"=DO YOU OFTEN THINK OF 1?",
"=DOES THINKING OF 1 BRING ANYTHING ELSE TO MIND?",
"=WHAT ELSE DO YOU REMEMBER?",
"=WHY DO YOU REMEMBER 1 JUST NOW?",
"=WHAT IN THE PRESENT SITUATION REMINDS YOU OF 1?",
"=WHAT IS THE CONNECTION BETWEEN ME AND 1?",

"0DO YOU REMEMBER 1",
"=DID YOU THINK I WOULD FORGET 1?",
"=WHY DO YOU THINK I SHOULD RECALL 1 NOW?",
"=WHAT ABOUT 1?",
"=YOU MENTIONED 1?",

"1 IS MY PROBLEM0",
"=1 13 YOUR PROBLEM?", // string 13 = "is" or "are"
"=ARE YOU SURE 13 1 YOUR PROBLEM?",
"=PERHAPS 13 1 NOT YOUR REAL PROBLEM.",
"=YOU THINK YOU HAVE PROBLEMS?",
"=DO YOU OFTEN THINK ABOUT 1?",

"0PROBLEM0",
"=PLEASE CONTINUE, THIS MAY BE INTERESTING.",
"=HAVE YOU ANY OTHER PROBLEMS YOU WISH TO DISCUSS?",
"=PERHAPS YOU'D RATHER CHANGE THE SUBJECT.",
"=YOU SEEM A BIT UNEASY.",

"0I DREAMT 1",
"0I DREAMED 1",
"=REALLY 1?",
"=HAVE YOU EVER FANTASIZED 1 WHILE YOU WERE AWAKE?",
"=HAVE YOU DREAMT 1 BEFORE?",
"=WHAT DOES THAT DREAM SUGGEST TO YOU?",
"=DO YOU DREAM OFTEN?",
"=WHAT PERSONS APPEAR IN YOUR DREAMS?",
"=DON'T YOU BELIEVE THAT DREAM HAS SOMETHING TO DO WITH YOUR PROBLEM?",
"=DO YOU EVER WISH YOU COULD FLEE FROM REALITY?",

"0DREAM0",
"=WHAT DOES THAT DREAM SUGGEST TO YOU?",
"=DO YOU DREAM OFTEN?",
"=WHAT PERSONS APPEAR IN YOUR DREAMS?",
"=DON'T YOU BELIEVE THAT DREAM HAS SOMETHING TO DO WITH YOUR PROBLEM?",
"=DO YOU EVER WISH YOU COULD FLEE FROM REALITY?",

"0IF 1 HAD 2",
"=DO YOU THINK IT'S LIKELY THAT 1 MIGHT HAVE 2?",
"=DO YOU WISH THAT 1 HAD 2?",
"=REALLY, IF 1 HAD 2?",

"0IF 1",
"=DO YOU THINK IT'S LIKELY THAT 1?",
"=DO YOU WISH THAT 1?",
"=WHAT DO YOU THINK ABOUT 1?",
"=REALLY, IF 1?",

"WAS I 1",
"=WHAT IF YOU WERE 1?",
"=DO YOU THINK YOU WERE 1?",
"=WERE YOU 1?",
"=WHAT WOULD IT MEAN IF YOU WERE 1?",
"=WHAT DOES \"1\" SUGGEST TO YOU?",
"=WHY DO YOU ASK?",
"=DOES THAT QUESTION INTERST 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?",

"0I WAS 1",
"=WERE YOU REALLY?",
"=WHY DO YOU TELL ME YOU WERE 1 NOW?",
"=PERHAPS I ALREADY KNEW YOU WERE 1.",

"WERE YOU 1",
"=WOULD YOU LIKE TO BELIEVE THAT I WAS 1?",
"=WHAT SUGGESTS THAT I WAS 1?",
"=WHAT DO YOU THINK?",
"=PERHAPS I WAS 1.",
"=WHAT IF I HAD BEEN 1.",

"0 MY 1",
"MY 1",
"=YOUR 1?",
"=WHY DO YOU SAY YOUR 1?",
"=DOES THAT SUGGEST ANYTHING ELSE WHICH BELONGS TO YOU?",
"=IS IT IMPORTANT TO YOU THAT 1?",

"0EVERYONE0",
"0EVERYBODY0",
"=REALLY, EVERYONE?",
"=SURELY NOT EVERYONE.",
"=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 PARTICULAR PERSON IN MIND, DON'T YOU?",
"=WHO DO YOU THINK YOU'RE TALKING ABOUT?",
"=I SUSPECT YOU'RE EXAGGERATING A LITTLE.",

"NO ONE0",
"0 NO ONE0",
"0NOBODY0",
"=REALLY, NO ONE?",
"=SURELY SOMEONE.",
"=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 PARTICULAR PERSON IN MIND, DON'T YOU?",
"=WHO DO YOU THINK YOU'RE TALKING ABOUT?",
"=I SUSPECT YOU'RE EXAGGERATING A LITTLE.",

"0ALWAYS0",
"=CAN YOU THINK OF A SPECIFIC EXAMPLE?",
"=WHEN?",
"=WHAT INCIDENT ARE YOU THINKING OF?",
"=REALLY, ALWAYS?",
"=WHAT IF THIS NEVER HAPPENED?",

"0HOW 0",
"0WHERE 0",
"=WHY DO YOU ASK?",
"=DOES THAT QUESTION INTERST YOU?",
"=WHAT IS IT YOU REALLY WANT TO KNOW?",
"=ARE SUCH QUESTIONS MUCH ON YOUR MIND?",
"=WHAT ANWSER 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?",

/* "there is no" strings must precede "there is" strings */
"0THERE IS NO 1",
"0THERE IS NOT 1",
"=WHAT IF THERE WERE 1",
"=DID YOU THINK THERE MIGHT BE 1",
"=HOW 13 1 RELATED TO YOU?",
/* these must follow "there is no" strings */
"0THERE IS 1",
"=13 THERE REALLY 1?",
"=HOW 13 1 RELATED TO YOU?",

"0SEX 1",
"=DO YOU REALLY WANT TO DISCUSS SEX?",
"=DO YOU EVER DREAM ABOUT SEX?",
"=WHY DO YOU MENTION SEX?",
"=COULD SEX BE PART OF YOUR PROBLEM?",

"0HECK1", // checks for strong language
"0DARN1",
"=ARE SUCH OBSCENITIES FREQUENTLY ON YOUR MIND?",
"=YOU ARE BEING A BIT CHILDISH.",
"=REALLY NOW",
"=DEAR ME",
"=I REALLY SHOULDN'T TOLERATE SUCH LANGUAGE.",

"0MY FRIEND 1",
"=WHAT ELSE CAN YOU TELL ME ABOUT YOUR FRIEND?",
"=WHAT MIGHT YOUR FRIEND HAVE TO DO WITH THE PROBLEM?",

"0", // last resort: match anything
"=PLEASE GO ON.",
"=I AM NOT SURE I UNDERSTAND YOU FULLY.",
"=WHAT DOES THAT SUGGEST TO YOU?",
"=DO YOU FEEL STRONGLY ABOUT DISCUSSING SUCH THINGS?",
NULL // special end of list character
};


int iLastIndex = 0; // don't send same response twice in a row
// note: this requires 2 responses for each pattern

char Substring[20][STRSIZE] = {
"", "", "", "", "", "", "", "", "", "",
"REMEMBER", /* 10 */
"COMPUTER", /* 11 */
"FAMILY", /* 12 */
"IS", /* 13 */
"", "", "", "", "", "" };


/* Compare user input to patterns */

int Match (char *str, char *pat)
{
char * pStr; // backup ptr to the user input string
char * pPat; // backup ptr to the pattern
char *pSubstr = NULL; // possible substrings within pattern
int index = 0; // index to substring

while (TRUE) { // exit routine from within this loop

if (isdigit(*pat)) { // replaceable pattern number
index = atoi(pat); // extract pattern number
while (isdigit(*pat)) // skip number in pattern
pat++;

pSubstr = Substring[index]; // pointer to current substring

if (*pat == '\0') { // if end of pattern, everything will match
strcpy(pSubstr, str); // copy rest of input into substring
return(TRUE);
}

else
while (*pat != *str) { // match all to specific char in pattern
*pSubstr++ = *str++; // fill substring
if (*str == '\0') // stuff left to match, but no input
return(FALSE);
*pSubstr = '\0'; // can overwrite if there's more...
}

pStr = str; // keep track; it may still be *
pPat = pat; // keep track; it may still be *
}

if (*str == *pat) { // matches the specific pattern
str++; // skip to next character of input string
pat++; // skip to next character of pattern
if ((*str == '\0') && (*pat == '\0')) // both at end?
return(TRUE);
}

else if (pSubstr != NULL) { // didn't match specific, so still * substring
pat = pPat; // restore ptr to input pattern
while (pStr < str) // catch up to current input character
*pSubstr++ = *pStr++;
while (*pat != *str) { // match to next possible match in pattern
*pSubstr++ = *str++; // fill substring with more characters
if (*str == '\0') // stuff left to match, but no input
return(FALSE);
}
*pSubstr = '\0'; // can overwrite if there's more...
pStr = str; // keep track; it may still be *
pPat = pat; // keep track; it may still be *
}

else
return(FALSE); // no match

} // end while (TRUE) loop

} // end function Match


/* Add possible substrings to the response string */

void Respond(char *str, char *finalstr)
{
char copy[STRSIZE]; // copy of the substring to process token at a time
char *token;
char *word;
int index; // index to substring (string converted to number)
int len = 0; // index to output string for sprintf

while (*str) {

if (! isdigit(*str))
len += sprintf(finalstr + len, "%c", *str++);

else { // check for pattern number

index = atoi(str); // extract pattern number
while (isdigit(*str)) // skip number in pattern
str++;

strcpy(copy, Substring[index]); // process substring
token = strtok(copy, " "); // skip blanks

while (token) {
word = token;

if (! strcmp(token,"I") || ! strcmp(token,"ME"))
word = "YOU";
else if (! strcmp(token,"YOU"))
word = "I";
else if (! strcmp(token,"MY"))
word = "YOUR";
else if (! strcmp(token,"YOUR"))
word = "MY";
else if (! strcmp(token,"MINE"))
word = "YOURS";
else if (! strcmp(token,"YOURS"))
word = "MINE";
else if (! strcmp(token,"MYSELF"))
word = "YOURSELF";
else if (! strcmp(token,"YOURSELF"))
word = "MYSELF";
else if (! strcmp(token,"I'M"))
word = "YOU'RE";
else if (! strcmp(token,"YOU'RE"))
word = "I'M";
else if (! strcmp(token,"AM"))
word = "ARE";
else if (! strcmp(token,"WAS"))
word = "WERE";

len += sprintf(finalstr + len, "%s", word);

// get next token from Substring
if ((token = strtok(NULL, " ")) != NULL)
len += sprintf(finalstr + len, " ");

} // end while token

} // end else (if isdigit)

} // end while str

len += sprintf(finalstr + len, "\n");

} // end function Respond


/* Replace synonyms in user input */

void Synonyms(char *input, char *output)
{
char *ps1 = input;
char *ps2 = output;
char *token;
char *word;

static char *synonym10[] = {"RECALL", "RECOLLECT", ""};
static char *synonym11[] = {"MACHINE", ""};
static char *synonym12[] = {"MOTHER", "MOMMY", "FATHER", "DADDY",
"SISTER", "BROTHER", "AUNT", "UNCLE", ""};
static char *synonym13[] = {"ARE", "AM", ""};
static char *synonym14[] = {"SAD", "UNHAPPY", "DEPRESSED", "SICK", ""};
static char *synonym15[] = {"HAPPY", "ELATED", "GLAD", "BETTER", ""};

short StrMember();

// preprocessing...convert to uppercase and check for special chars

while (*ps1) {
*ps1 = toupper(*ps1);
if (*ps1 == '.' || *ps1 == ',' || *ps1 == '!' ||
*ps1 == '?' || *ps1 == ';' || *ps1 == ':' ||
! isprint(*ps1)) {
*ps1 = '\0';
break;
}
ps1++;
}

// ok, it's preprocessed now...let's check for pattern matches

ps1 = input; // back to the beginning...
strcpy(ps2, "");
token = strtok(ps1, " "); // search for tokens deliminated by space

while (token) {

word = token;

if (StrMember(token, synonym10)) {
word = "REMEMBER"; // use this synonym for pattern-matching
}
else if (StrMember(token, synonym11)) {
strcpy(Substring[11], token); // 11 is hardcoded into response
word = "COMPUTER";
}
else if (StrMember(token, synonym12)) {
strcpy(Substring[12], token); // 12
word = "FAMILY";
}
else if (StrMember(token, synonym13)) {
strcpy(Substring[13], token); // 13
word = "IS";
}
else if (StrMember(token, synonym14)) {
strcpy(Substring[14], token); // 14
word = "SAD";
}
else if (StrMember(token, synonym15)) {
strcpy(Substring[15], token); // 15
word = "HAPPY";
}

strcat(ps2, word); // append the token to the output string
strcat(ps2, " "); // restore space
token = strtok(NULL, " "); // search for the next token

} // end while token

} // end function Synonyms


short StrMember(char *str, char **list)
{
while (strcmp(*list, "")) { // not end of the list
if (!strcmp(str, *list))
return 1;
else
list++;
}

return 0;
}


/* Top-level routine */

void Analyze(unsigned char *str)
{
int i = 0; // index to entry within Pattern
int j; // index to first possible response string
int index; // index of the actual response string used
int count = 0; // count of all possible response strings (must be > 2)
char *response;
char synstr[STRSIZE];

Synonyms(str, synstr);

while (Pattern[i] != NULL) { // check against all patterns

if (Pattern[i][0] != '=') { // if a patient pattern

if (Match(synstr, Pattern[i]) == TRUE) {

// skip past patient input to doctor responses
while (Pattern[i] && Pattern[i][0] != '=')
i++;

// count the number of possible responses, and
// point index to beginning of doctor responses
if (Pattern[i] && Pattern[i][0] == '=') {
count = 1;
j = i++;
}

// count all possible doctor responses
while (Pattern[i] && Pattern[i][0] == '=') {
count++;
i++;
}

// pick a different doctor response from last time
do {
index = j + (rand() % count);
} while (index == iLastIndex);

// process the doctor respose, and
// keep track of the response used last
response = &Pattern[index][1];
iLastIndex = index;
Respond(response, str);
return;

} // end if match

} // end if patient pattern

i++; // next pattern

} // end while pattern

} // end function Analyze


/* Shutdown the server by calling RPC API functions */

void Shutdown(void)
{
RPC_STATUS status;

printf("Calling RpcMgmtStopServerListening\n");
status = RpcMgmtStopServerListening(NULL);
printf("RpcMgmtStopServerListening returned: 0x%x\n", status);
if (status) {
exit(status);
}

printf("Calling RpcServerUnregisterIf\n");
status = RpcServerUnregisterIf(NULL, NULL, FALSE);
printf("RpcServerUnregisterIf returned 0x%x\n", status);
if (status) {
exit(status);
}
}

/* end file doctorp.c */