/***************************************************************************
 *  file: spec_pro.c , Special module.                     Part of DIKUMUD *
 *  Usage: Procedures handling special procedures for object/room/mobile   *
 *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
 *                                                                         *
 *  Copyright (C) 1992, 1993 Michael Chastain, Michael Quan, Mitchell Tse  *
 *  Performance optimization and bug fixes by MERC Industries.             *
 *  You can use our stuff in any way you like whatsoever so long as this   *
 *  copyright notice remains intact.  If you like it please drop a line    *
 *  to mec@garnet.berkeley.edu.                                            *
 *                                                                         *
 *  This is free software and you are benefitting.  We hope that you       *
 *  share your changes too.  What goes around, comes around.               *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "structs.h"
#include "mob.h"
#include "obj.h"
#include "utils.h"
#include "interp.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "limits.h"

/*   external vars  */

extern struct room_data *world;
extern struct descriptor_data *descriptor_list;
extern struct index_data *obj_index;
extern struct time_info_data time_info;


/* extern procedures */

void hit(struct char_data *ch, struct char_data *victim, int type);
void gain_exp(struct char_data *ch, int gain);

void cast_burning_hands( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_chill_touch( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_colour_spray( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_energy_drain( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_fireball( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_magic_missile( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *victim, struct obj_data *tar_obj );
void cast_blindness( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_curse( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_sleep( byte level, struct char_data *ch, char *arg, int type,
    struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_armor( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_bless( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_cure_light( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj );
/* Dragon breath .. */
void cast_fire_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_frost_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_acid_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_gas_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj );
void cast_lightning_breath( byte level, struct char_data *ch, char *arg,
	       int type, struct char_data *tar_ch,
	       struct obj_data *tar_obj );


/* Data declarations */

struct social_type
{
  char *cmd;
  int next_line;
};


/* ********************************************************************
*  Special procedures for rooms                                       *
******************************************************************** */

char *how_good(int percent)
{
    if (percent == 0)
	return ( " (not learned)");
    if (percent <= 10)
	return ( " (awful)");
    if (percent <= 20)
	return ( " (bad)");
    if (percent <= 40)
	return ( " (poor)");
    if (percent <= 55)
	return ( " (average)");
    if (percent <= 70)
	return ( " (fair)");
    if (percent <= 80)
	return ( " (good)");
    if (percent <= 85)
	return ( " (very good)");

    return ( " (Superb)");
}

int guild(struct char_data *ch, int cmd, char *arg)
{

  char buf[MAX_STRING_LENGTH];
  int nnumber, number, i, percent;

  extern char *spells[];
  extern struct spell_info_type spell_info[MAX_SPL_LIST];
  extern struct int_app_type int_app[26];

  static char *nw_skills[] = {
    "secondattack",
    "disarm",
    "thirdattack",
    "parry",
    "\n"
    };

  static char *nt_skills[] = {
    "trip",
    "dodge",
    "dual",
    "disarm",
    "\n"
    };
  
  static char *w_skills[] = {
    "kick",  /* No. 50 */
    "bash",
    "rescue",
    "\n"
    };

  static char *t_skills[] = {
    "sneak",   /* No. 45 */
    "hide",
    "steal",
    "backstab",
    "pick",
    "\n"
    };

#if 0
  static char *ex_skills[] = {
    "recall",
    "/n"
    };
#endif
  
  if ((cmd != 164) && (cmd != 170)) return(FALSE);
  
  for(; *arg==' '; arg++);
  
  switch (GET_CLASS(ch)) {
  case CLASS_MAGIC_USER :{
    if (!*arg) {
      sprintf(buf,"You have got %d practice sessions left.\n\r",
	ch->specials.practices);
      send_to_char(buf, ch);
      send_to_char("You can practice any of these spells:\n\r", ch);
      for(i=0; *spells[i] != '\n'; i++)
    if (spell_info[i+1].spell_pointer &&
	(spell_info[i+1].min_level_magic <= GET_LEVEL(ch))) {
      sprintf(buf," %20s",spells[i]);
      send_to_char(buf, ch);
      sprintf(buf,"%14s",how_good(ch->skills[i+1].learned));
      send_to_char(buf, ch);
      sprintf(buf," %4d",use_mana(ch,i+1));
      send_to_char(buf, ch);
      send_to_char("\n\r", ch);
    }
      return(TRUE);
    }

    number = old_search_block(arg,0,strlen(arg),spells,FALSE);
    if(number == -1) {
      send_to_char("You do not know of this spell...\n\r", ch);
      return(TRUE);
    }
    if (GET_LEVEL(ch) < spell_info[number].min_level_magic) {
      send_to_char("You do not know of this spell...\n\r", ch);
      return(TRUE);
    }
    if (ch->specials.practices <= 0) {
      send_to_char("You do not seem to be able to practice now.\n\r", ch);
      return(TRUE);
    }
    if (ch->skills[number].learned >= 95) {
      send_to_char("You are already learned in this area.\n\r", ch);
      return(TRUE);
    }
    
    send_to_char("You Practice for a while...\n\r", ch);
    ch->specials.practices--;
    
    percent = ch->skills[number].learned+MAX(25,int_app[GET_INT(ch)].learn);
    ch->skills[number].learned = MIN(95, percent);
    
    if (ch->skills[number].learned >= 95) {
      send_to_char("You are now learned in this area.\n\r", ch);
      return(TRUE);
    }
    
  } break;

  case CLASS_THIEF: {
    if (!*arg) {
      sprintf(buf,"You have got %d practice sessions left.\n\r",
      ch->specials.practices);
      send_to_char(buf, ch);
      send_to_char("You can practise any of these skills:\n\r", ch);
      for(i=0; *t_skills[i] != '\n';i++) {
    send_to_char(t_skills[i], ch);
    send_to_char(how_good(ch->skills[i+45].learned), ch);
    send_to_char("\n\r", ch);
      }
      for(i=0; *nt_skills[i] != '\n';i++) {
    send_to_char(nt_skills[i], ch);
    send_to_char(how_good(ch->skills[i+SKILL_TRIP].learned), ch);
    send_to_char("\n\r", ch);
      }
      return(TRUE);
    }
    number = search_block(arg,t_skills,FALSE);
    nnumber = search_block(arg,nt_skills, FALSE);
    
    if((number == -1) && (nnumber == -1)) {
      send_to_char("You do not know of this skill...\n\r", ch);
      return(TRUE);
    }
    if (ch->specials.practices <= 0) {
      send_to_char("You do not seem to be able to practice now.\n\r", ch);
      return(TRUE);
    }
    if (nnumber == -1)
      {
    if (ch->skills[number+SKILL_SNEAK].learned >= 90) {
      send_to_char("You are already learned in this area.\n\r", ch);
      return(TRUE);
    }
    send_to_char("You Practice for a while...\n\r", ch);
    ch->specials.practices--;
    
    percent = ch->skills[number+SKILL_SNEAK].learned +
      MIN(int_app[GET_INT(ch)].learn, 12);
    ch->skills[number+SKILL_SNEAK].learned = MIN(90, percent);
    
    if (ch->skills[number+SKILL_SNEAK].learned >= 90) {
      send_to_char("You are now learned in this area.\n\r", ch);
      return(TRUE);
    }
      } else
    {
	if (ch->skills[nnumber+SKILL_TRIP].learned >= 90) {
	  send_to_char("You are already learned in this area.\n\r", ch);
	  return(TRUE);
	}
	send_to_char("You Practice for a while...\n\r", ch);
	ch->specials.practices--;

	percent = ch->skills[nnumber+SKILL_TRIP].learned +
	  MIN(int_app[GET_INT(ch)].learn, 12);
	ch->skills[nnumber+SKILL_TRIP].learned = MIN(90, percent);

	if (ch->skills[nnumber+SKILL_TRIP].learned >= 90) {
	  send_to_char("You are now learned in this area.\n\r", ch);
	  return(TRUE);
    }
      }
    
  } break;
    
  case CLASS_CLERIC     :{
    if (!*arg) {
      sprintf(buf,"You have got %d practice sessions left.\n\r",
      ch->specials.practices);
      send_to_char(buf, ch);
      send_to_char("You can practise any of these spells:\n\r", ch);
      for(i=0; *spells[i] != '\n'; i++)
    if (spell_info[i+1].spell_pointer &&
	(spell_info[i+1].min_level_cleric <= GET_LEVEL(ch))) {
      sprintf(buf," %20s ",spells[i]);
      send_to_char(buf, ch);
      sprintf(buf,"%14s",how_good(ch->skills[i+1].learned));
      send_to_char(buf, ch);
      sprintf(buf," %4d",use_mana(ch,i+1));
      send_to_char(buf, ch);
      send_to_char("\n\r", ch);
    }
      return(TRUE);
    }
    number = old_search_block(arg,0,strlen(arg),spells,FALSE);
    if(number == -1) {
      send_to_char("You do not know of this spell...\n\r", ch);
      return(TRUE);
    }
    if (GET_LEVEL(ch) < spell_info[number].min_level_cleric) {
      send_to_char("You do not know of this spell...\n\r", ch);
      return(TRUE);
    }
    if (ch->specials.practices <= 0) {
      send_to_char("You do not seem to be able to practice now.\n\r", ch);
      return(TRUE);
    }
    if (ch->skills[number].learned >= 95) {
      send_to_char("You are already learned in this area.\n\r", ch);
      return(TRUE);
    }
    send_to_char("You Practice for a while...\n\r", ch);
    ch->specials.practices--;
    
    percent = ch->skills[number].learned+MAX(25,int_app[GET_INT(ch)].learn);
    ch->skills[number].learned = MIN(95, percent);
    
    if (ch->skills[number].learned >= 95) {
      send_to_char("You are now learned in this area.\n\r", ch);
      return(TRUE);
    }
  } break;
    
  case CLASS_WARRIOR: {
    if (!*arg) {
      sprintf(buf,"You have got %d practice sessions left.\n\r",
      ch->specials.practices);
      send_to_char(buf, ch);
      send_to_char("You can practise any of these skills:\n\r", ch);
      for(i=0; *w_skills[i] != '\n';i++) {
    send_to_char(w_skills[i], ch);
    send_to_char(how_good(ch->skills[i+SKILL_KICK].learned), ch);
    send_to_char("\n\r", ch);
      }
      for(i=0; *nw_skills[i] != '\n';i++) {
    send_to_char(nw_skills[i],ch);
    send_to_char(how_good(ch->skills[i+SKILL_SECOND_ATTACK].learned), ch);
    send_to_char("\n\r", ch);
      }
      return(TRUE);
    }
    number = search_block(arg, w_skills, FALSE);
    nnumber = search_block(arg, nw_skills, FALSE);
    
    if((number == -1) && (nnumber == -1)) {
      send_to_char("You do not have ability to practise this skill!\n\r", ch);
      return(TRUE);
    }
    if (ch->specials.practices <= 0) {
      send_to_char("You do not seem to be able to practice now.\n\r", ch);
      return(TRUE);
    }
    if (nnumber == -1)
      {
    if (ch->skills[number+SKILL_KICK].learned >= 85) {
      send_to_char("You are already learned in this area.\n\r", ch);
      return(TRUE);
    }
    send_to_char("You Practice for a while...\n\r", ch);
    ch->specials.practices--;
    
    percent = ch->skills[number+SKILL_KICK].learned +
      MIN(12, int_app[GET_INT(ch)].learn);
    ch->skills[number+SKILL_KICK].learned = MIN(85, percent);
    
    if (ch->skills[number+SKILL_KICK].learned >= 85) {
      send_to_char("You are now learned in this area.\n\r", ch);
      return(TRUE);
    }
      } else
    {
	if (ch->skills[nnumber+SKILL_SECOND_ATTACK].learned >= 85) {
	  send_to_char("You are already learned in this area.\n\r", ch);
	  return(TRUE);
	}
	send_to_char("You Practice for a while...\n\r", ch);
	ch->specials.practices--;

	percent = ch->skills[nnumber+SKILL_SECOND_ATTACK].learned +
	  MIN(12, int_app[GET_INT(ch)].learn);
	ch->skills[nnumber+SKILL_SECOND_ATTACK].learned = MIN(85, percent);

	if (ch->skills[nnumber+SKILL_SECOND_ATTACK].learned >= 85) {
	  send_to_char("You are now learned in this area.\n\r", ch);
	  return(TRUE);
    }
      }
  } break;
  }
  return (TRUE);
}



int train(struct char_data *ch, int cmd, char *arg)
{
    char    buf[256];
    sbyte   *pAbility       = NULL;
    sbyte   *pTmpAbility    = NULL;
    int     cost            = 5;


    /*
     * Check for right command.
     * Strip white space on arg.
     */
    if ( cmd != 165 )
	return FALSE;

    while ( *arg == ' ' )
	arg++;

    if ( *arg == '\0' )
    {
	sprintf( buf, "You have %d practice sessions left.\n\r",
	    ch->specials.practices );
	send_to_char( buf, ch );
	arg = "foo";
    }

    if ( !str_cmp( arg, "str" ) )
    {
	if ( GET_CLASS(ch) == CLASS_WARRIOR )
	    cost    = 3;
	pAbility    = &ch->abilities.str;
	pTmpAbility = &ch->tmpabilities.str;
    }

    else if ( !str_cmp( arg, "int" ) )
    {
	if ( GET_CLASS(ch) == CLASS_MAGIC_USER )
	    cost    = 3;
	pAbility    = &ch->abilities.intel;
	pTmpAbility = &ch->tmpabilities.intel;
    }

    else if ( !str_cmp( arg, "wis" ) )
    {
	if ( GET_CLASS(ch) == CLASS_CLERIC )
	    cost    = 3;
	pAbility    = &ch->abilities.wis;
	pTmpAbility = &ch->tmpabilities.wis;
    }

    else if ( !str_cmp( arg, "con" ) )
    {
	pAbility    = &ch->abilities.con;
	pTmpAbility = &ch->tmpabilities.con;
    }

    else if ( !str_cmp( arg, "dex" ) )
    {
	if ( GET_CLASS(ch) == CLASS_THIEF )
	    cost    = 3;
	pAbility    = &ch->abilities.dex;
	pTmpAbility = &ch->tmpabilities.dex;
    }

    else
    {
	send_to_char( "You can train in: str int wis con dex.\n\r", ch );
	return TRUE;
    }

    if ( cost > ch->specials.practices )
    {
	send_to_char( "You don't have enough practices.\n\r", ch );
	return TRUE;
    }

    if ( *pAbility >= 18 || *pTmpAbility >= 18 )
    {
	send_to_char( "That ability is already at maximum.\n\r", ch );
	return TRUE;
    }

    ch->specials.practices    -= cost;
    *pAbility                 += 1;
    *pTmpAbility                    += 1;
    send_to_char( "Your ability increases!\n\r", ch );

    return TRUE;
}




int mayor(struct char_data *ch, int cmd, char *arg)
{
  static char open_path[] =
    "W3a3003b33000c111d0d111Oe333333Oe22c222112212111a1S.";

  static char close_path[] =
    "W3a3003b33000c111d0d111CE333333CE22c222112212111a1S.";

  static char *path;
  static int index;
  static bool move = FALSE;

  void do_move(struct char_data *ch, char *argument, int cmd);
  void do_open(struct char_data *ch, char *argument, int cmd);
  void do_lock(struct char_data *ch, char *argument, int cmd);
  void do_unlock(struct char_data *ch, char *argument, int cmd);
  void do_close(struct char_data *ch, char *argument, int cmd);


  if (!move) {
	if (time_info.hours == 6) {
      move = TRUE;
      path = open_path;
	    index = 0;
    } else if (time_info.hours == 20) {
      move = TRUE;
      path = close_path;
	    index = 0;
    }
  }

    if (cmd || !move || (GET_POS(ch) < POSITION_SLEEPING) ||
	(GET_POS(ch) == POSITION_FIGHTING))
	return FALSE;

  switch (path[index]) {
    case '0' :
    case '1' :
    case '2' :
    case '3' :
      do_move(ch,"",path[index]-'0'+1);
      break;

	case 'W' :
	    GET_POS(ch) = POSITION_STANDING;
	    act("$n awakens and groans loudly.",
		FALSE,ch,0,0,TO_ROOM);
	    break;

	case 'S' :
	    GET_POS(ch) = POSITION_SLEEPING;
	    act("$n lies down and instantly falls asleep.",
		FALSE,ch,0,0,TO_ROOM);
	    break;

    case 'a' :
      act("$n says 'Hello Honey!'",FALSE,ch,0,0,TO_ROOM);
      act("$n smirks.",FALSE,ch,0,0,TO_ROOM);
      break;

    case 'b' :
      act("$n says 'What a view! I must get something done about that dump!'",
	FALSE,ch,0,0,TO_ROOM);
      break;

    case 'c' :
      act(
      "$n says 'Vandals! Youngsters nowadays have no respect for anything!'",
	FALSE,ch,0,0,TO_ROOM);
      break;

    case 'd' :
      act("$n says 'Good day, citizens!'", FALSE, ch, 0,0,TO_ROOM);
      break;

    case 'e' :
      act("$n says 'I hereby declare the bazaar open!'",FALSE,ch,0,0,TO_ROOM);
      break;

    case 'E' :
      act("$n says 'I hereby declare Midgaard closed!'",FALSE,ch,0,0,TO_ROOM);
      break;

    case 'O' :
      do_unlock(ch, "gate", 0);
      do_open(ch, "gate", 0);
      break;

    case 'C' :
      do_close(ch, "gate", 0);
      do_lock(ch, "gate", 0);
      break;

    case '.' :
      move = FALSE;
      break;

  }

  index++;
  return FALSE;
}

/* ********************************************************************
*  General special procedures for mobiles                                      *
******************************************************************** */

/* SOCIAL GENERAL PROCEDURES

If first letter of the command is '!' this will mean that the following
command will be executed immediately.

"G",n      : Sets next line to n
"g",n      : Sets next line relative to n, fx. line+=n
"m<dir>",n : move to <dir>, <dir> is 0,1,2,3,4 or 5
"w",n      : Wake up and set standing (if possible)
"c<txt>",n : Look for a person named <txt> in the room
"o<txt>",n : Look for an object named <txt> in the room
"r<int>",n : Test if the npc in room number <int>?
"s",n      : Go to sleep, return false if can't go sleep
"e<txt>",n : echo <txt> to the room, can use $o/$p/$N depending on
	     contents of the **thing
"E<txt>",n : Send <txt> to person pointed to by thing
"B<txt>",n : Send <txt> to room, except to thing
"?<num>",n : <num> in [1..99]. A random chance of <num>% success rate.
	     Will as usual advance one line upon sucess, and change
	     relative n lines upon failure.
"O<txt>",n : Open <txt> if in sight.
"C<txt>",n : Close <txt> if in sight.
"L<txt>",n : Lock <txt> if in sight.
"U<txt>",n : Unlock <txt> if in sight.    */

/* Execute a social command.                                        */
void exec_social(struct char_data *npc, char *cmd, int next_line,
		 int *cur_line, void **thing)
{
  bool ok;

  void do_move(struct char_data *ch, char *argument, int cmd);
  void do_open(struct char_data *ch, char *argument, int cmd);
  void do_lock(struct char_data *ch, char *argument, int cmd);
  void do_unlock(struct char_data *ch, char *argument, int cmd);
  void do_close(struct char_data *ch, char *argument, int cmd);

  if (GET_POS(npc) == POSITION_FIGHTING)
    return;

  ok = TRUE;

  switch (*cmd) {

    case 'G' :
      *cur_line = next_line;
      return;

    case 'g' :
      *cur_line += next_line;
      return;

    case 'e' :
      act(cmd+1, FALSE, npc, *thing, *thing, TO_ROOM);
      break;

    case 'E' :
      act(cmd+1, FALSE, npc, 0, *thing, TO_VICT);
      break;

    case 'B' :
      act(cmd+1, FALSE, npc, 0, *thing, TO_NOTVICT);
      break;

    case 'm' :
      do_move(npc, "", *(cmd+1)-'0'+1);
      break;

    case 'w' :
      if (GET_POS(npc) != POSITION_SLEEPING)
	ok = FALSE;
      else
	GET_POS(npc) = POSITION_STANDING;
      break;

    case 's' :
      if (GET_POS(npc) <= POSITION_SLEEPING)
	ok = FALSE;
      else
	GET_POS(npc) = POSITION_SLEEPING;
      break;

    case 'c' :  /* Find char in room */
      *thing = get_char_room_vis(npc, cmd+1);
      ok = (*thing != 0);
      break;

    case 'o' : /* Find object in room */
      *thing = get_obj_in_list_vis(npc, cmd+1, world[npc->in_room].contents);
      ok = (*thing != 0);
      break;

    case 'r' : /* Test if in a certain room */
      ok = (npc->in_room == atoi(cmd+1));
      break;

    case 'O' : /* Open something */
      do_open(npc, cmd+1, 0);
      break;

    case 'C' : /* Close something */
      do_close(npc, cmd+1, 0);
      break;

    case 'L' : /* Lock something  */
      do_lock(npc, cmd+1, 0);
      break;

    case 'U' : /* UnLock something  */
      do_unlock(npc, cmd+1, 0);
      break;

    case '?' : /* Test a random number */
      if (atoi(cmd+1) <= number(1,100))
	ok = FALSE;
      break;

    default:
      break;
  }  /* End Switch */

  if (ok)
    (*cur_line)++;
  else
    (*cur_line) += next_line;
}



void npc_steal(struct char_data *ch,struct char_data *victim)
{
    int gold;

    if(IS_NPC(victim)) return;
    if(GET_LEVEL(victim)>20) return;

    if (AWAKE(victim) && (number(0,GET_LEVEL(ch)) == 0)) {
	act("You discover that $n has $s hands in your wallet.",
	    FALSE,ch,0,victim,TO_VICT);
	act("$n tries to steal gold from $N.",TRUE, ch, 0, victim, TO_NOTVICT);
    } else {
	/* Steal some gold coins */
	gold = (int) ((GET_GOLD(victim)*number(1,10))/100);
	if (gold > 0) {
	    GET_GOLD(ch) += gold;
	    GET_GOLD(victim) -= gold;
	}
    }
}


int snake(struct char_data *ch, int cmd, char *arg)
{
    void cast_poison( byte level, struct char_data *ch, char *arg, int type,
      struct char_data *tar_ch, struct obj_data *tar_obj );

   if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if ( ch->specials.fighting && 
	(ch->specials.fighting->in_room == ch->in_room) &&
	number(0 , 99) < 2 * GET_LEVEL(ch) )
	{
	    act("You bite $N!", 1, ch, 0, ch->specials.fighting, TO_CHAR);
	    act("$n bites $N!", 1, ch, 0, ch->specials.fighting, TO_NOTVICT);
	    act("$n bites you!", 1, ch, 0, ch->specials.fighting, TO_VICT);
	    cast_poison( GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL,
		 ch->specials.fighting, 0);
	    return TRUE;
	}
    return FALSE;
}

int thief(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *cons;

   if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_STANDING)return FALSE;

    for(cons = world[ch->in_room].people; cons; cons = cons->next_in_room )
	if((!IS_NPC(cons)) && (GET_LEVEL(cons)<32) && (number(1,5)==1))
	    npc_steal(ch,cons); 

    return TRUE;
}

int magic_user(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;


    /* Find a dude to do evil things upon ! */

    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room )
	if (vict->specials.fighting==ch && number(0,2)==0)
	    break;

    if (!vict)
	return FALSE;


    if( vict!=ch->specials.fighting && GET_LEVEL(ch)>13 && number(0,7)==0 )
    {
	act("$n utters the words 'dilan oso'.", 1, ch, 0, 0, TO_ROOM);
	cast_sleep(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	return TRUE;
    }

    if( (GET_LEVEL(ch)>12) && (number(0,6)==0) )
    {
	act("$n utters the words 'gharia miwi'.", 1, ch, 0, 0, TO_ROOM);
	cast_curse(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	return TRUE;
    }

    if( (GET_LEVEL(ch)>7) && (number(0,5)==0) )
    {
	act("$n utters the words 'koholian dia'.", 1, ch, 0, 0, TO_ROOM);
	cast_blindness(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	return TRUE;
    }

    if( (GET_LEVEL(ch)>12) && (number(0,8)==0) && IS_EVIL(ch))
    {
	act("$n utters the words 'ib er dranker'.", 1, ch, 0, 0, TO_ROOM);
	cast_energy_drain(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	return TRUE;
    }

    switch (GET_LEVEL(ch)) {
	case 1:
	case 2:
	case 3:
	case 4:
	    act("$n utters the words 'hahili duvini'.", 1, ch, 0, 0, TO_ROOM);
	    cast_magic_missile(
		GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	    break;
	case 5:
	case 6:
	case 7:
	case 8:
	    act("$n utters the words 'grynt oef'.", 1, ch, 0, 0, TO_ROOM);
	    cast_burning_hands(
		GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	    break;
	case 9:
	case 10:
	    act("$n utters the words 'sjulk divi'.", 1, ch, 0, 0, TO_ROOM);
	    cast_lightning_bolt(
		GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	    break;
	case 11:
	case 12:
	case 13:
	case 14:
	    act("$n utters the words 'nasson hof'.", 1, ch, 0, 0, TO_ROOM);
	    cast_colour_spray(
		GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	    break;
	default:
	    act("$n utters the words 'tuborg'.", 1, ch, 0, 0, TO_ROOM);
	    cast_fireball(
		GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	    break;
    }
    return TRUE;
}

int Thalos_citizen(struct char_data *ch, int cmd, char *arg)
{
  void do_say(struct char_data *ch, char *argument, int cmd);
  struct char_data *vict;

  if (!AWAKE(ch))
    return FALSE;

  for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
    if (vict->specials.fighting==ch && number(0,1)==0)
      break;

  if (!vict)
    return FALSE;
  
  switch (number(0,20))
    {
    case 0 :  do_say(ch, "Thalos must be the safest city around.", 0);
      return TRUE;
    case 1 :  do_say(ch, "Don't you just love these lamia pets?", 0);
      do_say(ch, "They must be god's gift to man.", 0);
      return TRUE;
    case 2 :  do_say(ch, "Hello, neighbor.  How's the weather?", 0);
      return TRUE;
    case 3 :  do_say(ch, "Thalos is built to last.  Don't you think?", 0);
      return TRUE;
    case 4 :  do_say(ch, "Our lamia pets will do anything.", 0);
      do_say(ch, "Make our beds, serv our meals, wash the dishes,...", 0);
      return TRUE;
    case 5 :  do_say(ch, "Have you seen the cute little beholder in", 0);
      do_say(ch, "the temple.  He's so cuuuute!", 0);
      return TRUE;
    case 6 :  do_say(ch, "Oh, don't worry about the old man at the", 0);
      do_say(ch, "guild house.  He's insane.", 0);
      return TRUE;
    case 7 :  do_say(ch, "That's a mighty big weapon you have there.", 0);
      do_say(ch, "Off to hunt a bear?", 0);
      return TRUE;
      default :  return FALSE;
    }
}

int baby_troll(struct char_data *ch, int cmd, char *arg)
{
  struct char_data *vict;

  void do_say(struct char_data *ch, char *argument, int cmd);

  if (cmd) return FALSE;
  if (!AWAKE(ch))
    return FALSE;

  if (!ch->specials.fighting) {
    
    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
      if (number(0,1)==0)
    break;

    if (!vict)
      return FALSE;

    switch (number(0,15))
    {
      case 1 :
	act( "The baby troll says, 'Wana play?'",TRUE, vict, 0, 0, TO_ROOM);
	break;
      case 2 :
	act("The baby troll says, 'Come sit down and play with us.'",
		TRUE, vict, 0, 0, TO_ROOM);
	break;
      case 3 :
	act("The baby troll throws something greasy and grimey at $n!",\
	    TRUE, vict, 0, 0, TO_ROOM);
	act("The baby troll throws something greasy and grimey at you!",
	    TRUE,vict,0,0,TO_CHAR);
	break;
      default:
	return FALSE;
    }
  }
  
  return FALSE;
}

int Fanatic_Hector(struct char_data *ch, int cmd, char *arg)
{
  struct char_data *vict;

  void do_say(struct char_data *ch, char *argument, int cmd);
  void do_emote(struct char_data *ch, char *argument, int cmd);

  if (cmd || !AWAKE(ch))
    return FALSE;

  if (ch->specials.fighting)
    return TRUE;

  for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
    if (number(0,1)==0)
      break;

  if (!vict)
    return FALSE;

  switch (number(0,15))
    {
    case 1 :  do_say(ch, "The end of the world is comming!  Beware!", 0);
      return TRUE;
    case 2 :  do_say(ch, "To arms!  To arms!  Darkness is here!", 0);
      return TRUE;
    case 3 :  do_emote(ch,
	"waves his right fist covered in golden silk at you.", 0);
      return TRUE;
    case 4 :  do_emote(ch, "spits on the banner of Thalos with disgust.", 0);
      return TRUE;
    default:
	return FALSE;
    }
}

int Executioner(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *tch;
    struct char_data *mob;
    char buf[MAX_INPUT_LENGTH];
    char *strName;

    if (cmd || !AWAKE(ch))
	return FALSE;

    for ( tch = world[ch->in_room].people; tch; tch = tch->next_in_room )
    {
	if ( IS_SET(tch->specials.affected_by, AFF_KILLER) )
	    strName = "KILLER";
	else if ( IS_SET(tch->specials.affected_by, AFF_THIEF) )
	    strName = "THIEF";
	else
	    continue;

	sprintf( buf,
	    "%s is a %s!  PROTECT THE INNOCENT!  MORE BLOOOOD!!!",
	    GET_NAME(tch),
	    strName );
	do_shout( ch, buf, 0 );
	hit( ch, tch, TYPE_UNDEFINED );
	mob = read_mobile( real_mobile(3060), REAL );
	char_to_room( mob, ch->in_room );
	mob = read_mobile( real_mobile(3060), REAL );
	char_to_room( mob, ch->in_room );
	break;
    }

    return FALSE;
}



int red_dragon(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    return FALSE;

    if (cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;

    /* Find a dude to do evil things upon ! */

    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room )
	if (vict->specials.fighting==ch && number(0,1)==0){
	  act("$n breathes fire.",1, ch, 0, 0, TO_ROOM);
	  cast_fire_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
	}

    if (!vict)
      if (number(0,1) == 0){
	act("$n breathes fire.",1, ch, 0, 0, TO_ROOM);
	cast_fire_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL,
		 ch->specials.fighting, 0);
      }

    return TRUE;
}

int white_dragon(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    return FALSE;

    if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;

    /* Find a dude to do evil things upon ! */
    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room )
		if (vict->specials.fighting==ch && number(0,1)==0){
	  act("$n breathes frost.",1, ch, 0, 0, TO_ROOM);
	  cast_frost_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);
		}

	if (!vict)
	  if (number(0,1) == 0){
	act("$n breathes frost.",1, ch, 0, 0, TO_ROOM);
	cast_frost_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL,
		  ch->specials.fighting, 0);
	  }

    return TRUE;
}

int black_dragon(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    return FALSE;

    if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;

    /* Find a dude to do evil things upon ! */

    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room )
	if (vict->specials.fighting==ch && number(0,2)==0)
	    break;

    if (!vict)
    {
      if (number(0,1) == 0)
	{
	vict = ch->specials.fighting;
	if (vict == NULL)
	  return FALSE;
      }
      else
	return FALSE;
    }

    act("$n breathes acid.",1, ch, 0, 0, TO_ROOM);
    cast_acid_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);

    return TRUE;
}

int blue_dragon(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    return FALSE;

    if(cmd) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;

    /* Find a dude to do evil things upon ! */

    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
	if (vict->specials.fighting==ch && number(0,2)==0)
	    break;

    if (!vict)
    {
      if (number(0,1) == 0)
	{
	vict = ch->specials.fighting;
	if (vict == NULL)
	  return FALSE;
      }     
      else
	return FALSE;
    }

    act("$n breathes lightning.",1, ch, 0, 0, TO_ROOM);
    cast_lightning_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);

    return TRUE;
}

int green_dragon(struct char_data *ch, int cmd, char *arg)
{
    return FALSE;

    if ( cmd ) return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;
    
    if(!ch->specials.fighting) return FALSE;

    if(number(0,1)==0) return FALSE;

    act("$n breathes gas.",1, ch, 0, 0, TO_ROOM);
    cast_gas_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, 0, 0);

    return TRUE;
}

int brass_dragon(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *vict;

    return FALSE;

    if ( cmd == 4 && ch->in_room == real_room(5065) )
    {
	act( "The brass dragon says '$n isn't invited'",
	    FALSE, ch, 0, 0, TO_ROOM );
	send_to_char( "The brass dragon says 'you're not invited'\n\r", ch );
	return TRUE;
    }

    if ( cmd )
	return FALSE;

    if(GET_POS(ch)!=POSITION_FIGHTING) return FALSE;

    if (!ch->specials.fighting) return FALSE;

    if (number(0,1)==0)
    {
	act("$n breathes gas.",1,ch, 0, 0, TO_ROOM);
	cast_gas_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, 0, 0);
	return TRUE;
    }

    for (vict = world[ch->in_room].people; vict; vict = vict->next_in_room)
	if (vict->specials.fighting==ch && number(0,1)==0)
	    break;

    if (!vict)
    {
	if (number(0,1) == 0)
	{
	    vict = ch->specials.fighting;
	    if (vict == NULL)
		return FALSE;
	}
	else
	    return FALSE;
    }

    act("$n breathes lightning.",1, ch, 0, 0, TO_ROOM);
    cast_lightning_breath(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, vict, 0);

    return TRUE;

}
  

/* ********************************************************************
*  Special procedures for mobiles                                      *
******************************************************************** */

int guild_guard(struct char_data *ch, int cmd, char *arg)
{
    if (cmd>6 || cmd<1)
	return FALSE;

    if ( ( GET_CLASS(ch) != CLASS_MAGIC_USER
	&& ch->in_room == real_room(3017) && cmd == 3 )
    ||   ( GET_CLASS(ch) != CLASS_CLERIC
	&& ch->in_room == real_room(3004) && cmd == 1 )
    ||   ( GET_CLASS(ch) != CLASS_THIEF
	&& ch->in_room == real_room(3027) && cmd == 2 )
    ||   ( GET_CLASS(ch) != CLASS_WARRIOR
	&& ch->in_room == real_room(3021) && cmd == 2 )
	)
    {
	act( "The guard humiliates $n, and blocks $s way.",
	    FALSE, ch, 0, 0, TO_ROOM );
	send_to_char(
	    "The guard humiliates you, and blocks your way.\n\r", ch );
	return TRUE;
    }

    return FALSE;

}

int puff(struct char_data *ch, int cmd, char *arg)
{
    void do_say(struct char_data *ch, char *argument, int cmd);

    if (cmd)
	return(0);

    switch (number(0, 12))
    {
	case 5:
	    do_say(ch, "My god! It's full of stars!", 0);
	   return(1);
	case 2:
	    do_say(ch, "How'd all those fish get up here?", 0);
	    return(1);
	case 8:
	    do_say(ch, "I'm a very female dragon.", 0);
	    return(1);
	case 9:
	    do_say(ch, "I've got a peaceful, easy feeling.", 0);
	    return(1);
	default:
	    return(0);
    }
}
		    
int fido(struct char_data *ch, int cmd, char *arg)
{

    struct obj_data *i, *temp, *next_obj;

    if (cmd || !AWAKE(ch))
	return(FALSE);

    for (i = world[ch->in_room].contents; i; i = i->next_content) {
	if (GET_ITEM_TYPE(i)==ITEM_CONTAINER && i->obj_flags.value[3]) {
	    act("$n savagely devours a corpse.", FALSE, ch, 0, 0, TO_ROOM);
	    for(temp = i->contains; temp; temp=next_obj)
	    {
		next_obj = temp->next_content;
		obj_from_obj(temp);
		obj_to_room(temp,ch->in_room);
	    }
	    extract_obj(i);
	    return(TRUE);
	}
    }
    return(FALSE);
}



int janitor(struct char_data *ch, int cmd, char *arg)
{
    struct obj_data *i;

    if (cmd || !AWAKE(ch))
	return(FALSE);

    for (i = world[ch->in_room].contents; i; i = i->next_content) {
	if (IS_SET(i->obj_flags.wear_flags, ITEM_TAKE) && 
      ((i->obj_flags.type_flag == ITEM_DRINKCON) ||
	  (i->obj_flags.cost <= 10))) {
	    act("$n picks up some trash.", FALSE, ch, 0, 0, TO_ROOM);

	    obj_from_room(i);
	    obj_to_char(i, ch);
	    return(TRUE);
	}
    }
    return(FALSE);
}

int cityguard(struct char_data *ch, int cmd, char *arg)
{
    struct char_data *tch, *evil;
    int max_evil;
    char buf[100];

    if (cmd || !AWAKE(ch) || (GET_POS(ch) == POSITION_FIGHTING))
	return (FALSE);

    max_evil = 300;
    evil = 0;

    for (tch=world[ch->in_room].people; tch; tch = tch->next_in_room) {
      if(IS_SET(tch->specials.affected_by, AFF_KILLER)) {
	sprintf(buf,
 "%s is a KILLER! PROTECT THE INNOCENT!  BANZAI!!! CHARGE!!! ARARARAGGGHH!",
     GET_NAME(tch));
	do_shout(ch, buf, 0);
	hit(ch, tch, TYPE_UNDEFINED);
	return (TRUE);
      } else
	if (IS_SET(tch->specials.affected_by, AFF_THIEF)) {
	  sprintf(buf,
 "%s is a THIEF! PROTECT THE INNOCENT!  BANZAI!!! CHARGE!!! ARARARAGGGHH!",
     GET_NAME(tch));
	  do_shout(ch, buf, 0);
	  hit(ch, tch, TYPE_UNDEFINED);
	  return (TRUE);
	}
      if (tch->specials.fighting) {
	if ((GET_ALIGNMENT(tch) < max_evil) &&
	(IS_NPC(tch) || IS_NPC(tch->specials.fighting))) {
	  max_evil = GET_ALIGNMENT(tch);
	  evil = tch;
	}
      }
    }

    if (evil && !IS_EVIL(evil->specials.fighting))
    {
	act(
 "$n screams 'PROTECT THE INNOCENT!  BANZAI!!! CHARGE!!! ARARARAGGGHH!'",
     FALSE, ch, 0, 0, TO_ROOM);
	hit(ch, evil, TYPE_UNDEFINED);
	return(TRUE);
    }

    return(FALSE);
}



int adept(struct char_data *ch, int cmd, char *arg)
{
  struct char_data *tch;

  void do_say(struct char_data *ch, char *argument, int cmd);

  if (cmd || !AWAKE(ch))
    return(FALSE);
  
  for (tch = world[ch->in_room].people; tch; tch = tch->next_in_room)
    if(!IS_NPC(tch) && number (0,2) == 1 && CAN_SEE(ch,tch))
      break;
  
  if (!tch)
    return FALSE;
  
  switch (number (0,10))
    {
    case 3 :
      act("$n utters the words 'garf'.", 1, ch, 0, 0, TO_ROOM);
      cast_cure_light(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, tch, 0);
      return (1);
    case 7 :
      act("$n utters the words 'nahk'.", 1, ch, 0, 0, TO_ROOM);
      cast_bless(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, tch, 0);
      return (1);
    case 6 :
      act("$n utters the words 'tehctah'.", 1, ch, 0, 0, TO_ROOM);
      cast_armor(GET_LEVEL(ch), ch, "", SPELL_TYPE_SPELL, tch, 0);
      return (1);
    case 4 :
      do_say(ch,"Finish school.  Don't drop out.", 0);
      return (1);
    case 5 :
      do_say(ch,"Move it.  Others want to go to this school.", 0);
      return (1);
    default:
      return (0);
    }
}


int mud_school_adept(struct char_data *ch, int cmd, char *arg)
{
  struct char_data *tch;

  void do_say(struct char_data *ch, char *argument, int cmd);

  if (cmd)
    return (0);

  if (!AWAKE(ch))
    return (0);
  
  for (tch = world[ch->in_room].people; tch; tch = tch->next_in_room)
    if(!IS_NPC(tch) && number (0,2) == 1 && CAN_SEE(ch,tch))
      break;

  if (!tch)
    return (0);
  
  switch (number(0,20))
    {
    case 15 :
      do_say(ch,"What are you staring at?", 0);
      return(1);
    case 18 :
      do_say(ch,"Hi, I'm your friend.", 0);
      return(1);
    case 3 :
      do_say(ch,"Isn't this a fine school?", 0);
      return(1);
    case 12 :
      do_say(ch,"Finish school.  Dont drop out.", 0);
      return(1);
    case 5 :
      do_say(ch,"Move it.  Others want to go to this school.", 0);
      return(1);
    case 6 :
      do_say(ch,"Be careful, don't get killed by those monsters!", 0);
      return(1);
    case 7 :
      do_say(ch,"Don't forget to wear your clothes, young students!", 0);
      return(1);
    case 8 :
      do_say(ch,"What are you doing just STANDING there?!?!!?", 0);
      do_say(ch,"GET going!", 0);
      return(1);
    case 9 :
      do_say(ch,"Hello....Hello, are you listening to me?", 0);
      return(1);
    default:
      return(0);
    }
  
}



int MERCling(struct char_data *ch, int cmd, char *arg)
{
	void do_shout(struct char_data *ch, char *argument, int cmd);

	if (cmd)
		return(0);

	switch (number(0, 12))
	{
    case 0:
      do_shout(ch, "Happy Birthday to Hatchet!  Happy Birthday to me!", 0);
      return(1);
    case 1:
      do_shout(ch, "Happy Birthday to Kahn!  Happy Birthday to you!", 0);
      return(1);
    case 2:
      do_shout(ch, "Happy Birthday to Hatchet!  Happy Birthday to you!", 0);
      return(1);
    case 3:
      do_shout(ch, "Happy Birthday to Kahn!  Happy Birthday to me!", 0);
      return(1);
    default:
      return(0);
	}
}

/*********************************************************************
*  Special procedures for shops                                      *
*********************************************************************/

int pet_shops(struct char_data *ch, int cmd, char *arg)
{
    char buf[MAX_STRING_LENGTH], pet_name[256];
    int pet_room;
    struct char_data *pet;

    pet_room = ch->in_room+1;

    if (cmd==59) { /* List */
	send_to_char("Available pets are:\n\r", ch);
	for(pet = world[pet_room].people; pet; pet = pet->next_in_room) {
	    sprintf(buf, "%8d - %s\n\r",
		3*GET_EXP(pet), pet->player.short_descr);
	    send_to_char(buf, ch);
	}
	return(TRUE);
    } else if (cmd==56) { /* Buy */

	arg = one_argument(arg, buf);
	arg = one_argument(arg, pet_name);
	/* Pet_Name is for later use when I feel like it */

	if (!(pet = get_char_room(buf, pet_room))) {
	    send_to_char("There is no such pet!\n\r", ch);
	    return(TRUE);
	}

	if (GET_GOLD(ch) < (GET_EXP(pet)*3)) {
	    send_to_char("You don't have enough gold!\n\r", ch);
	    return(TRUE);
	}

	GET_GOLD(ch) -= GET_EXP(pet)*3;

	/*
	 * Should be some code here to defend against weird monsters
	 * getting loaded into the pet shop back room.  -- Furey
	 */
	pet = read_mobile(pet->nr, REAL);
	GET_EXP(pet) = 0;
	SET_BIT(pet->specials.affected_by, AFF_CHARM);

	if (*pet_name) {
	    sprintf(buf,"%s %s", pet->player.name, pet_name);
	    free(pet->player.name);
	    pet->player.name = str_dup(buf);     

	    sprintf( buf,
	"%sA small sign on a chain around the neck says 'My Name is %s'\n\r",
	      pet->player.description, pet_name);
	    free(pet->player.description);
	    pet->player.description = str_dup(buf);
	}

	char_to_room(pet, ch->in_room);
	add_follower(pet, ch);

	/* Be certain that pet's can't get/carry/use/weild/wear items */
	IS_CARRYING_W(pet) = 1000;
	IS_CARRYING_N(pet) = 100;

	send_to_char("May you enjoy your pet.\n\r", ch);
	act("$n bought $N as a pet.",FALSE,ch,0,pet,TO_ROOM);

	return(TRUE);
    }

    /* All commands except list and buy */
    return(FALSE);
}


/* Idea of the LockSmith is functionally similar to the Pet Shop */
/* The problem here is that each key must somehow be associated  */
/* with a certain player. My idea is that the players name will  */
/* appear as the another Extra description keyword, prefixed     */
/* by the words 'item_for_' and followed by the player name.     */
/* The (keys) must all be stored in a room which is (virtually)  */
/* adjacent to the room of the lock smith.                       */


/* ********************************************************************
*  Special procedures for objects                                     *
******************************************************************** */