[LONG] [Spec_Proc] Re: mobs responding to tells

From: Alvoria MUD (mudguy@conan.ids.net)
Date: 12/16/96


On Sun, 15 Dec 1996, Cyber Reaper wrote:
> ok.. I need help with this one.. I have thought of every way I could to do
> this and am WAY lost... here is the idea...
>
> <snip>
> 
> now.. I know it would be a if statment.. but I dont know how to get her to
> respond
> to tells.. =:( can anyone send me a short example spec_proc...
> 

Okie... here's my response... this is a spec_proc I was kindof putting off
making, but then upon getting the message from Terry I decided to get it
done... :P... It's all kindof simple to understand... I suppose, it
basically will reply with an appropriate response based on what keywords/
tokens it sees in the question. It's a really cheezy way to make it give
intelligible answers but it does what it has to do... Of course this
assumes that players will always give it complete sentences so it looks
like it's intelligent... *stare*

Btw this will only work for 1 mob... if you want different mobs to be able
to use their own text to reply with... etc etc... you have some work to do
but it's not too difficult to change this. :) . Perhaps I will edit this
in the future to poise it as an alternative to the Eliza patch... maybe...
Also it's not too difficult to change or add sentences/phrases... for the
sake of your mud's sanity... PLEASE change the sentences... the ones I
have there are just for testing purposes (but please leave the one about
me. :) )

Enjoy...

  - mendar

--

/* 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)

struct strung_token
{
  int thing;
  int reference;
  int ask_type;
};

/* 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},
  { 1, T_IGNORE, 2},     /* 1 */
  { 2, 3, 8},            
  { 5, 2, 2},            /* 3 */
  { 3, 4, 3},            
  { 4, T_IGNORE, 6},     /* 5 */
  { 6, 6, 2},            
  { 7, 1, 6}             /* 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;
  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");
            assert(0);
          break;
        }

      if(exist)
        {
          return index;
        }
    }
  return T_UNKNOWN;
}

int match_sentence(struct strung_token sentence)
{
  int index;

  for(index=0; index<=T_NUM_SENTENCES ; index++)
    {
      if(((sentence.thing==valid_queries[index].thing)||
          (sentence.thing==T_IGNORE))&&
         ((sentence.reference==valid_queries[index].reference)||
          (sentence.reference==T_IGNORE))&&
         ((sentence.ask_type==valid_queries[index].ask_type)||
          (sentence.ask_type==T_IGNORE)))
        return index;
    }
  return 0;
}

SPECIAL(know_it_all)
{
  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"))
    {
      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);

      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);

      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);
}


--
Alvoria MUD -- "I forced it to SIGSEGV... it got stuck... " (??)
  Address   -- telnet://conan.ids.net:4000/
  Homepage  -- http://users.ids.net/~mudguy/
  Host Site -- http://www.ids.net/

+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
+-----------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/18/00 PST