From: Mendar Subject: Tell-Proc -- /* start of that know it all... or something */ /* Some Documentation... Comments... Okie... this is really cheezy, but for most sentences it will work. :) Basically what it does is check each of the three arrays of tokens for the first token of each list to match. I suppose I could make it all one array, but then there are some sentences that would not be comprehensible if that were done... (ie some words masquerade as nouns and 'references' etc... ) */ #define T_IGNORE (-1) #define T_UNKNOWN (0) #define T_THING (0) #define T_REFERENCE (1) #define T_ASK_TYPE (2) #define T_NUM_SENTENCES (7) #define T_TEST_MOB (1) /* I used puff... she's such a sport.. :P */ /* The following struct is used to define the format for a sentence/ strung set of tokens the spec understands.... the vnum is there so you can isolate which mobs can understand the paticular string. In the valid token strung array down below, set vnum to be T_IGNORE if you want all the mobs to be able to understand that phrase. */ struct strung_token { int thing; int reference; int ask_type; int vnum; }; /* Here is a list of 'nouns' or other objects */ const char *thing_tokens[] = { "ZZZ", /* leave this one unused */ "dragon", /* 1 */ "chickens", "cityguards", /* 3 */ "immortals", "weapon", /* 5 */ "guildmaster", "you", /* 7 */ /* Remember this would be > ME <, the mob that the spec is assigned to... */ "&" }; /* Here is a list of 'references' or 'qualities' that apply. */ const char *reference_tokens[] = { "ZZZ", /* leave this one unused */ "made", /* 1 */ "good", "strong", /* 3 */ "evil", "good", /* 5 */ "my", "&" }; /* Here is a list of the keywords that define the question */ const char *ask_type_tokens[]= { "ZZZ", /* leave this one unused */ "what", /* 1 */ "where", "why", /* 3 */ "when", "how", /* 5 */ "who", "is", /* 7 */ "are", /* This token should be at the end because a question like "Where are" will get mixed up if it sees 'are' first */ "&" }; /* This is a list of valid 'sentences' accepted */ /* Use T_IGNORE if you want it to ignore what value is present for the question */ struct strung_token valid_queries[] = { { T_IGNORE, T_IGNORE, T_IGNORE, T_IGNORE}, { 1, T_IGNORE, 2, T_TEST_MOB}, /* 1 */ { 2, 3, 8, T_TEST_MOB}, { 5, 2, 2, T_TEST_MOB}, /* 3 */ { 3, 4, 3, T_TEST_MOB}, { 4, T_IGNORE, 6, T_TEST_MOB}, /* 5 */ { 6, 6, 2, T_TEST_MOB}, { 7, 1, 6, T_IGNORE} /* 7 */ }; /* The Examples, Tokens are in Caps. */ /* 0. No example here. :P. */ /* 1. WHERE is the DRAGON? */ /* 2. ARE the CHICKENS STRONG? */ /* 3. WHERE can I get GOOD WEAPONS? */ /* 4. WHY do CITYGUARDS attack EVIL people? */ /* 5. WHO are the IMMORTALS? */ /* 6. WHERE is MY GUILDMASTER? */ /* 7. WHO MADE YOU? */ /* Please leave this line+reply intact... (etc.) :) - mendar */ /* Here are the corresponding replies. */ const char *reply_lines[] = { /* This response is if the guy doesn't understand. */ /* It's only called if the ask_type exists., else it won't say anything at all. */ /* Consider this line as 'reserved' :P */ "I don't know.", "The Dragon is below the steel door in the mining cave.", "No, the chickens are not very strong.", "The weaponmaster in Mandreth has good weapons.", "The cityguards attack them to preserve Mandreth.", "Type wizlist and immlist to see the names of the Immortals.", "There is only one guildmaster, the Avatar above Martyr's Square.", "Mendar made me. He sleeps too much." }; void all_tolower(char *string) { register char *index; index=string; while(*index) { *index=LOWER(*index); index++; } } int get_t_token(const char *sentence, int which) { char *exist=NULL; int flag=TRUE,index=0; while(flag) { index++; switch(which) { case T_THING: if((*(thing_tokens[index]))!='&') { exist=strstr(sentence,thing_tokens[index]); } else { return T_UNKNOWN; } break; case T_REFERENCE: if((*(reference_tokens[index]))!='&') { exist=strstr(sentence,reference_tokens[index]); } else { return T_UNKNOWN; } break; case T_ASK_TYPE: if((*(ask_type_tokens[index]))!='&') { exist=strstr(sentence,ask_type_tokens[index]); } else { return T_UNKNOWN; } break; default: send_to_all("Error in t_token.\r\n"); break; } if(exist) { return index; } } return T_UNKNOWN; } int match_sentence(struct strung_token sentence) { int index; for(index=1; index<=T_NUM_SENTENCES ; index++) { if(((sentence.thing==valid_queries[index].thing)|| (valid_queries[index].thing==T_IGNORE))&& ((sentence.reference==valid_queries[index].reference)|| (valid_queries[index].reference==T_IGNORE))&& ((sentence.ask_type==valid_queries[index].ask_type)|| (valid_queries[index].ask_type==T_IGNORE)) && ((sentence.vnum==valid_queries[index].vnum)|| (valid_queries[index].vnum==T_IGNORE))) return index; } return 0; } SPECIAL(tell_proc) { ACMD(do_tell); struct char_data *self, *someone; struct strung_token sentence_tokens; char lbuf_1[250], lbuf_2[250], temp_buf[250]; int my_reply; self=(struct char_data *)me; if(CMD_IS("tell")) /* Uncomment and switch the line below with the one above if you want it to use ask instead of tell. Another line like this below. */ /* if(CMD_IS("ask")) */ { strcpy(temp_buf,argument); half_chop(argument, lbuf_1, lbuf_2); /* after the half_chop and the strcpy, temp_buf is the orignal line, */ /* argument is messed up :P, lbuf_1 is who, lbuf_2 is what to tell */ if(!(lbuf_1 && lbuf_2)) { strcpy(argument, temp_buf); return (0); /* let the normal do_tell take care of it. */ } someone = get_char_vis(ch, lbuf_1); if(someone!=self) { strcpy(argument, temp_buf); return (0); /* again, let do_tell handle it. */ } do_tell(ch, temp_buf, cmd, 0); /* Uncomment and switch the line below with the one above if you want it to use ask instead of tell. Another line like this above.*/ /* do_ask(ch, temp_buf, cmd, 0); */ all_tolower(lbuf_2); sentence_tokens.thing = get_t_token(lbuf_2,T_THING); sentence_tokens.reference = get_t_token(lbuf_2, T_REFERENCE); sentence_tokens.ask_type = get_t_token(lbuf_2, T_ASK_TYPE); sentence_tokens.vnum = GET_MOB_VNUM(self); /* on the prev. line remember that this proc is ASSIGNED to the mob... so it's self rather than ch. */ my_reply=match_sentence(sentence_tokens); if(!my_reply) { if(sentence_tokens.ask_type>T_UNKNOWN) { my_reply=0; } else { my_reply=-1; } } /* at this point we don't care about lbuf_1 so we'll recycle it :P */ if(my_reply!=-1) { sprintf(lbuf_1,"%s tells you, '%s'\r\n", PERS(self,ch), reply_lines[my_reply]); send_to_char(lbuf_1,ch); } return (1); } return (0); }