exodus2/
exodus2/area/mobscr/
exodus2/area/mobvoc/
exodus2/bin/
exodus2/clans/
exodus2/gods/
exodus2/player/A/
exodus2/player/B/
exodus2/player/D/
exodus2/player/E/
exodus2/player/L/
exodus2/player/M/
exodus2/player/O/
exodus2/player/R/
exodus2/src/obj/clans/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "merc.h"
#include "tables.h"
#include "interp.h"
#include "clans/new_clans.h"
#include "clans/new_clans_comm.h"
#include "clans/new_clans_io.h"
#include "clans/new_clans_util.h"

inline void variable_substitution_new (CHAR_DATA *ch, CHAR_DATA *victim, CHAR_DATA *wearer, CHAR_DATA *extra, char *string);
	

inline int said_name (char *name, struct talk_list *tlist)
{
  struct talk_list *walk_tlist;
  for (walk_tlist = tlist; walk_tlist; walk_tlist = walk_tlist->next)
    if (is_name (walk_tlist->word, name))
      return (1);
  return (0);
}
inline void free_response_list (struct response_list *rlist)
{
  struct response_list *walk_rlist, *next_rlist;
  for (walk_rlist = rlist; walk_rlist; walk_rlist = next_rlist)
    {
      next_rlist = walk_rlist->next;
      free (walk_rlist);
    }
}
inline void free_talk_list (struct talk_list *tlist)
{
  struct talk_list *walk_tlist, *next_tlist;
  for (walk_tlist = tlist; walk_tlist; walk_tlist = next_tlist)
    {
      next_tlist = walk_tlist->next;
      free (walk_tlist);
    }
}
inline void
respond (CHAR_DATA * ch, CHAR_DATA * mob, struct response_list *rlist,
	 int from)
{
  char first_word[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  char *cptr;
  cptr = strtok (rlist->text, ";");
  if (cptr == NULL)
    return;
  cptr = one_argument_nl (cptr, first_word);
  if (!str_cmp (first_word, "cmd"))
    interpret (mob, cptr);

  else if (!str_cmp (first_word, "trig"))
    {
      if (HAS_SCRIPT (mob))
	{
	  TRIGGER_DATA *trig;
	  char trigcmd[MAX_STRING_LENGTH];
	  cptr = one_argument (cptr, trigcmd);
	  for (trig = mob->triggers; trig != NULL; trig = trig->next)
	    {
	      if (trig->current == NULL && !IS_SET (mob->act, ACT_HALT)
		  && !str_cmp (trig->name, trigcmd))
		{
		  act_trigger (mob, trig->name, rlist->wassaid, NAME (ch),
			       NAME (mob));
		  trig->current = trig->script;
		  trig->bits = SCRIPT_ADVANCE;
		}
	    }
	}
    }
  else
    {
      if (from == 0 && ch->race != 7)
	{
	  sprintf (buf, "%s %s %s", ch->name, first_word, cptr);
	  do_tell (mob, buf);
	}
      else
	{
	  sprintf (buf, "%s %s", first_word, cptr);
	  do_say (mob, buf);
	}
    }
  while ((cptr = strtok (NULL, ";")) != NULL)
    {
      cptr = one_argument_nl (cptr, first_word);
      if (!str_cmp (first_word, "cmd"))
	interpret (mob, cptr);

      else if (!str_cmp (first_word, "trig"))
	{
	  if (HAS_SCRIPT (mob))
	    {
	      TRIGGER_DATA *trig;
	      char trigcmd[MAX_STRING_LENGTH];
	      cptr = one_argument (cptr, trigcmd);
	      for (trig = mob->triggers; trig != NULL; trig = trig->next)
		{
		  if (trig->current ==
		      NULL && !IS_SET (mob->act,
				       ACT_HALT) && !str_cmp (trig->
							      name, trigcmd))
		    {
		      act_trigger (mob, trig->name, rlist->wassaid,
				   NAME (ch), NULL);
		      trig->current = trig->script;
		      trig->bits = SCRIPT_ADVANCE;
		    }
		}
	    }
	}
      else
	{
	  if (from == 0 && ch->race != 7)
	    {
	      sprintf (buf, "%s %s %s", ch->name, first_word, cptr);
	      do_tell (mob, buf);
	    }
	  else
	    {
	      sprintf (buf, "%s %s", first_word, cptr);
	      do_say (mob, buf);
	    }
	}
    }
}

inline void variable_substitution (CHAR_DATA * ch, char *string)
{
	variable_substitution_new (ch,NULL,NULL,NULL,string);
}

inline void variable_substitution_new (CHAR_DATA *ch, CHAR_DATA *victim, 
				       CHAR_DATA *wearer, CHAR_DATA *extra, char *string)
{
  char new_string[MAX_STRING_LENGTH];
  char *cptr, *cptr2;
  char buf[MAX_STRING_LENGTH];

  /* Substitute character name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$name")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (!IS_NPC(ch))
        strcat (new_string, ch->name);
      else strcat (new_string, ch->short_descr);
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute area name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$area")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      strcat (new_string, ch->in_room->area->name);
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute room name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$room")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      strcat (new_string, ch->in_room->name);
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute level */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$level")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      sprintf (new_string + strlen (new_string), "%d", ch->level);
      cptr2 = (cptr + 6);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute race name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$race")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (!IS_NPC(ch))
        strcat (new_string, pc_race_table[ch->race].name);
      else strcat (new_string, race_table[ch->race].name);
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute clan name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$clan")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (ch->clan != CLAN_BOGUS)
	strcat (new_string, get_clan_name_ch (ch));

      else
	strcat (new_string, "no clan");
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute class name */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$class")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (IS_NPC(ch))
        strcat (new_string, "mobile");
      else strcat (new_string, class_table[ch->class].name);
      cptr2 = (cptr + 6);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute time */
  cptr2 = string;
  new_string[0] = '\0';
  while ((cptr = strstr (cptr2, "$time")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      sprintf (new_string + strlen (new_string), "%d o'clock %s",
	       (time_info.hour % 12 == 0) ? 12 : time_info.hour % 12,
	       time_info.hour >= 12 ? "pm" : "am");
      cptr2 = (cptr + 5);
    }
  strcat (new_string, cptr2);
  strcpy (string, new_string);

  /* Substitute he/she/it */
  cptr2 = string;

  new_string[0] = '\0';

  while ((cptr = strstr (cptr2, "$e")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      strcat (new_string, (ch->sex == SEX_MALE)?"he":((ch->sex == SEX_FEMALE)?"she":"it"));
      cptr2 = (cptr + 2);
    }

  strcat (new_string, cptr2);

  strcpy (string, new_string);

  /* Substitute him/her/it */
  cptr2 = string;

  new_string[0] = '\0';

  while ((cptr = strstr (cptr2, "$m")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      strcat (new_string, (ch->sex == SEX_MALE)?"him":((ch->sex == SEX_FEMALE)?"her":"it"));
      cptr2 = (cptr + 2);
    }

  strcat (new_string, cptr2);

  strcpy (string, new_string);

  /* Substitute his/her/its */
  cptr2 = string;

  new_string[0] = '\0';

  while ((cptr = strstr (cptr2, "$s")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      strcat (new_string, (ch->sex == SEX_MALE)?"his":((ch->sex == SEX_FEMALE)?"her":"its"));
      cptr2 = (cptr + 2);
    }

  strcat (new_string, cptr2);

  strcpy (string, new_string);

  /* Substitute random mob */
  cptr2 = string;

  new_string[0] = '\0';

  while ((cptr = strstr (cptr2, "$randmob")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (ch->in_room)
	{
	  int i=0,amount=0;
	  CHAR_DATA *tch;
	  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
	    {
	      if (IS_NPC(tch))
		++amount;
	    }
	  if (amount != 0)
	  {
	    amount = number_range(1,amount);

	    for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
            {
	      if (IS_NPC(tch))
	      {
		if (++i == amount)
		  {
                  strcat (new_string, tch->short_descr);
	          break;
		  }
	      }
	    }
	  }
	  else strcat (new_string, "NOONE");
	    
          cptr2 = (cptr + 8);
	  
	}
    }

  strcat (new_string, cptr2);

  strcpy (string, new_string);
  /* Substitute random pc */
  cptr2 = string;

  new_string[0] = '\0';

  while ((cptr = strstr (cptr2, "$randpc")) != NULL)
    {
      *cptr = '\0';
      strcat (new_string, cptr2);
      if (ch->in_room)
        {
          int i=0,amount=0;
          CHAR_DATA *tch;
          for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
            {
              if (!IS_NPC(tch))
                ++amount;
            }
          if (amount != 0)
            {
	      amount = number_range(1,amount);

	      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
		{
		  if (!IS_NPC(tch))
		    if (++i == amount)
		      {
			strcat (new_string, tch->name);
			break;
		      }
		}
            }
          else strcat (new_string, "NOONE");
	  cptr2 = (cptr + 7);
	}
    }
      strcat (new_string, cptr2);

      strcpy (string, new_string);

      /* Substitute random pc (but NOT ch, setter offer of trigger)*/
      cptr2 = string;

      new_string[0] = '\0';

      while ((cptr = strstr (cptr2, "$2randpc")) != NULL)
	{
	  *cptr = '\0';
	  strcat (new_string, cptr2);
	  if (ch->in_room)
	    {
	      int i=0,amount=0;
	      CHAR_DATA *tch;
	      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
		{
		  if (!IS_NPC(tch) && tch != ch)
		    ++amount;
		}
	      if (amount != 0)
		{
		  amount = number_range(1,amount);

		  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
		    {
		      if (!IS_NPC(tch) && tch != ch)
			if (++i == amount)
			  {
			    strcat (new_string, tch->name);
			    break;
			  }
		    }
		}
	      else strcat (new_string, "NOONE");
	      cptr2 = (cptr + 8);
	    }
	}
	  strcat (new_string, cptr2);

	  strcpy (string, new_string);

	  /* Substitute random ch (but not ch IE the triggerer of the trigger)*/
	  cptr2 = string;

	  new_string[0] = '\0';

	  while ((cptr = strstr (cptr2, "$2randch")) != NULL)
	    {
	      *cptr = '\0';
	      strcat (new_string, cptr2);
	      if (ch->in_room)
		{
		  int i=0,amount=0;
		  CHAR_DATA *tch;
		  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
		    {
		      if (tch != ch)
			++amount;
		    }
		  if (amount != 0)
		    {
		      amount = number_range(1,amount);

		      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			{
			  if (tch != ch)
			    if (++i == amount)
			      {
				if (!IS_NPC(tch))
				  strcat (new_string, tch->name);
				else strcat (new_string, tch->short_descr);
				break;
			      }
			}
		    }
		  else strcat (new_string, "NOONE");
		  cptr2 = (cptr + 8);
		}
	    }
	      strcat (new_string, cptr2);

	      strcpy (string, new_string);

	      /* Substitute random ch */
	      cptr2 = string;

	      new_string[0] = '\0';

	      while ((cptr = strstr (cptr2, "$randch")) != NULL)
		{
		  *cptr = '\0';
		  strcat (new_string, cptr2);
		  if (ch->in_room)
		    {
		      int i=0,amount=0;
		      CHAR_DATA *tch;
		      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			{
			    ++amount;
			}
		      if (amount != 0)
			{
			  amount = number_range(1,amount);

			  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			    {
				if (++i == amount)
				  {
				    if (!IS_NPC(tch))
				      strcat (new_string, tch->name);
				    else strcat (new_string, tch->short_descr);
				    break;
				  }
			    }
			}
		      else strcat (new_string, "NOONE");
		      cptr2 = (cptr + 7);
		    }
		}
		  strcat (new_string, cptr2);

		  strcpy (string, new_string);

		  /* Substitute random ch (can be used for spells */
		  cptr2 = string;

		  new_string[0] = '\0';

		  while ((cptr = strstr (cptr2, "$3randch")) != NULL)
		    {
		      *cptr = '\0';
		      strcat (new_string, cptr2);
		      if (ch->in_room)
			{
			  int i=0,amount=0;
			  CHAR_DATA *tch;
			  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			    {
			      ++amount;
			    }
			  if (amount != 0)
			    {
			      amount = number_range(1,amount);

			      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
				{
				  if (++i == amount)
				    {
				      if (!IS_NPC(tch))
					strcat (new_string, tch->name);
				      else 
				      {
					one_argument(tch->name,buf);
					strcat(new_string,buf);
				      }
				      //else strcat (new_string, tch->short_descr);
				      break;
				    }
				}
			    }
			  else strcat (new_string, "NOONE");
			  cptr2 = (cptr + 8);
			}
		    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  /* Substitute random ch (can be used for spells) (NOT THE TRIGGER)*/
		  cptr2 = string;

		  new_string[0] = '\0';

		  while ((cptr = strstr (cptr2, "$4randch")) != NULL)
		    {
		      *cptr = '\0';
		      strcat (new_string, cptr2);
		      if (ch->in_room)
			{
			  int i=0,amount=0;
			  CHAR_DATA *tch;
			  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			    {
			      if (tch != ch)
			        ++amount;
			    }
			  if (amount != 0)
			    {
			      amount = number_range(1,amount);

			      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
				{
 				  if (tch != ch)
				    if (++i == amount)
				      {
				        if (!IS_NPC(tch))
			  		  strcat (new_string, tch->name);
				        else
				        {
				          one_argument(tch->name,buf);
				          strcat(new_string,buf);
				        }
				        break;
				      }
				}
			    }
			  else strcat (new_string, "NOONE");
			  cptr2 = (cptr + 8);
			}
		    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  /* Substitute random mob (can be used for spells) */
		  cptr2 = string;

		  new_string[0] = '\0';

		  while ((cptr = strstr (cptr2, "$2randmob")) != NULL)
		    {
		      *cptr = '\0';
		      strcat (new_string, cptr2);
		      if (ch->in_room)
			{
			  int i=0,amount=0;
			  CHAR_DATA *tch;
			  for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
			    {
			      if (IS_NPC(tch))
			        ++amount;
			    }
			  if (amount != 0)
			    {
			      amount = number_range(1,amount);
				
			      for (tch = ch->in_room->people;tch != NULL;tch = tch->next_in_room)
				{
				  if (IS_NPC(tch))
				    if (++i == amount)
				      {
					 one_argument(tch->name,buf);
			                 strcat(new_string,buf);
				         break;
				      }
				}
			    }
			  else strcat (new_string, "NOONE");
			  cptr2 = (cptr + 9);
			}
		    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  //Substitues for victim's name (returns short_descr for mobs, can be used in say)
		  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$vict")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
		      if (victim)
		      {
                          if (!IS_NPC(victim))
                            strcat (new_string, victim->name);
                          else
			  {
			    strcat(new_string,victim->short_descr);
			  }
		      }
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 5);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  //substitues for victim's name (returns a keyword, can be used for spells)
		  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$2vict")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
		      if (victim)
			{
                          if (!IS_NPC(victim))
                            strcat (new_string, victim->name);
                          else
			    {
			      one_argument(victim->name,buf);
			      strcat(new_string,buf);
			    }
			}
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 6);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  //Substitues for extra's name (returns short_descr for mobs, can be used in say)
                  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$3vict")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
                      if (extra)
			{
                          if (!IS_NPC(extra))
                            strcat (new_string, extra->name);
                          else
			    {
			      strcat(new_string,extra->short_descr);
			    }
			}
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 6);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);


		  //substitues for extra's name (returns a keyword, can be used for spells)
                  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$4vict")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
                      if (extra)
                        {
                          if (!IS_NPC(extra))
                            strcat (new_string, extra->name);
                          else
                            {
                              one_argument(extra->name,buf);
                              strcat(new_string,buf);
                            }
                        }
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 6);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);



		  //substitution for wearer (returns short_descr of mobs, for use in say)
		  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$wearer")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
		      if (wearer)
			{
                          if (!IS_NPC(wearer))
                            strcat (new_string, wearer->name);
                          else
			    {
			      strcat(new_string,wearer->short_descr);
			    }
			}
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 7);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);

		  
		  //substituion for wearer (returns a keyword, can be used in spells etc)
		  cptr2 = string;

                  new_string[0] = '\0';

                  while ((cptr = strstr (cptr2, "$2wearer")) != NULL)
                    {
                      *cptr = '\0';
                      strcat (new_string, cptr2);
		      if (wearer)
                        {
                          if (!IS_NPC(wearer))
                            strcat (new_string, wearer->name);
                          else
                            {
                              one_argument(wearer->name,buf);
                              strcat(new_string,buf);
                            }
                        }
                      else strcat (new_string, "NOONE");
                      cptr2 = (cptr + 8);
                    }
                  strcat (new_string, cptr2);

                  strcpy (string, new_string);




}
inline int calculate_new_mood (char *string, int old_mood)
{
  register sh_int new_mood;
  if (string[0] == '-' && string[1] == '\0')
    return (old_mood);
  switch (string[0])
    {
    case '-':
      new_mood = old_mood - atoi (&string[1]);
      if (new_mood < 0)
	new_mood = 0;

      else if (new_mood > 7)
	new_mood = 7;
      break;
    case '+':
      new_mood = old_mood + atoi (&string[1]);
      if (new_mood < 0)
	new_mood = 0;

      else if (new_mood > 7)
	new_mood = 7;
      break;
    default:
      new_mood = atoi (string);
      if (new_mood < 0)
	new_mood = 0;

      else if (new_mood > 8)
	new_mood = 8;
      break;
    }
  return (new_mood);
}
inline int mood_matches (char *string, int mood_value)
{
  switch (string[0])
    {
    case '<':
      if (mood_value < atoi (&string[1]))
	return (1);
      break;
    case '>':
      if (mood_value > atoi (&string[1]) && mood_value != 8)
	return (1);
      break;
    default:
      if (atoi (string) == mood_value)
	return (1);
      break;
    }
  return (0);
}
inline int word_match (char *word, struct talk_list *talk_words)
{
  struct talk_list *step_words;
  char *cptr;
  if ((cptr = strtok (word, "|")) == NULL)
    return (0);
  for (step_words = talk_words; step_words; step_words = step_words->next)
    {
      if (!str_cmp (step_words->word, cptr))
	return (1);
    }
  while ((cptr = strtok (NULL, "|")) != NULL)
    for (step_words = talk_words; step_words; step_words = step_words->next)
      {
	if (!str_cmp (step_words->word, cptr))
	  return (1);
      }
  return (0);
}

int real_matches;
int default_matches;
struct response_list *responses;
struct response_list *default_responses;
int
match_vocab_file (char *filename, struct talk_list *talk_words, int from,
		  CHAR_DATA * mob, CHAR_DATA * ch, int level, char *wassaid)
{
  struct response_list *new_response;
  char fullpath[MAX_STRING_LENGTH];
  FILE *vocfp;
  register bool found;
  char *cptr, *cchar, *cword;
  char voc_line[MAX_STRING_LENGTH];
  if (level == 5)
    return (0);
  sprintf (fullpath, "mobvoc/%s", filename);
  if ((vocfp = fopen (fullpath, "r")) == NULL)
    return (1);

  /* Skip creator line */
  fgets (voc_line, MAX_STRING_LENGTH, vocfp);
  while (fgets (voc_line, MAX_STRING_LENGTH, vocfp))
    {
      found = TRUE;
      cptr = strchr (voc_line, ':');
      if (cptr == NULL)
	break;
      *cptr = '\0';
      if (!strcmp (voc_line, "DEFAULT")
	  && (from == 0 || said_name (mob->name, talk_words)))
	{
	  cchar = (cptr + 1);
	  cptr = strtok (cchar, ":");
	  if (cptr == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  if (!mood_matches (cptr, mob->mood))
	    continue;
	  default_matches++;
	  new_response = malloc (sizeof (struct response_list));
	  if (new_response == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  cptr = strtok (NULL, ":");
	  new_response->new_mood = calculate_new_mood (cptr, mob->mood);
	  cptr = strtok (NULL, "\n");
	  if (cptr == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  variable_substitution (ch, cptr);
	  strcpy (new_response->text, cptr);
	  strcpy (new_response->wassaid, wassaid);
	  new_response->next = default_responses;
	  default_responses = new_response;
	  continue;
	}
      else if (!strcmp (voc_line, "INCLUDE"))
	{
	  if ((cword = (cptr + 1)) == NULL)
	    continue;
	  if ((cptr = strchr (cword, '\n')) != NULL)
	    *cptr = '\0';
	  if (match_vocab_file
	      (cword, talk_words, from, mob, ch, level + 1, wassaid) == -1)
	    {
	      free_response_list (default_responses);
	      free_response_list (responses);
	      free_talk_list (talk_words);
	      return (-1);
	    }
	  continue;
	}
      cchar = cword = voc_line;
      while (*cchar != '\0')
	{
	  if (*cchar == '&')
	    {
	      *cchar = '\0';
	      if (!word_match (cword, talk_words))
		{
		  found = FALSE;
		  break;
		}
	      cword = (cchar + 1);
	    }
	  cchar++;
	}
      if (found)
	if (!word_match (cword, talk_words))
	  found = FALSE;
      if (!found)
	continue;

      else
	{
	  cchar++;
	  cptr = strtok (cchar, ":");
	  if (cptr == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  if (!mood_matches (cptr, mob->mood))
	    continue;
	  real_matches++;
	  new_response = malloc (sizeof (struct response_list));
	  if (new_response == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  cptr = strtok (NULL, ":");
	  new_response->new_mood = calculate_new_mood (cptr, mob->mood);
	  cptr = strtok (NULL, "\n");
	  if (cptr == NULL)
	    {
	      fclose (vocfp);
	      return (-1);
	    }
	  variable_substitution (ch, cptr);
	  strcpy (new_response->text, cptr);
	  strcpy (new_response->wassaid, wassaid);
	  new_response->next = responses;
	  responses = new_response;
	}
    }
  fclose (vocfp);
  return (0);
}

void mob_talk (CHAR_DATA * ch, CHAR_DATA * mob, char *string, int from)
{
  struct response_list *new_response;
  char *cptr;
  struct talk_list *new_talk;
  register sh_int rand_match;
  struct talk_list *talk_words = NULL;
  char wassaid[MAX_STRING_LENGTH];
  responses = NULL;
  default_responses = NULL;
  real_matches = default_matches = 0;
  if (mob->pIndexData->vocfile[0] == '\0' || mob->mood == 0)
    return;
  strcpy (wassaid, string);
  for (cptr = string; *cptr != '\0'; cptr++)
    {
      if (!isalnum (*cptr))
	*cptr = ' ';
    }
  if ((cptr = strtok (string, " ")) == NULL)
    return;
  if ((talk_words = malloc (sizeof (struct talk_list))) == NULL)
    return;
  talk_words->word = cptr;
  talk_words->next = NULL;
  while ((cptr = strtok (NULL, " ")) != NULL)
    {
      if ((new_talk = malloc (sizeof (struct talk_list))) == NULL)
	return;
      new_talk->word = cptr;
      new_talk->next = talk_words;
      talk_words = new_talk;
    }
  if (talk_words == NULL)
    return;
  if (match_vocab_file
      (mob->pIndexData->vocfile, talk_words, from, mob, ch, 1, wassaid) == -1)
    {
      free_response_list (default_responses);
      free_response_list (responses);
      free_talk_list (talk_words);
    }
  if (real_matches != 0)
    {
      rand_match = number_range (0, real_matches - 1);
      real_matches = 0;
      for (new_response = responses; new_response;
	   new_response = new_response->next)
	{
	  if (rand_match == real_matches)
	    {
	      respond (ch, mob, new_response, from);
	      mob->mood = new_response->new_mood;
	      break;
	    }
	  real_matches++;
	}
    }
  else if (default_matches != 0)
    {
      rand_match = number_range (0, default_matches - 1);
      default_matches = 0;
      for (new_response = default_responses; new_response;
	   new_response = new_response->next)
	{
	  if (rand_match == real_matches)
	    {
	      respond (ch, mob, new_response, from);
	      mob->mood = new_response->new_mood;
	      break;
	    }
	  default_matches++;
	}
    }
  free_response_list (default_responses);
  free_response_list (responses);
  free_talk_list (talk_words);
  return;
}