|
|
1.1 root 1: /****************************************************************************
2: Microsoft RPC Version 1.0
3: Copyright Microsoft Corp. 1992
4: Doctor Example
5:
6: FILE: Doctorp.c
7:
8: PURPOSE: Procedures that can be linked with the client side
9: to form a standalone application, or linked with
10: the server side to form a distributed RPC application
11:
12: DATA: Pattern - array of strings; input patterns and responses
13: Substring - substrings within user input
14:
15: FUNCTIONS: Analyze(*pszInOut); top level function
16: Match(*string, *pattern); compare input to patterns
17: Respond(*string, *response); replace substrings in response
18: Synonyms(*ps1, *ps2); replace synonyms in user input
19:
20: HISTORY: Based on an example program provided with:
21: Microsoft LISP Artificial Intelligence Programming
22: Environment for the MS-DOS Operating System
23: Portions Copyright (C) Microsoft Corporation 1986
24: Copyright (C) Soft Warehouse, Inc.1979,1980,1982,1983,1985,1986
25: Converted from LISP to C by David Bullock
26: Copyright (C) Microsoft Corporation 1992
27: ****************************************************************************/
28:
29: #include <stdlib.h>
30: #include <stdio.h>
31: #include <string.h>
32: #include <ctype.h>
33:
34: #include <rpc.h>
35: #include "doctor.h"
36:
37: #define TRUE 1
38: #define FALSE 0
39:
40: #define STRSIZE 500
41:
42: char *Pattern[] =
43: {
44: "0COMPUTER 1",
45: "0COMPUTERS 1",
46: "=DO 11S WORRY YOU?", /* string 11 = "computer" or "machine" */
47: "=WHY DO YOU MENTION 11S?",
48: "=WHAT DO YOU THINK 11S HAVE TO DO WITH YOUR PROBLEM?",
49: "=WHAT DO YOU THINK ABOUT 11S?",
50:
51: "0RPC0",
52: "=WHY DO YOU MENTION RPC?",
53: "=DO YOU MENTION RPC BECAUSE YOU ARE FEELING REMOTE RIGHT NOW?",
54: "=WHAT FEELINGS DO YOU HAVE ABOUT RPC?",
55:
56: "0SORRY0",
57: "=PLEASE DON'T APOLOGIZE.",
58: "=APOLOGIES ARE NOT NECESSARY.",
59: "=WHAT FEELINGS DO YOU HAVE WHEN YOU APOLOGIZE?",
60: "=I'VE TOLD YOU THAT APOLOGIES ARE NOT REQUIRED.",
61: "=APOLOGIES ARE NOT NECESSARY, PLEASE GO ON",
62:
63: "0I AM SAD1",
64: "=I AM SORRY TO HEAR YOU ARE 14.",
65: "=DO YOU THINK COMING HERE WILL HELP YOU NOT TO BE 14?",
66: "=I'M SURE IT'S NOT PLEASANT TO BE 14.",
67: "=CAN YOU EXPLAIN WHAT MADE YOU 14?",
68:
69: "0I AM HAPPY1",
70: "=HOW HAVE I HELPED YOU TO BE 15?",
71: "=HAS YOUR TREATMENT MADE YOU 15?",
72: "=WHAT MAKES YOU 15 JUST NOW?",
73: "=CAN YOU EXPLAIN WHY YOU ARE SUDDENLY 15?",
74:
75: "0NAME0",
76: "=I AM NOT INTERESTED IN NAMES.",
77: "=I'VE TOLD YOU BEFORE I DON'T CARE ABOUT NAMES. PLEASE CONTINUE.",
78:
79: "0 FAMILY1",
80: "=TELL ME MORE ABOUT YOUR 12.", /* string 12 = mother, brother, etc. */
81: "=WHO ELSE IN YOUR FAMILY?",
82: "=YOUR 12?",
83: "=WHAT ELSE COMES TO MIND WHEN YOU THINK OF YOUR 12?",
84:
85: "0I REMEMBER 1",
86: "=DO YOU OFTEN THINK OF 1?",
87: "=WHAT IN THE PRESENT SITUATION REMINDS YOU OF 1?",
88:
89: "0SAME0",
90: "0ALIKE0",
91: "0IS 0LIKE0",
92: "=IN WHAT WAY?",
93: "=WHAT RESEMBLANCE DO YOU SEE?",
94: "=WHAT DOES THAT SIMILARITY SUGGEST TO YOU?",
95: "=WHAT OTHER CONNECTIONS DO YOU SEE?",
96: "=WHAT DO YOU SUPPOSE THAT RESEMBLANCE MEANS?",
97: "=WHAT IS THE CONNECTION, DO YOU SUPPOSE?",
98: "=COULD THERE REALLY BE SOME CONNECTION?",
99: "=HOW?",
100:
101: "0I REMEMBER 1",
102: "=DO YOU OFTEN THINK OF 1?",
103: "=DOES THINKING OF 1 BRING ANYTHING ELSE TO MIND?",
104: "=WHAT ELSE DO YOU REMEMBER?",
105: "=WHY DO YOU REMEMBER 1 JUST NOW?",
106: "=WHAT IN THE PRESENT SITUATION REMINDS YOU OF 1?",
107: "=WHAT IS THE CONNECTION BETWEEN ME AND 1?",
108:
109: "0DO YOU REMEMBER 1",
110: "=DID YOU THINK I WOULD FORGET 1?",
111: "=WHY DO YOU THINK I SHOULD RECALL 1 NOW?",
112: "=WHAT ABOUT 1?",
113: "=YOU MENTIONED 1?",
114:
115: "1 IS MY PROBLEM0",
116: "=1 13 YOUR PROBLEM?",
117: "=ARE YOU SURE 13 1 YOUR PROBLEM?",
118: "=PERHAPS 13 1 NOT YOUR REAL PROBLEM.",
119: "=YOU THINK YOU HAVE PROBLEMS?",
120: "=DO YOU OFTEN THINK ABOUT 1?",
121:
122: "0PROBLEM0",
123: "=PLEASE CONTINUE, THIS MAY BE INTERESTING.",
124: "=HAVE YOU ANY OTHER PROBLEMS YOU WISH TO DISCUSS?",
125: "=PERHAPS YOU'D RATHER CHANGE THE SUBJECT.",
126: "=YOU SEEM A BIT UNEASY.",
127:
128: "0I DREAMT 1",
129: "0I DREAMED 1",
130: "=REALLY 1?",
131: "=HAVE YOU EVER FANTASIZED 1 WHILE YOU WERE AWAKE?",
132: "=HAVE YOU DREAMT 1 BEFORE?",
133: "=WHAT DOES THAT DREAM SUGGEST TO YOU?",
134: "=DO YOU DREAM OFTEN?",
135: "=WHAT PERSONS APPEAR IN YOUR DREAMS?",
136: "=DON'T YOU BELIEVE THAT DREAM HAS SOMETHING TO DO WITH YOUR PROBLEM?",
137: "=DO YOU EVER WISH YOU COULD FLEE FROM REALITY?",
138:
139: "0DREAM0",
140: "=WHAT DOES THAT DREAM SUGGEST TO YOU?",
141: "=DO YOU DREAM OFTEN?",
142: "=WHAT PERSONS APPEAR IN YOUR DREAMS?",
143: "=DON'T YOU BELIEVE THAT DREAM HAS SOMETHING TO DO WITH YOUR PROBLEM?",
144: "=DO YOU EVER WISH YOU COULD FLEE FROM REALITY?",
145:
146: "0IF 1 HAD 2",
147: "=DO YOU THINK IT'S LIKELY THAT 1 MIGHT HAVE 2?",
148: "=DO YOU WISH THAT 1 HAD 2?",
149: "=REALLY, IF 1 HAD 2?",
150:
151: "0IF 1",
152: "=DO YOU THINK IT'S LIKELY THAT 1?",
153: "=DO YOU WISH THAT 1?",
154: "=WHAT DO YOU THINK ABOUT 1?",
155: "=REALLY, IF 1?",
156:
157: "WAS I 1",
158: "=WHAT IF YOU WERE 1?",
159: "=DO YOU THINK YOU WERE 1?",
160: "=WERE YOU 1?",
161: "=WHAT WOULD IT MEAN IF YOU WERE 1?",
162: "=WHAT DOES \"1\" SUGGEST TO YOU?",
163: "=WHY DO YOU ASK?",
164: "=DOES THAT QUESTION INTERST YOU?",
165: "=WHAT IS IT YOU REALLY WANT TO KNOW?",
166: "=ARE SUCH QUESTIONS MUCH ON YOUR MIND?",
167: "=WHAT ANSWER WOULD PLEASE YOU MOST?",
168: "=WHAT DO YOU THINK?",
169: "=WHAT COMES TO YOUR MIND WHEN YOU ASK THAT?",
170: "=HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
171: "=HAVE YOU ASKED ANYONE ELSE?",
172:
173: "0I WAS 1",
174: "=WERE YOU REALLY?",
175: "=WHY DO YOU TELL ME YOU WERE 1 NOW?",
176: "=PERHAPS I ALREADY KNEW YOU WERE 1.",
177:
178: "WERE YOU 1",
179: "=WOULD YOU LIKE TO BELIEVE THAT I WAS 1?",
180: "=WHAT SUGGESTS THAT I WAS 1?",
181: "=WHAT DO YOU THINK?",
182: "=PERHAPS I WAS 1.",
183: "=WHAT IF I HAD BEEN 1.",
184:
185: "0 MY 1",
186: "MY 1",
187: "=YOUR 1?",
188: "=WHY DO YOU SAY YOUR 1?",
189: "=DOES THAT SUGGEST ANYTHING ELSE WHICH BELONGS TO YOU?",
190: "=IS IT IMPORTANT TO YOU THAT 1?",
191:
192: "0EVERYONE0",
193: "0EVERYBODY0",
194: "=REALLY, EVERYONE?",
195: "=SURELY NOT EVERYONE.",
196: "=CAN YOU THINK OF ANYONE IN PARTICULAR?",
197: "=WHO, FOR EXAMPLE?",
198: "=YOU ARE THINKING OF A VERY SPECIAL PERSON.",
199: "=WHO, MAY I ASK?",
200: "=SOMEONE SPECIAL, PERHAPS.",
201: "=YOU HAVE A PARTICULAR PERSON IN MIND, DON'T YOU?",
202: "=WHO DO YOU THINK YOU'RE TALKING ABOUT?",
203: "=I SUSPECT YOU'RE EXAGGERATING A LITTLE.",
204:
205: "NO ONE0",
206: "0 NO ONE0",
207: "0NOBODY0",
208: "=REALLY, NO ONE?",
209: "=SURELY SOMEONE.",
210: "=CAN YOU THINK OF ANYONE IN PARTICULAR?",
211: "=WHO, FOR EXAMPLE?",
212: "=YOU ARE THINKING OF A VERY SPECIAL PERSON.",
213: "=WHO, MAY I ASK?",
214: "=SOMEONE SPECIAL, PERHAPS.",
215: "=YOU HAVE A PARTICULAR PERSON IN MIND, DON'T YOU?",
216: "=WHO DO YOU THINK YOU'RE TALKING ABOUT?",
217: "=I SUSPECT YOU'RE EXAGGERATING A LITTLE.",
218:
219: "0ALWAYS0",
220: "=CAN YOU THINK OF A SPECIFIC EXAMPLE?",
221: "=WHEN?",
222: "=WHAT INCIDENT ARE YOU THINKING OF?",
223: "=REALLY, ALWAYS?",
224: "=WHAT IF THIS NEVER HAPPENED?",
225:
226:
227: /**********/
228:
229: "0HOW 0",
230: "0WHERE 0",
231: "=WHY DO YOU ASK?",
232: "=DOES THAT QUESTION INTERST YOU?",
233: "=WHAT IS IT YOU REALLY WANT TO KNOW?",
234: "=ARE SUCH QUESTIONS MUCH ON YOUR MIND?",
235: "=WHAT ANWSER WOULD PLEASE YOU MOST?",
236: "=WHAT DO YOU THINK?",
237: "=WHAT COMES TO YOUR MIND WHEN YOU ASK THAT?",
238: "=HAVE YOU ASKED SUCH QUESTIONS BEFORE?",
239: "=HAVE YOU ASKED ANYONE ELSE?",
240:
241:
242: /**********/
243:
244: /* "there is no" strings must precede "there is" strings */
245: "0THERE IS NO 1",
246: "0THERE IS NOT 1",
247: "=WHAT IF THERE WERE 1",
248: "=DID YOU THINK THERE MIGHT BE 1",
249: "=HOW 13 1 RELATED TO YOU?",
250: /* these must follow "there is no" strings */
251: "0THERE IS 1",
252: "=13 THERE REALLY 1?", /* string 13 = "is" or "are" */
253: "=HOW 13 1 RELATED TO YOU?",
254:
255: /**********/
256:
257: "0SEX 1",
258: "=DO YOU REALLY WANT TO DISCUSS SEX?",
259: "=DO YOU EVER DREAM ABOUT SEX?",
260: "=WHY DO YOU MENTION SEX?",
261: "=COULD SEX BE PART OF YOUR PROBLEM?",
262:
263: "0HECK1", // checks for strong language
264: "0DARN1",
265: "=ARE SUCH OBSCENITIES FREQUENTLY ON YOUR MIND?",
266: "=YOU ARE BEING A BIT CHILDISH.",
267: "=REALLY NOW",
268: "=DEAR ME",
269: "=I REALLY SHOULDN'T TOLERATE SUCH LANGUAGE.",
270:
271: /***************/
272:
273: "0MY FRIEND 1",
274: "=WHAT ELSE CAN YOU TELL ME ABOUT YOUR FRIEND?",
275: "=WHAT MIGHT YOUR FRIEND HAVE TO DO WITH THE PROBLEM?",
276:
277: /***************/
278:
279: /* last resort */
280:
281: "0", // last resort: match anything
282: "=PLEASE GO ON.",
283: "=I AM NOT SURE I UNDERSTAND YOU FULLY.",
284: "=WHAT DOES THAT SUGGEST TO YOU?",
285: "=DO YOU FEEL STRONGLY ABOUT DISCUSSING SUCH THINGS?",
286: NULL // special end of list character
287: };
288:
289: int iLastIndex = 0; // don't send same response twice in a row
290: // note: this requires 2 responses for each pattern
291:
292: char Substring[20][STRSIZE] = {
293: "", "", "", "", "", "", "", "", "", "",
294: "REMEMBER", /* 10 */
295: "COMPUTER", /* 11 */
296: "FAMILY", /* 12 */
297: "IS", /* 13 */
298: "", "", "", "", "", "" };
299:
300:
301: int Match (char *str, char *pat)
302: {
303: char * pStr; // backup ptr to the user input string
304: char * pPat; // backup ptr to the pattern
305: char *pSubstr = NULL; // possible substrings within pattern
306: int index = 0; // index to substring
307:
308: while (TRUE) { // exit routine from within this loop
309: if (isdigit(*pat)) { // replaceable pattern number
310: index = atoi(pat);
311: while (isdigit(*pat)) // skip number in pattern
312: pat++;
313: pSubstr = Substring[index]; // pointer to current substring
314:
315: if (*pat == '\0') { // if end of pattern, everything will match
316: strcpy(pSubstr, str); // copy rest of input into substring
317: return(TRUE);
318: }
319: else while (*pat != *str) { // match all to specific char in pattern
320: *pSubstr++ = *str++; // fill substring
321: if (*str == '\0') // stuff left to match, but no input
322: return(FALSE);
323: *pSubstr = '\0'; // can overwrite if there's more...
324: }
325: pStr = str; // keep track; it may still be *
326: pPat = pat; // keep track; it may still be *
327: } // end if isdigit pattern number
328:
329: if (*str == *pat) { // matches the specific pattern
330: str++; // skip to next character of input string
331: pat++; // skip to next character of pattern
332: if ((*str == '\0') && (*pat == '\0')) // both at end?
333: return(TRUE);
334: } // end if character match
335: else if (pSubstr != NULL) { // didn't match specific, so still * substring
336: pat = pPat; // restore ptr to input pattern
337: while (pStr < str) // catch up to current input character
338: *pSubstr++ = *pStr++;
339: while (*pat != *str) { // match to next possible match in pattern
340: *pSubstr++ = *str++; // fill substring with more characters
341: if (*str == '\0') // stuff left to match, but no input
342: return(FALSE);
343: }
344: *pSubstr = '\0'; // can overwrite if there's more...
345: pStr = str; // keep track; may still be *
346: pPat = pat; // keep track; may still be *
347: } // end else if
348: else
349: return(FALSE); // no match
350: } // end while (TRUE) loop
351: } // end of function Match
352:
353:
354: /* Respond: adds possible substrings to the response string */
355:
356: void Respond(char *str, char *finalstr)
357: {
358: char copy[STRSIZE]; // copy of the substring to process token at a time
359: char *token;
360: char *word;
361: int index; // index to substring (string converted to number)
362: int len = 0; // index to output string for sprintf
363:
364: while (*str) {
365: if (isdigit(*str)) { // check for pattern number
366: index = atoi(str); // process entire substring
367: while (isdigit(*str)) // skip number in pattern
368: str++;
369: strcpy(copy, &Substring[index][0]); // process substring
370: token = strtok(copy, " "); // skip blanks
371: while (token) {
372: word = token;
373: if (strcmp(token,"I") == 0) (word = "YOU");
374: else if (strcmp(token,"YOU") == 0) (word = "I");
375: else if (strcmp(token,"ME") == 0) {word = "YOU";}
376: else if (strcmp(token,"MY") == 0) {word = "YOUR";}
377: else if (strcmp(token,"YOUR") == 0) {word = "MY";}
378: else if (strcmp(token,"MINE") == 0) {word = "YOURS";}
379: else if (strcmp(token,"YOURS") == 0) {word = "MINE";}
380: else if (strcmp(token,"MYSELF") == 0) {word = "YOURSELF";}
381: else if (strcmp(token,"YOURSELF") == 0) {word = "MYSELF";}
382: else if (strcmp(token,"I'M") == 0) {word = "YOU'RE";}
383: else if (strcmp(token,"YOU'RE") == 0) {word = "I'M";}
384: else if (strcmp(token,"AM") == 0) {word = "ARE";}
385: else if (strcmp(token,"WAS") == 0) {word = "WERE";}
386:
387: len += sprintf(finalstr + len, "%s", word);
388:
389: if ((token = strtok(NULL, " ")) != NULL) // get next token from substr
390: len += sprintf(finalstr + len, " ");
391: } // end while token
392: } // end if isdigit
393: else
394: len += sprintf(finalstr + len, "%c", *str++);
395: } // end while str
396: len += sprintf(finalstr + len, "\n");
397: } // end of function Respond
398:
399:
400:
401: void Synonyms(char *input, char *output)
402: {
403: char *ps1 = input;
404: char *ps2 = output;
405: char *token;
406: char *word;
407:
408: while (*ps1) { // convert to uppercase and check for special chars
409: *ps1 = toupper(*ps1);
410: if ( (*ps1 == '.') || (*ps1 == ',') || (*ps1 == '!') || (*ps1 == '?')
411: || (*ps1 == ';') || (*ps1 == ':') || (! isprint(*ps1)) )
412: *ps1 = '\0';
413: ps1++;
414: } // ok, it's preprocessed now...let's check for pattern matches
415:
416: ps1 = input; // back to the beginning...
417: strcpy(ps2, "");
418: token = strtok(ps1, " "); // skip blanks
419: while (token) {
420: word = token;
421: if ((strcmp(token,"RECALL") == 0) || (strcmp(token,"RECOLLECT") == 0)){
422: word = "REMEMBER"; // use this synonym for pattern-matching
423: }
424: else if (strcmp(token,"MACHINE") == 0) {
425: strcpy(&Substring[11][0], token); // 11 is hardcoded into response
426: word = "COMPUTER"; // use this synonym for pattern-matching
427: }
428: else if ((strcmp(token,"MOTHER") == 0)||(strcmp(token,"MOMMY") == 0)
429: ||(strcmp(token,"FATHER") == 0)||(strcmp(token,"DADDY") == 0)
430: ||(strcmp(token,"SISTER") == 0)||(strcmp(token,"BROTHER") == 0)
431: ||(strcmp(token,"AUNT") == 0)||(strcmp(token,"UNCLE") == 0)){
432: strcpy(&Substring[12][0], token); // 12
433: word = "FAMILY";
434: }
435: else if ((strcmp(token,"ARE") == 0)||(strcmp(token,"IS") == 0)){
436: strcpy(&Substring[13][0], token); // 13
437: word = "IS";
438: }
439: else if ((strcmp(token,"SAD") == 0)||(strcmp(token,"UNHAPPY") == 0)
440: ||(strcmp(token,"DEPRESSED") == 0)||(strcmp(token,"SICK") == 0)){
441: strcpy(&Substring[14][0], token); // 14
442: word = "SAD";
443: }
444: else if ((strcmp(token,"HAPPY") == 0)||(strcmp(token,"ELATED") == 0)
445: ||(strcmp(token,"GLAD") == 0)||(strcmp(token,"BETTER") == 0)){
446: strcpy(&Substring[15][0], token); // 15
447: word = "HAPPY";
448: }
449:
450: strcat(ps2, word);
451: token = strtok(NULL, " ");
452: strcat(ps2, " "); // restore space
453: } // end while token
454: } // end function Synonyms
455:
456:
457:
458:
459: void Analyze(unsigned char *str)
460: {
461: int i; // index to entry within Pattern
462: int j; // index to first possible response string
463: int index; // index of the actual response string used
464: int count = 0; // count of all possible response strings (must be >2)
465: char *response;
466: char *space = NULL;
467: char synstr[STRSIZE];
468:
469: Synonyms(str, synstr);
470:
471: i = 0;
472: while (Pattern[i] != NULL) { // check against all patterns
473: if (Pattern[i][0] != '=') { // if not a doctor pattern
474: if (Match(synstr, Pattern[i]) == TRUE) {
475:
476: while (Pattern[i] && Pattern[i][0] != '=')
477: i++; // skip past patient input to doctor responses
478:
479: if (Pattern[i] && Pattern[i][0] == '=') {
480: count = 1; // count number of possible responses
481: j = i; // index to beginning of doctor responses
482: ++i;
483: }
484:
485: while (Pattern[i] && Pattern[i][0] == '=') {
486: ++count; // bump counter; another doctor response
487: ++i;
488: }
489:
490: do // pick a different doctor response from last time
491: index = j + (rand() % count);
492: while (index == iLastIndex);
493:
494: response = &Pattern[index][1];
495: iLastIndex = index; // keep track of response used last
496: Respond(response, str); // process the response
497: return;
498: } // end if match
499: } // end if patient pattern
500: ++i; // next pattern
501: } // end while pattern
502: } // end function Analyze
503:
504:
505: /* shutdown the server by calling RPC API functions */
506:
507: void Shutdown(void)
508: {
509: RPC_STATUS status;
510:
511: printf("Calling RpcMgmtStopServerListening\n");
512: status = RpcMgmtStopServerListening(NULL);
513: printf("RpcMgmtStopServerListening returned: 0x%x\n", status);
514: if (status) {
515: exit(2);
516: }
517:
518: printf("Calling RpcServerUnregisterIf\n");
519: status = RpcServerUnregisterIf(NULL, NULL, FALSE);
520: printf("RpcServerUnregisterIf returned 0x%x\n", status);
521: if (status) {
522: exit(2);
523: }
524: }
525:
526:
527: /* end of file \doctorp.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.